From 485f8fb2500980be2cb0cde43e3582c088739a6f Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Thu, 19 Mar 2015 00:40:49 +0000 Subject: [PATCH] tests: add a test for SECCOMP_MODE_FILTER decoding * tests/seccomp.c: New file. * tests/seccomp.test: New test. * tests/Makefile.am (check_PROGRAMS): Add seccomp. (TESTS): Add seccomp.test. * tests/.gitignore: Add seccomp. --- tests/.gitignore | 1 + tests/Makefile.am | 2 + tests/seccomp.c | 113 +++++++++++++++++++++++++++++++++++++++++++++ tests/seccomp.test | 15 ++++++ 4 files changed, 131 insertions(+) create mode 100644 tests/seccomp.c create mode 100755 tests/seccomp.test diff --git a/tests/.gitignore b/tests/.gitignore index 8efb0ef1..9fdbe4d8 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -12,6 +12,7 @@ netlink_inet_diag netlink_unix_diag pc scm_rights +seccomp select set_ptracer_any sigaction diff --git a/tests/Makefile.am b/tests/Makefile.am index 0acad4df..930f6d95 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -21,6 +21,7 @@ check_PROGRAMS = \ netlink_unix_diag \ pc \ scm_rights \ + seccomp \ select \ set_ptracer_any \ sigaction \ @@ -56,6 +57,7 @@ TESTS = \ ipc_shm.test \ ipc_sem.test \ scm_rights-fd.test \ + seccomp.test \ select.test \ sigaction.test \ sigreturn.test \ diff --git a/tests/seccomp.c b/tests/seccomp.c new file mode 100644 index 00000000..01fe2ebb --- /dev/null +++ b/tests/seccomp.c @@ -0,0 +1,113 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include + +#ifdef HAVE_PRCTL +# include +#endif +#ifdef HAVE_LINUX_SECCOMP_H +# include +#endif +#ifdef HAVE_LINUX_FILTER_H +# include +#endif + +#if defined HAVE_PRCTL \ + && defined PR_SET_NO_NEW_PRIVS \ + && defined PR_SET_SECCOMP \ + && defined SECCOMP_MODE_FILTER \ + && defined SECCOMP_RET_ERRNO \ + && defined BPF_JUMP \ + && defined BPF_STMT + +#define SOCK_FILTER_ALLOW_SYSCALL(nr) \ + BPF_JUMP(BPF_JMP | BPF_K | BPF_JEQ, __NR_ ## nr, 0, 1), \ + BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW) + +#define SOCK_FILTER_DENY_SYSCALL(nr, err) \ + BPF_JUMP(BPF_JMP | BPF_K | BPF_JEQ, __NR_ ## nr, 0, 1), \ + BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | (SECCOMP_RET_DATA & (err))) + +#define SOCK_FILTER_KILL_PROCESS \ + BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL) + +#define PRINT_ALLOW_SYSCALL(nr) \ + printf("BPF_JUMP(BPF_JMP | BPF_K | BPF_JEQ, %#x, 0, 0x1), " \ + "BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), ", \ + __NR_ ## nr) + +#define PRINT_DENY_SYSCALL(nr, err) \ + printf("BPF_JUMP(BPF_JMP | BPF_K | BPF_JEQ, %#x, 0, 0x1), " \ + "BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | %#x), ", \ + __NR_ ## nr, err) + +static const struct sock_filter filter[] = { + /* load syscall number */ + BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)), + + /* allow syscalls */ + SOCK_FILTER_ALLOW_SYSCALL(close), + SOCK_FILTER_ALLOW_SYSCALL(exit), + SOCK_FILTER_ALLOW_SYSCALL(exit_group), + + /* deny syscalls */ + SOCK_FILTER_DENY_SYSCALL(sync, EBUSY), + SOCK_FILTER_DENY_SYSCALL(setsid, EPERM), + + /* kill process */ + SOCK_FILTER_KILL_PROCESS +}; + +static const struct sock_fprog prog = { + .len = sizeof(filter) / sizeof(filter[0]), + .filter = (struct sock_filter *) filter, +}; + +int +main(void) +{ + int fds[2]; + + puts("prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) = 0"); + + printf("prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, ["); + + printf("BPF_STMT(BPF_LD | BPF_W | BPF_ABS, %#x), ", + (unsigned) offsetof(struct seccomp_data, nr)); + + PRINT_ALLOW_SYSCALL(close); + PRINT_ALLOW_SYSCALL(exit); + PRINT_ALLOW_SYSCALL(exit_group); + + PRINT_DENY_SYSCALL(sync, EBUSY), + PRINT_DENY_SYSCALL(setsid, EPERM), + + printf("BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL)"); + + puts("]) = 0"); + puts("+++ exited with 0 +++"); + + fflush(stdout); + close(0); + close(1); + + if (pipe(fds) || + prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) || + prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || + close(0) || close(1)) + _exit(77); + + _exit(0); +} + +#else + +int main(void) { return 77; } + +#endif diff --git a/tests/seccomp.test b/tests/seccomp.test new file mode 100755 index 00000000..4101cae1 --- /dev/null +++ b/tests/seccomp.test @@ -0,0 +1,15 @@ +#!/bin/sh + +# Check how SECCOMP_MODE_FILTER is decoded. + +. "${srcdir=.}/init.sh" + +OUT="$LOG.out" + +run_prog > /dev/null +run_strace -veprctl $args > "$OUT" +match_diff "$LOG" "$OUT" + +rm -f "$OUT" + +exit 0