Hi, seccomp syscall args are always passed as 64 bit integers, regardless of architecture. At the moment, we only inspect the low word. It's conceivable that this could be used to evade sandbox restrictions on syscall argumements, but we only permit a single syscall (socketcall) with argument inspection. Anyway, we should fix it. Can someone run their eyes over my amateur bpf? This also fixes argument inspection on 64-bit BE architectures. -d diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c index 2e1ed2c5..c3f8daa3 100644 --- a/sandbox-seccomp-filter.c +++ b/sandbox-seccomp-filter.c @@ -73,6 +73,16 @@ # define SECCOMP_FILTER_FAIL SECCOMP_RET_TRAP #endif /* SANDBOX_SECCOMP_FILTER_DEBUG */ +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define ARG_LO_OFFSET 0 +#define ARG_HI_OFFSET sizeof(uint32_t) +#elif __BYTE_ORDER == __BIG_ENDIAN +#define ARG_LO_OFFSET sizeof(uint32_t) +#define ARG_HI_OFFSET 0 +#else +#error "Unknown endianness" +#endif + /* Simple helpers to avoid manual errors (but larger BPF programs). */ #define SC_DENY(_nr, _errno) \ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_ ## _nr, 0, 1), \ @@ -81,10 +91,14 @@ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_ ## _nr, 0, 1), \ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) #define SC_ALLOW_ARG(_nr, _arg_nr, _arg_val) \ - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_ ## _nr, 0, 4), \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_ ## _nr, 0, 6), \ + /* verify high word of syscall argument is zero */ \ + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ + ARG_HI_OFFSET + offsetof(struct seccomp_data, args[(_arg_nr)])), \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 4), \ /* load first syscall argument */ \ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ - offsetof(struct seccomp_data, args[(_arg_nr)])), \ + ARG_LO_OFFSET + offsetof(struct seccomp_data, args[(_arg_nr)])), \ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_arg_val), 0, 1), \ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), \ /* reload syscall number; all rules expect it in accumulator */ \