online judge sandbox 设计思路(2)
This article is deprecated, please see here for more details.
seccomp()
seccomp 是 Linux 内核提供的一种应用程序沙箱机制,seccomp 通过只允许应用程序调用 exit(), sigreturn(), read() 和 write() 四种系统调用来达到沙箱的效果。如果应用程序调用了除了这四种之外的系统调用, kernel 会向进程发送 SIGKILL 信号。
seccomp 很难在实际中得到推广,因为限制实在是太多了,Linus 本人也对它的应用持怀疑的态度,直到出现了 seccomp-bpf。seccomp-bpf 是 seccomp 的一个扩展,它可以通过配置来允许应用程序调用其他的系统调用。chrome 中第一个应用 seccomp-bpf 的场景是把 Flash 放到了沙箱里运行(实在是不放心),后续也把 render 的过程放到了沙箱里。
我们仍然先通过限制 unlink() 来看一下 seccomp 是如何工作的:
[root@localhost ~]# yum install -y libseccomp libseccomp-devel [root@localhost ~]# cat a.c #include <stdio.h> #include <sys/prctl.h> #include <linux/seccomp.h> #include <unistd.h> int main() { printf("starting...\n"); printf("add seccomp restriction\n"); prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT); unlink("/etc/hosts"); printf("i just removed /etc/hosts!\n"); return 0; } [root@localhost ~]# gcc a.c -lseccomp -o a.out [root@localhost ~]# ll /etc/hosts -rw-r--r--. 1 root root 158 May 7 23:04 /etc/hosts [root@localhost ~]# ./a.out starting... add seccomp restriction Killed [root@localhost ~]# echo $? 137 [root@localhost ~]# ll /etc/hosts -rw-r--r--. 1 root root 158 May 7 23:04 /etc/hosts
删除失败了。
下面,我们写一个程序 b.out,让 seccomp 允许调用 unlink() ,但是不允许调用 fork():
#include <stdio.h> #include <unistd.h> #include <seccomp.h> int main() { printf("starting...\n"); scmp_filter_ctx ctx; ctx = seccomp_init(SCMP_ACT_KILL); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0); seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0); // 自定义白名单 seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(unlink), 0); seccomp_load(ctx); printf("we can call unlink()\n"); unlink("/etc/hosts"); printf("let's fork()\n"); fork(); printf("U cannot see me\n"); return 0; }
编译运行下:
[root@localhost ~]# ll /etc/hosts -rw-r--r--. 1 root root 158 May 7 23:30 /etc/hosts [root@localhost ~]# ./b.out starting... we can call unlink() let's fork() Bad system call [root@localhost ~]# ll /etc/hosts ls: cannot access /etc/hosts: No such file or directory
我们的目的达到了。
seccomp-nurse
seccomp-nurse 是一个基于 seccomp 的 sandbox 框架,主页是:https://github.com/nbareil/seccomp-nurse,这里只用一张主页上的图来描述他的架构:
Docker 大法好
Docker 在 1.10 之后引入了 seccomp 选项,可以借助一个 json 配置文件来限定运行程序可以使用的系统调用。详情见:https://github.com/docker/docker/blob/master/docs/security/seccomp.md
参考:
http://man7.org/linux/man-pages/man2/seccomp.2.html
https://wiki.mozilla.org/Security/Sandbox/Seccomp
https://blog.yadutaf.fr/2014/05/29/introduction-to-seccomp-bpf-linux-syscall-filter/
http://blog.viraptor.info/post/seccomp-sandboxes-and-memcached-example-part-1
http://blog.viraptor.info/post/seccomp-sandboxes-and-memcached-example-part-2