IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> seccomp实现安全判题沙箱 -> 正文阅读

[C++知识库]seccomp实现安全判题沙箱

seccomp实现安全判题沙箱

需求分析

软件判题器需要一下几点

  • 保证判题的正确性
  • 能够并发进行判题
  • 能够保证判题过程的安全性
  • 能够限制判题过程的资源
  • 能够根据编程语言进行动态定制
  • 能够返回判题过程中使用的资源大小

需要的参数

入参类型描述限制
binstring可执行文件无限制
output-filestring输出重定向文件无限制
input-filestring输入重定向文件无限制
error-filestring错误重定向文件无限制
num-threadint最大可执行线程不超过cpu核心数
max-memoryint最大内存使用(Byte)不超过系统内存的1/16
max-stack-sizeint最大堆栈大小无限制
max-output-sizeint最大输出文件大小(KB)一般不超过100MB
max-cpu-timeint最大CPU时间占用(ms)无限制
max-real-timeint包含系统调度的时间占用(ms)无限制
argumentsvector可执行文件的运行参数长度<=255
envvector执行程序时的环境变量长度<=255

输出的结果

直接返回值结果

出参类型描述
memoryint占用的内存(Byte)
cpu-timeint占用的cpu时间(ms)
real-timeint占用的真实时间(ms)
output-filestring程序的输出结果
error-filestring出错的错误文件结果
exit-codeint程序执行结果的状态码
signalint沙箱执行结果状态码

判题器实现

前期准备

# 安装seccomp开发环境支持
sudo apt-get install libseccomp-dev

创建限制与返回结果

按照判题器的要求创建资源限制,返回结果以及判题器的配置文件

判题的资源限制

// limit.h
struct Limit {
    int max_real_time;
    int max_cpu_time;
    int max_memory;
    int max_stack_size;
    int max_output_size;
    int num_thread;
};

判题最后返回的结果文件

// result.h
struct Result {
    int cpu_time;
    int real_time;
    long memory;
    int signal;
    int exit_code;
};

判题器的配置文件

struct Config {
    Limit limit;
    std::string input_file;
    std::string output_file;
    std::string error_file;
};

创建判题器核心

rlimit

linux下对资源进行限制的函数是位于**<sys/resource>下的getrlimitsetrlimit**

#include <sys/resource.h>

int getrlimit(int resource, struct rlimit *rlptr);
int setrlimit(int resource, const struct rlimit *rlptr);

系统的资源由最初的0号进程获取,后续所有的子进程继承父进程的资源限制

每个子进程也可以调用setrlimit改变资源限制

rlimit的结构

struct rlimit {
	rlim_t rlim_cur; //current limit
	rlim_t rlim_max; //max limit value for "rlim_cur"
};

对应的resource参数可选如下:

RLIMIT_AS/RLIMIT_VMEM: 这两个资源表示的是同一个含义,都是只address space限制,可用内存用户地址空间最大长度,会影响到sbrk和mmap函数。
RLIMIT_STACK:栈的长度,默认一般是8K
RLIMIT_CORE:程序crash后生成的core dump文件的大小,如果为0将不生成对应的core文件。
RLIMIT_NOFILE:进程能够打开的最多文件数目,此限制会影响到sysconf的_SC_OPEN_MAX的返回值。
RLIMIT_NPROC:每个用户ID能够拥有的最大子进程数目,此限制会影响到sysconf的_SC_CHILD_MAX的返回值。
RLIMIT_NICE:对应进程的优先级nice值。
RLIMIT_SWAP:进程能够消耗的最大swap空间。
RLIMIT_CPU:CPU时间的最大值(秒单位),超过此限制后会发送SIGXCPU信号给进程。
RLIMIT_DATA:数据段的最大长度。默认为unlimited
RLIMIT_FSIZE:创建文件的最大字节长度。默认为ulimited
RLIMIT_MSGQUEUE:为posix消息队列可分配的最大存储字节数
RLIMIT_SIGPENDING:可排队的信号最大数量
RLIMIT_NPTS:可同时打开的伪终端数目
RLIMIT_RSS:最大可驻内存字节长度
RLIMIT_SBSIZE:单个用户所有套接字缓冲区的最大长度
RLIMIT_MEMLOCK:一个进程使用mlock能够锁定存储空间中的最大字节长度

如果设置resource的值为 RLIM_INFINITY 表示无限制

exit code

返回的状态码是0表示执行成功

对于完整的fork流程之后,会有一个退出的状态码,默认成功的状态码是0.其他的都是一些错误的状态码

在所有的状态码中1, 2, 126 – 165255 是系统定义的有意义的状态码,用户定义的时候应当避免这些状态码

exit的函数段

void exit(int return_code)

如果执行exit()中的return_code大于255时,会对255取模

如果return_code是负数,返回值会做运算65536 + return_code * 256

