seccomp是secure computing mode的缩写,是Linux内核中的一个安全计算工具,机制用于限制应用程序可以使用的系统调用,增加系统的安全性。可以理解为系统调用的防火墙,利用BPF来规律系统调用。
在/proc/${pid}/status文件中的Seccomp字段可以看到进程的Seccomp。
prctl
下面程序使用prctl来设置程序的seccomp为strict模式,仅允许read、write、_exit和sigreturn四个系统调用。当调用未在seccomp白名单中的系统调用后,应用程序会被kill。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include <stdio.h> #include <sys/prctl.h> #include <linux/seccomp.h> #include <unistd.h>
int main() { printf("step 1: unrestricted\n");
prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT); printf("step 2: only 'read', 'write', '_exit' and 'sigreturn' syscalls\n");
dup2(1, 2); printf("step 3: !! YOU SHOULD NOT SEE ME !!\n");
return 0; }
|
执行上述程序后会输出如下内容:
1 2 3
| step 1: unrestricted step 2: only 'read', 'write', '_exit' and 'sigreturn' syscalls Killed
|
基于BPF的seccomp
上述基于prctl系统调用的seccomp机制不够灵活,在linux 3.5之后引入了基于BPF的可定制的系统调用过滤功能。
需要先安装依赖包:yum install libseccomp-dev
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| #include <stdio.h> /* printf */ #include <unistd.h> /* dup2: just for test */ #include <seccomp.h> /* libseccomp */
int main() { printf("step 1: unrestricted\n");
// Init the filter scmp_filter_ctx ctx; ctx = seccomp_init(SCMP_ACT_KILL); // default action: kill
// setup basic whitelist 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);
// setup our rule seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(dup2), 2, SCMP_A0(SCMP_CMP_EQ, 1), SCMP_A1(SCMP_CMP_EQ, 2));
// build and load the filter seccomp_load(ctx); printf("step 2: only 'write' and dup2(1, 2) syscalls\n");
// Redirect stderr to stdout dup2(1, 2); printf("step 3: stderr redirected to stdout\n");
// Duplicate stderr to arbitrary fd dup2(2, 42); printf("step 4: !! YOU SHOULD NOT SEE ME !!\n");
// Success (well, not so in this case...) return 0; }
|
输入如下内容:
1 2 3 4
| step 1: unrestricted step 2: only 'write' and dup2(1, 2) syscalls step 3: stderr redirected to stdout Bad system call
|
docker中的应用
通过如下方式可以查看docker是否启用seccomp:
1 2
| # docker info --format "{{ .SecurityOptions }}" [name=seccomp,profile=default]
|
docker每个容器默认都设置了一个seccomp profile,启用的系统调用可以从default.json中看到。
docker会将seccomp传递给runc中的sepc.linux.seccomp。
可以通过—security-opt seccomp=xxx
来设置docker的seccomp策略,xxx为json格式的文件,其中定义了seccomp规则。
也可以通过--security-opt seccomp=unconfined
来关闭docker引入默认的seccomp规则的限制。
ref