commit c1affbbd740a08b5b733057eba76f1d0aa57c783
parent 61b8a9e90d8d6eaa3c9ef9b8a1446820a138d87f
Author: Joris Vink <joris@coders.se>
Date: Wed, 25 Sep 2019 23:41:43 +0200
simplify bpf rule generation, add deny macro.
Diffstat:
2 files changed, 31 insertions(+), 46 deletions(-)
diff --git a/include/kore/seccomp.h b/include/kore/seccomp.h
@@ -26,15 +26,17 @@
/*
* Allow a system call by comparing the accumulator value (which will contain
* the system call value) with the value of SYS_##name.
- *
- * If the value is equal the true branch (first) is taken, otherwise the
- * false branch (second) is taken.
- *
- * When the program is constructed the true branch jump destination is
- * resolved automatically.
*/
-#define KORE_SYSCALL_ALLOW(_name) \
- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_##_name, 0, 0)
+#define KORE_SYSCALL_ALLOW(_name) \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_##_name, 0, 1), \
+ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
+
+/*
+ * Explicit deny of a system call with an errno code for the caller.
+ */
+#define KORE_SYSCALL_DENY_ERRNO(_name, _errno) \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_##_name, 0, 1), \
+ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO|(_errno))
/* The length of a filter. */
#define KORE_FILTER_LEN(x) (sizeof(x) / sizeof(x[0]))
diff --git a/src/seccomp.c b/src/seccomp.c
@@ -36,8 +36,14 @@
#define SECCOMP_KILL_POLICY SECCOMP_RET_KILL
#endif
-/* The bare minimum to be able to run kore. */
+/*
+ * The bare minimum to be able to run kore. These are added last and can
+ * be overwritten by a filter program that is added before hand.
+ */
static struct sock_filter filter_kore[] = {
+ /* Deny these, but with EACCESS instead of dying. */
+ KORE_SYSCALL_DENY_ERRNO(ioctl, EACCES),
+
/* File related. */
KORE_SYSCALL_ALLOW(open),
KORE_SYSCALL_ALLOW(read),
@@ -49,6 +55,7 @@ static struct sock_filter filter_kore[] = {
KORE_SYSCALL_ALLOW(lseek),
KORE_SYSCALL_ALLOW(close),
KORE_SYSCALL_ALLOW(access),
+ KORE_SYSCALL_ALLOW(writev),
KORE_SYSCALL_ALLOW(getcwd),
KORE_SYSCALL_ALLOW(openat),
KORE_SYSCALL_ALLOW(unlink),
@@ -74,14 +81,18 @@ static struct sock_filter filter_kore[] = {
KORE_SYSCALL_ALLOW(epoll_ctl),
KORE_SYSCALL_ALLOW(setsockopt),
KORE_SYSCALL_ALLOW(epoll_wait),
+ KORE_SYSCALL_ALLOW(epoll_pwait),
- /* "Other" without clear category. */
- KORE_SYSCALL_ALLOW(futex),
+ /* Signal related. */
KORE_SYSCALL_ALLOW(sigaltstack),
KORE_SYSCALL_ALLOW(rt_sigreturn),
KORE_SYSCALL_ALLOW(rt_sigaction),
KORE_SYSCALL_ALLOW(clock_gettime),
+ /* "Other" without clear category. */
+ KORE_SYSCALL_ALLOW(futex),
+ KORE_SYSCALL_ALLOW(rt_sigprocmask),
+
#if defined(__NR_getrandom)
KORE_SYSCALL_ALLOW(getrandom),
#endif
@@ -101,14 +112,9 @@ static struct sock_filter filter_prologue[] = {
};
/* bpf program epilogue. */
-#define FILTER_EPILOGUE_ALLOW_OFFSET 1
-
static struct sock_filter filter_epilogue[] = {
/* Return hit if no system calls matched our list. */
- BPF_STMT(BPF_RET+BPF_K, SECCOMP_KILL_POLICY),
-
- /* Final destination for syscalls that are accepted. */
- BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
+ BPF_STMT(BPF_RET+BPF_K, SECCOMP_KILL_POLICY)
};
#define filter_prologue_len KORE_FILTER_LEN(filter_prologue)
@@ -161,8 +167,8 @@ kore_seccomp_enable(void)
struct sock_fprog prog;
struct kore_runtime_call *rcall;
struct filter *filter;
+ size_t prog_len, off, i;
int skip_worker_filter;
- size_t prog_len, pos, jmp_off, i;
#if defined(KORE_DEBUG)
memset(&sa, 0, sizeof(sa));
@@ -195,50 +201,27 @@ kore_seccomp_enable(void)
KORE_FILTER_LEN(filter_kore));
}
- /*
- * Construct the entire BPF program by adding all relevant parts
- * together. While doing so remember where the jmp_off is going to be
- * so we can resolve the true branch for all comparisons.
- */
-
/* Start with the prologue. */
prog_len = filter_prologue_len;
- jmp_off = prog_len;
/* Now account for all enabled filters. */
- TAILQ_FOREACH(filter, &filters, list) {
+ TAILQ_FOREACH(filter, &filters, list)
prog_len += filter->instructions;
- jmp_off += filter->instructions;
- }
/* Finally add the epilogue. */
prog_len += filter_epilogue_len;
- /* Finalize the jump position. */
- jmp_off += FILTER_EPILOGUE_ALLOW_OFFSET;
-
- /* Initial filter position is immediately after prologue. */
- pos = filter_prologue_len + 1;
-
- /* Iterate over all filters and fixup the true branch. */
- TAILQ_FOREACH(filter, &filters, list) {
- for (i = 0; i < filter->instructions; i++) {
- filter->prog[i].jt = (u_int8_t)jmp_off - pos;
- pos++;
- }
- }
-
/* Build the entire bpf program now. */
if ((sf = calloc(prog_len, sizeof(*sf))) == NULL)
fatal("calloc");
- jmp_off = 0;
+ off = 0;
for (i = 0; i < filter_prologue_len; i++)
- sf[jmp_off++] = filter_prologue[i];
+ sf[off++] = filter_prologue[i];
TAILQ_FOREACH(filter, &filters, list) {
for (i = 0; i < filter->instructions; i++)
- sf[jmp_off++] = filter->prog[i];
+ sf[off++] = filter->prog[i];
if (!kore_quiet) {
kore_log(LOG_INFO,
@@ -247,7 +230,7 @@ kore_seccomp_enable(void)
}
for (i = 0; i < filter_epilogue_len; i++)
- sf[jmp_off++] = filter_epilogue[i];
+ sf[off++] = filter_epilogue[i];
/* Lock and load it. */
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1)