This is what I've been using to explore actual bitmap results for real-world filters... Signed-off-by: Kees Cook <keescook@xxxxxxxxxxxx> --- kernel/seccomp.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/kernel/seccomp.c b/kernel/seccomp.c index 9921f6f39d12..1a0595d7f8ef 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -835,6 +835,85 @@ static void seccomp_update_bitmap(struct seccomp_filter *filter, } } +static void __report_bitmap(const char *arch, u32 ret, int start, int finish) +{ + int gap; + char *name; + + if (finish == -1) + return; + + switch (ret) { + case UINT_MAX: + name = "filter"; + break; + case SECCOMP_RET_ALLOW: + name = "SECCOMP_RET_ALLOW"; + break; + case SECCOMP_RET_KILL_PROCESS: + name = "SECCOMP_RET_KILL_PROCESS"; + break; + case SECCOMP_RET_KILL_THREAD: + name = "SECCOMP_RET_KILL_THREAD"; + break; + default: + WARN_ON_ONCE(1); + name = "unknown"; + break; + } + + gap = 0; + if (start < 100) + gap++; + if (start < 10) + gap++; + if (finish < 100) + gap++; + if (finish < 10) + gap++; + + if (start == finish) + pr_info("%s %3d: %s\n", arch, start, name); + else if (start + 1 == finish) + pr_info("%s %*s%d,%d: %s\n", arch, gap, "", start, finish, name); + else + pr_info("%s %*s%d-%d: %s\n", arch, gap, "", start, finish, name); +} + +static void report_bitmap(struct seccomp_bitmaps *bitmaps, const char *arch) +{ + u32 nr; + int start = 0, finish = -1; + u32 ret = UINT_MAX; + struct report_states { + unsigned long *bitmap; + u32 ret; + } states[] = { + { .bitmap = bitmaps->allow, .ret = SECCOMP_RET_ALLOW, }, + { .bitmap = bitmaps->kill_process, .ret = SECCOMP_RET_KILL_PROCESS, }, + { .bitmap = bitmaps->kill_thread, .ret = SECCOMP_RET_KILL_THREAD, }, + { .bitmap = NULL, .ret = UINT_MAX, }, + }; + + for (nr = 0; nr < NR_syscalls; nr++) { + int i; + + for (i = 0; i < ARRAY_SIZE(states); i++) { + if (!states[i].bitmap || test_bit(nr, states[i].bitmap)) { + if (ret != states[i].ret) { + __report_bitmap(arch, ret, start, finish); + ret = states[i].ret; + start = nr; + } + finish = nr; + break; + } + } + } + if (start != nr) + __report_bitmap(arch, ret, start, finish); +} + static void seccomp_update_bitmaps(struct seccomp_filter *filter, void *pagepair) { @@ -849,6 +928,23 @@ static void seccomp_update_bitmaps(struct seccomp_filter *filter, SECCOMP_MULTIPLEXED_SYSCALL_TABLE_MASK, ¤t->seccomp.multiplex); #endif + if (strncmp(current->comm, "test-", 5) == 0 || + strcmp(current->comm, "seccomp_bpf") == 0 || + /* + * Why are systemd's process names head-truncated to 8 bytes + * and wrapped in parens!? + */ + (current->comm[0] == '(' && strrchr(current->comm, ')') != NULL)) { + pr_info("reporting syscall bitmap usage for %d (%s):\n", + task_pid_nr(current), current->comm); + report_bitmap(¤t->seccomp.native, "native"); +#ifdef CONFIG_COMPAT + report_bitmap(¤t->seccomp.compat, "compat"); +#endif +#ifdef SECCOMP_MULTIPLEXED_SYSCALL_TABLE_ARCH + report_bitmap(¤t->seccomp.multiplex, "multiplex"); +#endif + } } #else static void seccomp_update_bitmaps(struct seccomp_filter *filter, @@ -908,6 +1004,10 @@ static long seccomp_attach_filter(unsigned int flags, filter->prev = current->seccomp.filter; current->seccomp.filter = filter; atomic_inc(¤t->seccomp.filter_count); + if (atomic_read(¤t->seccomp.filter_count) > 10) + pr_info("%d filters: %d (%s)\n", + atomic_read(¤t->seccomp.filter_count), + task_pid_nr(current), current->comm); /* Evaluate filter for new known-outcome syscalls */ seccomp_update_bitmaps(filter, pagepair); @@ -2419,6 +2519,21 @@ static int __init seccomp_sysctl_init(void) pr_warn("sysctl registration failed\n"); else kmemleak_not_leak(hdr); +#ifndef SECCOMP_ARCH + pr_info("arch lacks support for constant action bitmaps\n"); +#else + pr_info("NR_syscalls: %d\n", NR_syscalls); + pr_info("arch: 0x%x\n", SECCOMP_ARCH); +#ifdef CONFIG_COMPAT + pr_info("compat arch: 0x%x\n", SECCOMP_ARCH_COMPAT); +#endif +#ifdef SECCOMP_MULTIPLEXED_SYSCALL_TABLE_ARCH + pr_info("multiplex arch: 0x%x (mask: 0x%x)\n", + SECCOMP_MULTIPLEXED_SYSCALL_TABLE_ARCH, + SECCOMP_MULTIPLEXED_SYSCALL_TABLE_MASK); +#endif +#endif + pr_info("sizeof(struct seccomp_bitmaps): %zu\n", sizeof(struct seccomp_bitmaps)); return 0; } -- 2.25.1