Add full seccomp BPF filter generation.
This CL uses the mechanism to generate filter sections from
policy strings and builds a complete filter by first
validating the arch and loading the syscall number, then
checking against all syscalls listed in the policy file, and
executing the argument filters if necessary.
BUG=chromium-os:25429
BUG=chromium-os:27878
TEST=syscall_filter_unittest
CQ-DEPEND=I3a4334a3c568178e19b18e7f3ed97517b03afd1b
Change-Id: I13a9b22ac8d55f02d5a77b5beedb955386b63723
Reviewed-on: https://gerrit.chromium.org/gerrit/19007
Tested-by: Jorge Lucangeli Obes <jorgelo@chromium.org>
Reviewed-by: Kees Cook <keescook@chromium.org>
Commit-Ready: Jorge Lucangeli Obes <jorgelo@chromium.org>
Reviewed-by: Will Drewry <wad@chromium.org>
diff --git a/bpf.c b/bpf.c
index 780f4e0..a0b6d3f 100644
--- a/bpf.c
+++ b/bpf.c
@@ -10,11 +10,7 @@
#include "bpf.h"
-/* Common jump targets. */
-#define NEXT 0
-#define SKIP 1
-#define SKIPN(_n) (_n)
-
+/* Basic BPF instruction setter. */
inline size_t set_bpf_instr(struct sock_filter *instr,
unsigned short code, unsigned int k,
unsigned char jt, unsigned char jf)
@@ -26,6 +22,35 @@
return 1U;
}
+/* Architecture validation. */
+size_t bpf_validate_arch(struct sock_filter *filter)
+{
+ struct sock_filter *curr_block = filter;
+ set_bpf_stmt(curr_block++, BPF_LD+BPF_W+BPF_ABS, arch_nr);
+ set_bpf_jump(curr_block++,
+ BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, SKIP, NEXT);
+ set_bpf_ret_kill(curr_block++);
+ return curr_block - filter;
+}
+
+/* Syscall number eval functions. */
+size_t bpf_allow_syscall(struct sock_filter *filter, int nr)
+{
+ struct sock_filter *curr_block = filter;
+ set_bpf_jump(curr_block++, BPF_JMP+BPF_JEQ+BPF_K, nr, NEXT, SKIP);
+ set_bpf_stmt(curr_block++, BPF_RET+BPF_K, SECCOMP_RET_ALLOW);
+ return curr_block - filter;
+}
+
+size_t bpf_allow_syscall_args(struct sock_filter *filter,
+ int nr, unsigned int id)
+{
+ struct sock_filter *curr_block = filter;
+ set_bpf_jump(curr_block++, BPF_JMP+BPF_JEQ+BPF_K, nr, NEXT, SKIP);
+ set_bpf_jump_lbl(curr_block++, id);
+ return curr_block - filter;
+}
+
/* Size-aware arg loaders. */
#if defined(BITS32)
size_t bpf_load_arg(struct sock_filter *filter, int argidx)
@@ -72,7 +97,6 @@
#if defined(BITS32)
#define bpf_comp_jeq bpf_comp_jeq32
-
#elif defined(BITS64)
#define bpf_comp_jeq bpf_comp_jeq64
#endif
@@ -207,6 +231,9 @@
/* Free label strings. */
void free_label_strings(struct bpf_labels *labels)
{
+ if (labels->count == 0)
+ return;
+
struct __bpf_label *begin = labels->labels, *end;
end = begin + labels->count;