基于Linux的沙箱评测系统内核的设计与实现
2022-08-29王硕郑晓东张强
王硕,郑晓东,张强
(齐齐哈尔大学 计算机与控制工程学院,黑龙江 齐齐哈尔 161006)
0 引 言
在线代码评测系统是一种在程序设计竞赛中用于检测源代码正确性的在线系统。在评测系统中,用户提交恶意代码导致的服务器文件系统损坏、数据泄漏等计算机安全类问题经常出现。稳定运行的在线代码评测系统可以为用户带来良好的使用体验,操作系统环境对评测系统运行的稳定性有重要的影响。以往的在线代码评测系统(Online Judge, OJ)多数运行于Windows 系统中,Linux 生产环境相较于Windows有着成本更低、稳定性更强、安全性更可靠,读、写、执行等权限管理更严格等优势。因此本文结合Linux 操作系统的优良特性和其内核提供的相关虚拟化技术、系统调用拦截等技术,综合实现了用于编译用户上传的源代码、执行生成的二进制文件、并对结果做出判定的沙箱评测系统内核。沙箱评测系统内核即在线评测系统的核心功能模块。
在Windows 操作系统中开发者多数采用应用程序接口拦截技术(API Hook)甄别进程中是否存在危险的系统调用;在Linux 操作系统中开发者多数使用容器技术或系统调用拦截技术,实现对进程中存在的恶意行为的监控与阻断。Linux 下的系统调用拦截技术有进程追踪(Process Trace, Ptrace)和带有过滤器的安全计算模式(Secure Computing Mode-BSD Packet Filter, Seccomp-BPF)。Linux文件权限分配机制可以限制软件的一部分读、写、执行功能;改变根目录(Change Root, Chroot)可以设定进程可见的文件系统根目录。单纯使用文件权限分配机制和改变根目录的方法构建的评测系统内核可能发生运行时权限泄露的问题。
目前一些优秀的开源在线代码评测系统通常采用比较原始的架构方式,使用逐级应用调用的方法,在配置运行参数后,直接将评测系统软件置于主流的容器中运行。若运行由用户提交的代码编译生成的软件破坏了容器内的环境,评测系统监控软件需要使用较长的时间恢复和重启容器及容器内的评测系统。如果这类评测系统在高并发的生产环境中运行,很可能发生操作系统内存溢出、CPU 过载等问题。在评测一段安全性未知的代码时,为了保障操作系统的安全,提高评测效率,设计一种由组合权限控制技术与沙箱技术构成的、有着高效的任务调度策略的沙箱评测系统内核,具有广泛的适用性和极高的应用价值。
1 安全防御的设计与实现
沙箱评测系统内核在安全防御上组合使用了控制组(Control Groups, Cgroups)、命名空间(Name Space)和带有过滤器的安全计算模式等Linux 提供的技术。控制组按资源限制级别构建不同分组,并将系统任务及其子任务隔离到相应的分组中,修改或更新组内的资源限制文件即可控制任务的内存占用、CPU 消耗等;命名空间主要用于隔离进程间通信、主机名等;带有过滤器的安全计算模式指定系统调用拦截规则名单,并将规则名单交由Linux 内核处理,从而快速准确地限制进程的系统调用,达到阻断用户程序的危险行为的目的。使用以上技术组合而成的具有安全防御功能的沙箱评测系统内核,可以有效地阻止用户代码执行非法的写入、修改、删除文件,以及连接网络、在进程间传递信息等恶意行为的发生,避免用户进程导致的操作系统及数据安全的问题出现。
如图1所示,沙箱评测系统内核在监控用户进程执行状态时使用了Linux 内核层和系统调用层的接口。其利用命名空间对网络连接、用户ID、进程ID、进程间通信、文件系统、主机名称进行统一的隔离;通过修改控制组内的虚拟资源限制文件,控制进程的内存消耗、磁盘消耗、CPU 占用等;使用进程资源限制函数对进程资源的使用进行严格的把控;选取系统级别的带有过滤器的安全计算模式,拦截系统调用。该内核在启动时会从配置文件中获取系统调用规则名单,并交由Linux 系统预处理。在沙箱评测系统内核执行用户进程的分支时,操作系统内核会判断用户进程的某个系统调用是否在规则名单中,从而杜绝用户进程中恶意行为的发生。
图1 评测过程中的Linux 接口调用图
2 整体设计与实现
沙箱评测系统内核的主要功能是评测用户上传的代码,对执行结果做出判定,并阻断用户代码执行过程中存在的危险行为,保障操作系统的安全。该内核可以被单点或多点部署,它通过网络接口数据传输的方式进行任务的分发和结果的回传。
沙箱评测系统内核使用了改进后的管道并发模型,实现了多用户的并发评测。评测系统内核任务调度,在宏观的流程中以串行的方式进行,并将任务拆分为编译、运行、评测、反馈等子任务,每个子任务都由相应的子模块进行调度。子模块在调度子任务过程中采用并行或并发的处理方式,每一个子任务的执行结果都会被异步的回传给沙箱评测系统内核的调用者,由调用者进行数据的统一处理。
沙箱评测系统内核运行于Linux 环境中,其主要功能架构图及评测流程如图2所示。
图2 沙箱评测系统内核主要功能架构图
系统评测流程具体为:
(1)评测API 模块接收用户提交的代码,将其封装成结构化的评测任务,并将评测任务发送至等待队列准备接受校验。调度过程如图3所示。
图3 评测API 模块的任务调度过程
(2)代码校验模块并发的从等待队列中取出封装好的评测任务,进行代码结构完整性等内容校验。若校验成功,则将当前评测任务发送至编译队列等待编译。调度过程如图4所示。
图4 代码校验模块的任务调度过程
(3)代码编译模块并发的从编译队列中取出评测任务,在配置信息指定的编译时长内对评测任务中的代码进行编译。若编译成功,则将编译评测代码所生成的二进制文件的路径写入当前的评测任务中,并将该任务发送至执行队列,等待执行;同时代码编译模块会向评测信息拉取模块发送拉取远端评测数据的请求。评测信息拉取模块获得远端的评测数据并存储在本地的缓存中以待使用。调度过程如图5所示。
图5 编译模块的任务调度过程
(4)代码执行模块并发的从执行队列中取出评测任务,在定制的具有安全防御功能的沙箱环境中安全无害的执行当前评测任务中指定路径下的二进制文件。目标程序在执行过程中,代码执行模块通过标准输入将缓存中的评测数据写入目标进程,并从标准输出、标准错误中收集目标程序的输出信息与错误信息,并将其与该评测数据中的正确答案一同写入评测任务,并发送至结果采集队列。调度过程如图6所示。
图6 执行模块的任务调度过程
(5)评测模块并发的从结果采集队列中收集相应目标程序的单次执行结果,首先判定代码执行时间是否在规定范围内,其次通过外部比较器,对执行结果与标准答案进行逐字节对比,判定该评测任务是否通过。调度过程如图7所示。
图7 评测模块的任务调度过程
(6)每一个小模块执行过后,都会向数据回传模块发送执行状态,数据回传模块会向沙箱评测系统内核的上游服务反馈执行结果。数据传递如图8所示。
图8 数据回传
3 沙箱评测内核的测试与总结
以下分别对沙箱评测系统内核的安全防御功能和软件的主要功能进行测试。
3.1 安全防御测试
如图9所示,在root 用户下,向沙箱评测系统内核发送执行init 0 命令的指令,init 0 命令为Linux 操作系统关机命令,关机对于Linux 操作系统中的服务来讲是危害非常严重的系统调用。经测试发现,沙箱评测系统内核已经成功拦截init 0 的系统调用,且在控制台中打印出了日志信息,该信息也会被记录在日志文件中。如发生以上行为,沙箱评测系统内核会通过邮件提醒其维护者“某用户提交了危害操作系统的代码或指令”。
图9 评测内核安全防御测试
3.2 主要功能测试
启动沙箱评测系统内核后,通过接口测试工具向评测系统内核提交数据,得到如图10 所示的反馈,由图中的日志信息可见,沙箱评测系统内核的编译、运行、评测等模块是串行执行的;在评测模块中,如果同一份代码有多个评测点,那么采用并发的评测方式。
图10 沙箱评测 系统内核服务执行效果图
3.3 测试总结
经多次测试,该沙箱评测系统内核能够拦截用户进程中不利于操作系统和数据安全的操作,准确的完成代码评测任务。沙箱评测系统内核的系统调用规则名单取决于特定的编程语言,对于算法竞赛来说,每种编程语言可以放行的系统调用的数量有限。该沙箱评测系统内核采用带有过滤器的安全计算模式的白名单机制,严格地控制进程的系统调用,为操作系统安全,数据安全带来了保障。相较于使用主流容器技术的评测系统核心,该沙箱评测系统内核原生的采用了Linux 提供的技术,使用了改进后的管道并发模型,降低了第三方软件调用的成本,突破了任务调度上的瓶颈,提升了软件整体性能。
4 结 论
通过Linux 内核提供的虚拟化技术和系统调用拦截技术及大量的防御性编程工作,构建起的沙箱评测系统内核,可以严格地控制进程的系统调用,准确地限制CPU 时间占用、内存资源占用、网络连接。该沙箱评测系统内核凭借执行效率高、资源占用率低、并发量大等优势,为在线代码评测系统的鲁棒性、执行效率带来了可靠的保障。