simplify bpf rule generation, add deny macro.

This commit is contained in:
Joris Vink 2019-09-25 23:41:43 +02:00
parent 61b8a9e90d
commit c1affbbd74
2 changed files with 31 additions and 46 deletions

View File

@ -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]))

View File

@ -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)