一些特殊的常见的系统定义的状态码

  • exit(1): It indicates abnormal termination of a program perhaps as a result a minor problem in the code.
  • exit(2): It is similar to exit(1) but is displayed when the error occurred is a major one. This statement is rarely seen.
  • exit(127): It indicates command not found.
  • exit(132): It indicates that a program was aborted (received SIGILL), perhaps as a result of illegal instruction or that the binary is probably corrupt.
  • exit(133): It indicates that a program was aborted (received SIGTRAP), perhaps as a result of dividing an integer by zero.
  • exit(134): It indicates that a program was aborted (received SIGABRT), perhaps as a result of a failed assertion.
  • exit(136): It indicates that a program was aborted (received SIGFPE), perhaps as a result of floating point exception or integer overflow.
  • exit(137): It indicates that a program took up too much memory.
  • exit(138): It indicates that a program was aborted (received SIGBUS), perhaps as a result of unaligned memory access.
  • exit(139): It indicates Segmentation Fault which means that the program was trying to access a memory location not allocated to it. This mostly occurs while using pointers or trying to access an out-of-bounds array index.
  • exit(158/152): It indicates that a program was aborted (received SIGXCPU), perhaps as a result of CPU time limit exceeded.
  • exit(159/153): It indicates that a program was aborted (received SIGXFSZ), perhaps as a result of File size limit exceeded.

rule

对于seccomp的规则主要有两类

  • 以c语言为代表的,无虚拟机运行的语言
  • 以Java为代表的有虚拟机运行的语言

有虚拟机参与的语言,可以交由虚拟机来保证一部分的安全性

对于判题器核心有一点,对于不同的语言应当有不同的限制,下面列举了需要运行最少需要的权限

语言权限备注
C/C++见下没有虚拟机,权限不需太多
JAVA见下虚拟机运行必须需要的权限
GO同上JAVA虚拟机运行必须需要的权限
//大部分编程题运行需要的最小权限
int sys_call_whitelist[] = {SCMP_SYS(read), SCMP_SYS(fstat),
                                SCMP_SYS(mmap), SCMP_SYS(mprotect),
                                SCMP_SYS(munmap), SCMP_SYS(uname),
                                SCMP_SYS(arch_prctl), SCMP_SYS(brk),
                                SCMP_SYS(access), SCMP_SYS(exit_group),
                                SCMP_SYS(close), SCMP_SYS(readlink),
                                SCMP_SYS(sysinfo), SCMP_SYS(write),
                                SCMP_SYS(writev), SCMP_SYS(lseek),
                                SCMP_SYS(clock_gettime), SCMP_SYS(pread64)};
//JVM运行所需要的最小权限
int sys_call_whitelist[] = {  SCMP_SYS(access),
                                    SCMP_SYS(arch_prctl),
                                    SCMP_SYS(brk),
                                    SCMP_SYS(clock_getres),
                                    SCMP_SYS(clone),
                                    SCMP_SYS(close),
                                    SCMP_SYS(connect),
                                    SCMP_SYS(execve),
                                    SCMP_SYS(exit_group),
                                    SCMP_SYS(fchdir),
                                    SCMP_SYS(fcntl),
                                    SCMP_SYS(fstat),
                                    SCMP_SYS(ftruncate),
                                    SCMP_SYS(futex),
                                    SCMP_SYS(getcwd),
                                    SCMP_SYS(getdents),
                                    SCMP_SYS(geteuid),
                                    SCMP_SYS(getpid),
                                    SCMP_SYS(gettid),
                                    SCMP_SYS(getuid),
                                    SCMP_SYS(kexec_load),
                                    SCMP_SYS(kill),
                                    SCMP_SYS(lseek),
                                    SCMP_SYS(lstat),
                                    SCMP_SYS(mkdir),
                                    SCMP_SYS(mmap),
                                    SCMP_SYS(mprotect),
                                    SCMP_SYS(munmap),
                                    SCMP_SYS(openat),
                                    SCMP_SYS(prctl),
                                    SCMP_SYS(pread64),
                                    SCMP_SYS(prlimit64),
                                    SCMP_SYS(pselect6),
                                    SCMP_SYS(read),
                                    SCMP_SYS(readlink),
                                    SCMP_SYS(rt_sigaction),
                                    SCMP_SYS(rt_sigprocmask),
                                    SCMP_SYS(rt_sigreturn),
                                    SCMP_SYS(sched_getaffinity),
                                    SCMP_SYS(sched_yield),
                                    SCMP_SYS(set_robust_list),
                                    SCMP_SYS(set_tid_address),
                                    SCMP_SYS(socket),
                                    SCMP_SYS(stat),
                                    SCMP_SYS(sysinfo),
                                    SCMP_SYS(uname),
                                    SCMP_SYS(unlink),
                                    SCMP_SYS(write)};
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-06-14 22:19:58  更:2022-06-14 22:20:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 17:12:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码