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.h b/bpf.h
index 3759813..cff5b1a 100644
--- a/bpf.h
+++ b/bpf.h
@@ -10,6 +10,7 @@
#define BPF_H
#include <asm/bitsperlong.h> /* for __BITS_PER_LONG */
+#include <linux/audit.h>
#include <linux/filter.h>
#include <stddef.h>
#include <sys/user.h>
@@ -49,6 +50,26 @@
__u64 args[6];
};
+#define syscall_nr (offsetof(struct seccomp_data, nr))
+#define arch_nr (offsetof(struct seccomp_data, arch))
+
+#if defined(__i386__)
+#define ARCH_NR AUDIT_ARCH_I386
+#elif defined(__x86_64__)
+#define ARCH_NR AUDIT_ARCH_X86_64
+#elif defined(__arm__)
+/*
+ * <linux/audit.h> includes <linux/elf-em.h>, which does not include EM_ARM.
+ * <linux/elf.h> only includes <asm/elf.h> if we're in the kernel.
+ */
+# ifndef EM_ARM
+# define EM_ARM 40
+# endif
+#define ARCH_NR AUDIT_ARCH_ARM
+#else
+#error "AUDIT_ARCH value unavailable"
+#endif
+
/* Size-dependent defines. */
#if defined(BITS32)
/* On 32 bits, comparisons take 2 instructions: 1 load arg, and 1 cmp. */
@@ -133,6 +154,9 @@
#define set_bpf_ret_allow(_block) \
set_bpf_stmt((_block), BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
+#define bpf_load_syscall_nr(_filter) \
+ set_bpf_stmt((_filter), BPF_LD+BPF_W+BPF_ABS, syscall_nr)
+
/* BPF label functions. */
int bpf_resolve_jumps(struct bpf_labels *labels,
struct sock_filter *filter, size_t count);
@@ -145,8 +169,15 @@
unsigned char jt, unsigned char jf);
/* Functions called by syscall_filter.c */
+#define ARCH_VALIDATION_LEN 3U
+#define ALLOW_SYSCALL_LEN 2U
+
size_t bpf_arg_comp(struct sock_filter **pfilter,
int op, int argidx, unsigned long c, unsigned int label_id);
+size_t bpf_validate_arch(struct sock_filter *filter);
+size_t bpf_allow_syscall(struct sock_filter *filter, int nr);
+size_t bpf_allow_syscall_args(struct sock_filter *filter,
+ int nr, unsigned int id);
/* Debug */
void dump_bpf_prog(struct sock_fprog *fprog);