seccompとは
Seccompとは、Linuxカーネルが持つセキュリティ機構の一つで、Secure Computing Modeの略です。 簡単に言うと、Seccompはシステムコールの許可・不許可を設定できるようにし、危険なシステムコールを実行できなくするためのものです。
突然の「Operation not permitted」-Dockerが採用するセキュリティ機構「Seccomp」とは何か? #docker #seccomp #mirantis - クリエーションライン株式会社
2つのモード
linuxのseccompにはSECCOMP_MODE_STRICTとSECCOMP_MODE_FILTERという2つのモードがある。
前者はread, write, exit, sigreturn以外のシステムコールを禁止するシンプルなものになっており、後者はBPFを利用して開発者が任意のシステムコールをフィルタできる柔軟なものになっている。
SECCOMP_MODE_STRICT
SECCOMP_MODE_STRICTで許可されるシステムコールはread, write, exit, sigreturnのみ。
違反するとプロセスにSIGKILLが送られる。
検証
#include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <linux/seccomp.h> #include <sys/prctl.h> int main(int argc, char *argv[]) { int before_seccomp = open("before_seccomp.txt", O_RDWR); close(before_seccomp); prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT); int after_seccomp = open("after_seccomp.txt", O_RDWR); close(after_seccomp); }
実行結果
$ clang seccomp_strict_test.c -o seccomp_strict_test $ ./seccomp_strict_test 1. invoked open system call 1. invoked close system call Killed
prctlでseccompが呼び出した後、openシステムコールが呼び出せずに、SIGKILLが送られている。
SECCOMP_MODE_FILTER
SECCOMP_MODE_STRICTでは許可されるシステムコールが予め決まっていたが、SECCOMP_MODE_FILTERでは任意のシステムコールを指定できる。
また、違反した際のアクションについてもいろいろと設定可能になっている。例えば、プロセスSIGKILLを送るのではなく、ログに記載するだけみたいなこともできる。
検証
#include <seccomp.h> #include <stdio.h> #include <sys/utsname.h> #include <unistd.h> int main(void) { scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ALLOW); if (ctx == NULL) { goto ERROR; } int rule_add_ret; rule_add_ret = seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(uname), 0); if (rule_add_ret != 0) { goto ERROR; } seccomp_load(ctx); printf("before uname invocation\n"); struct utsname buf; if (uname(&buf) != 0) { goto ERROR; }; printf("after uname invocation\n"); printf("sysname: %s, nodename: %s, version:%s\n", buf.sysname, buf.nodename, buf.version); seccomp_release(ctx); return 0; ERROR: perror("failed"); return -1; }
※prctlやseccompシステムコールを利用するのではなく、便利なlibseccompを利用している。
実行結果
$ clang seccomp_mode_filter.c -lseccomp -o filter $ ./filter before uname invocation Bad system call (core dumped)
unameの呼び出しがフィルタされているのがわかる。