[CRIU] [PATCH 4/7] check: add a check for seccomp filters c/r

Tycho Andersen tycho.andersen at canonical.com
Tue Nov 3 22:04:55 PST 2015


Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 cr-check.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 60 insertions(+), 3 deletions(-)

diff --git a/cr-check.c b/cr-check.c
index 85940f3..d8be470 100644
--- a/cr-check.c
+++ b/cr-check.c
@@ -12,6 +12,10 @@
 #include <fcntl.h>
 #include <signal.h>
 #include <linux/if.h>
+#include <linux/filter.h>
+#include <linux/bpf.h>
+#include <linux/seccomp.h>
+#include <sys/syscall.h>
 #include <sys/ioctl.h>
 #include <termios.h>
 #include <sys/mman.h>
@@ -525,7 +529,7 @@ static int check_sigqueuinfo()
 	return 0;
 }
 
-static pid_t fork_and_ptrace_attach(void)
+static pid_t fork_and_ptrace_attach(int (*child_setup)(void))
 {
 	pid_t pid;
 
@@ -534,6 +538,9 @@ static pid_t fork_and_ptrace_attach(void)
 		pr_perror("fork");
 		return -1;
 	} else if (pid == 0) {
+		if (child_setup && child_setup() != 0)
+			exit(1);
+
 		while (1)
 			sleep(1000);
 		exit(1);
@@ -557,7 +564,7 @@ static int check_ptrace_peeksiginfo()
 	pid_t pid, ret = 0;
 	k_rtsigset_t mask;
 
-	pid = fork_and_ptrace_attach();
+	pid = fork_and_ptrace_attach(NULL);
 	if (pid < 0)
 		return -1;
 
@@ -589,7 +596,7 @@ static int check_ptrace_suspend_seccomp(void)
 		return 0;
 	}
 
-	pid = fork_and_ptrace_attach();
+	pid = fork_and_ptrace_attach(NULL);
 	if (pid < 0)
 		return -1;
 
@@ -606,6 +613,53 @@ static int check_ptrace_suspend_seccomp(void)
 	return ret;
 }
 
+static int setup_seccomp_filter(void)
+{
+	struct sock_filter filter[] = {
+		BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct seccomp_data, nr)),
+		/* Allow all syscalls except ptrace */
+		BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_ptrace, 0, 1),
+		BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL),
+		BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
+	};
+
+	struct sock_fprog bpf_prog = {
+		.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
+		.filter = filter,
+	};
+
+	if (sys_prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, (long) &bpf_prog, 0, 0) < 0)
+		return -1;
+
+	return 0;
+}
+
+static int check_ptrace_dump_seccomp_filters(void)
+{
+	pid_t pid;
+	int ret = 0, fd;
+
+	if (opts.check_ms_kernel) {
+		pr_warn("Skipping PTRACE_SECCOMP_GET_FILTER check");
+		return 0;
+	}
+
+	pid = fork_and_ptrace_attach(setup_seccomp_filter);
+	if (pid < 0)
+		return -1;
+
+	fd = ptrace(PTRACE_SECCOMP_GET_FILTER, pid, NULL, 0);
+	if (fd < 0) {
+		ret = -1;
+		pr_err("Dumping seccomp filters not supported\n");
+	} else {
+		close(fd);
+	}
+
+	kill(pid, SIGKILL);
+	return ret;
+}
+
 static int check_mem_dirty_track(void)
 {
 	if (kerndat_get_dirty_track() < 0)
@@ -796,6 +850,7 @@ int cr_check(void)
 	ret |= check_sigqueuinfo();
 	ret |= check_ptrace_peeksiginfo();
 	ret |= check_ptrace_suspend_seccomp();
+	ret |= check_ptrace_dump_seccomp_filters();
 	ret |= check_mem_dirty_track();
 	ret |= check_posix_timers();
 	ret |= check_tun_cr(0);
@@ -859,6 +914,8 @@ int check_add_feature(char *feat)
 		chk_feature = check_fdinfo_lock;
 	else if (!strcmp(feat, "seccomp_suspend"))
 		chk_feature = check_ptrace_suspend_seccomp;
+	else if (!strcmp(feat, "seccomp_filters"))
+		chk_feature = check_ptrace_dump_seccomp_filters;
 	else {
 		pr_err("Unknown feature %s\n", feat);
 		return -1;
-- 
2.5.0



More information about the CRIU mailing list