From 285fdfc5d9959a2104021b6bbdec39b8c26e99ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= Date: Tue, 20 Sep 2016 19:39:47 +0200 Subject: [PATCH 1/4] seccomp: Fix documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix struct seccomp_filter and seccomp_run_filters() signatures. Signed-off-by: Mickaël Salaün Cc: Andy Lutomirski Cc: James Morris Cc: Kees Cook Cc: Will Drewry Signed-off-by: Kees Cook --- kernel/seccomp.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/kernel/seccomp.c b/kernel/seccomp.c index 0db7c8a2afe2..494cba230ca0 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -41,8 +41,7 @@ * outside of a lifetime-guarded section. In general, this * is only needed for handling filters shared across tasks. * @prev: points to a previously installed, or inherited, filter - * @len: the number of instructions in the program - * @insnsi: the BPF program instructions to evaluate + * @prog: the BPF program to evaluate * * seccomp_filter objects are organized in a tree linked via the @prev * pointer. For any task, it appears to be a singly-linked list starting @@ -168,8 +167,8 @@ static int seccomp_check_filter(struct sock_filter *filter, unsigned int flen) } /** - * seccomp_run_filters - evaluates all seccomp filters against @syscall - * @syscall: number of the current system call + * seccomp_run_filters - evaluates all seccomp filters against @sd + * @sd: optional seccomp data to be passed to filters * * Returns valid seccomp BPF response codes. */ From 0af04ba5640dd6318f117a9fcbfde886516a0220 Mon Sep 17 00:00:00 2001 From: Ricky Zhou Date: Thu, 13 Oct 2016 10:29:14 -0700 Subject: [PATCH 2/4] samples/seccomp: Fix hostprogs variable In f6041c1d, a separate SAMPLES_SECCOMP option was added. This changed hostprogs-y to hostprogs-m, so adjust it. Signed-off-by: Ricky Zhou Signed-off-by: Kees Cook --- samples/seccomp/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/seccomp/Makefile b/samples/seccomp/Makefile index ae7ff6f24f36..bf7cc6b0dc19 100644 --- a/samples/seccomp/Makefile +++ b/samples/seccomp/Makefile @@ -36,13 +36,13 @@ HOSTLOADLIBES_bpf-direct += $(MFLAG) HOSTLOADLIBES_bpf-fancy += $(MFLAG) HOSTLOADLIBES_dropper += $(MFLAG) endif -always := $(hostprogs-y) +always := $(hostprogs-m) else # MIPS system calls are defined based on the -mabi that is passed # to the toolchain which may or may not be a valid option # for the host toolchain. So disable tests if target architecture # is MIPS but the host isn't. ifndef CONFIG_MIPS -always := $(hostprogs-y) +always := $(hostprogs-m) endif endif From 1ff120504f8c322a03fbce035d99e29e741da725 Mon Sep 17 00:00:00 2001 From: Ricky Zhou Date: Thu, 13 Oct 2016 10:34:08 -0700 Subject: [PATCH 3/4] samples/seccomp: Enable PR_SET_NO_NEW_PRIVS in dropper Either CAP_SYS_ADMIN or PR_SET_NO_NEW_PRIVS is required to enable seccomp. This allows samples/seccomp/dropper to be run without CAP_SYS_ADMIN. Signed-off-by: Ricky Zhou Signed-off-by: Kees Cook --- samples/seccomp/dropper.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/samples/seccomp/dropper.c b/samples/seccomp/dropper.c index c69c347c7011..68325ca5e71c 100644 --- a/samples/seccomp/dropper.c +++ b/samples/seccomp/dropper.c @@ -11,7 +11,6 @@ * When run, returns the specified errno for the specified * system call number against the given architecture. * - * Run this one as root as PR_SET_NO_NEW_PRIVS is not called. */ #include @@ -42,8 +41,12 @@ static int install_filter(int nr, int arch, int error) .len = (unsigned short)(sizeof(filter)/sizeof(filter[0])), .filter = filter, }; + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { + perror("prctl(NO_NEW_PRIVS)"); + return 1; + } if (prctl(PR_SET_SECCOMP, 2, &prog)) { - perror("prctl"); + perror("prctl(PR_SET_SECCOMP)"); return 1; } return 0; From d881d25cf5bc2fafbbfb383a475278977e1bd55a Mon Sep 17 00:00:00 2001 From: Ricky Zhou Date: Thu, 13 Oct 2016 10:37:28 -0700 Subject: [PATCH 4/4] samples/seccomp: Support programs with >256 instructions Previously, the program size was incorrectly truncated to 8 bits, resulting in broken labels in large programs. Also changes the jump resolution loop to not rely on undefined behavior (making a pointer point before the filter array). Signed-off-by: Ricky Zhou Signed-off-by: Kees Cook --- samples/seccomp/bpf-helper.c | 38 ++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/samples/seccomp/bpf-helper.c b/samples/seccomp/bpf-helper.c index 05cb4d5ff9f5..1ef0f4d72898 100644 --- a/samples/seccomp/bpf-helper.c +++ b/samples/seccomp/bpf-helper.c @@ -18,41 +18,41 @@ int bpf_resolve_jumps(struct bpf_labels *labels, struct sock_filter *filter, size_t count) { - struct sock_filter *begin = filter; - __u8 insn = count - 1; + size_t i; - if (count < 1) + if (count < 1 || count > BPF_MAXINSNS) return -1; /* * Walk it once, backwards, to build the label table and do fixups. * Since backward jumps are disallowed by BPF, this is easy. */ - filter += insn; - for (; filter >= begin; --insn, --filter) { - if (filter->code != (BPF_JMP+BPF_JA)) + for (i = 0; i < count; ++i) { + size_t offset = count - i - 1; + struct sock_filter *instr = &filter[offset]; + if (instr->code != (BPF_JMP+BPF_JA)) continue; - switch ((filter->jt<<8)|filter->jf) { + switch ((instr->jt<<8)|instr->jf) { case (JUMP_JT<<8)|JUMP_JF: - if (labels->labels[filter->k].location == 0xffffffff) { + if (labels->labels[instr->k].location == 0xffffffff) { fprintf(stderr, "Unresolved label: '%s'\n", - labels->labels[filter->k].label); + labels->labels[instr->k].label); return 1; } - filter->k = labels->labels[filter->k].location - - (insn + 1); - filter->jt = 0; - filter->jf = 0; + instr->k = labels->labels[instr->k].location - + (offset + 1); + instr->jt = 0; + instr->jf = 0; continue; case (LABEL_JT<<8)|LABEL_JF: - if (labels->labels[filter->k].location != 0xffffffff) { + if (labels->labels[instr->k].location != 0xffffffff) { fprintf(stderr, "Duplicate label use: '%s'\n", - labels->labels[filter->k].label); + labels->labels[instr->k].label); return 1; } - labels->labels[filter->k].location = insn; - filter->k = 0; /* fall through */ - filter->jt = 0; - filter->jf = 0; + labels->labels[instr->k].location = offset; + instr->k = 0; /* fall through */ + instr->jt = 0; + instr->jf = 0; continue; } }