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

Leave a Reply

Your email address will not be published. Required fields are marked *

*