[Precise][SRU][PATCH] UBUNTU: SAUCE: backport ARM seccomp-bpf support

Kees Cook kees at ubuntu.com
Wed Nov 6 20:57:10 UTC 2013


This is a behavioral backport of the upstream ARM seccomp-bpf support,
with as few changes as possible. This passes the seccomp test suite on
both x86 and ARM.

There is very little difference in the TIF_SYSCALL_TRACE and TIF_SECCOMP
path in entry-common.S, so merge them into TIF_SYSCALL_WORK and move
seccomp into the syscall_trace() handler. (TIF_SECCOMP renumbered to fit
into an ARM instruction literal.)

The return value for secure_computing() is now checked and a -1 value will
result in the system call being skipped. An -ENOSYS is explicitly passed
for these skipped syscalls, which is something not done automatically
on ARM.

The ARM thread's syscall information is needed earlier for seccomp,
so its assignment has been moved up.

The SECCOMP_RET_ACTION mask has been adjusted to match upstream; this
change has no effect on real filters, but was needed to pass the strict
test cases.

BugLink: http://bugs.launchpad.net/bugs/1183616
Signed-off-by: Kees Cook <keescook at chromium.org>
---
 arch/arm/Kconfig                   |    1 +
 arch/arm/include/asm/thread_info.h |    5 ++++-
 arch/arm/kernel/entry-common.S     |   17 +++++------------
 arch/arm/kernel/ptrace.c           |   11 +++++++++--
 include/linux/seccomp.h            |    2 +-
 kernel/seccomp.c                   |    6 +++++-
 6 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index a78240d..0ae6743 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -12,6 +12,7 @@ config ARM
 	select HAVE_KPROBES if !XIP_KERNEL
 	select HAVE_KRETPROBES if (HAVE_KPROBES)
 	select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
+	select HAVE_ARCH_SECCOMP_FILTER
 	select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
 	select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL)
 	select HAVE_FUNCTION_GRAPH_TRACER if (!THUMB2_KERNEL)
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index 7b5cc8d..a483545 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -139,12 +139,12 @@ extern void vfp_flush_hwstate(struct thread_info *);
 #define TIF_NEED_RESCHED	1
 #define TIF_NOTIFY_RESUME	2	/* callback before returning to user */
 #define TIF_SYSCALL_TRACE	8
+#define TIF_SECCOMP		11	/* seccomp syscall filtering active */
 #define TIF_POLLING_NRFLAG	16
 #define TIF_USING_IWMMXT	17
 #define TIF_MEMDIE		18	/* is terminating due to OOM killer */
 #define TIF_FREEZE		19
 #define TIF_RESTORE_SIGMASK	20
-#define TIF_SECCOMP		21
 
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
@@ -156,6 +156,9 @@ extern void vfp_flush_hwstate(struct thread_info *);
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 
+/* Checks for any syscall work in entry-common.S */
+#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SECCOMP)
+
 /*
  * Change these and you break ASM code in entry-common.S
  */
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index b2a27b6..82f8fe1 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -433,17 +433,7 @@ ENTRY(vector_swi)
 	ldr	r10, [tsk, #TI_FLAGS]		@ check for syscall tracing
 	stmdb	sp!, {r4, r5}			@ push fifth and sixth args
 
-#ifdef CONFIG_SECCOMP
-	tst	r10, #_TIF_SECCOMP
-	beq	1f
-	mov	r0, scno
-	bl	__secure_computing	
-	add	r0, sp, #S_R0 + S_OFF		@ pointer to regs
-	ldmia	r0, {r0 - r3}			@ have to reload r0 - r3
-1:
-#endif
-
-	tst	r10, #_TIF_SYSCALL_TRACE		@ are we tracing syscalls?
+	tst	r10, #_TIF_SYSCALL_WORK		@ are we tracing syscalls?
 	bne	__sys_trace
 
 	cmp	scno, #NR_syscalls		@ check upper syscall limit
@@ -474,7 +464,10 @@ __sys_trace:
 	cmp	scno, #NR_syscalls		@ check upper syscall limit
 	ldmccia	r1, {r0 - r3}			@ have to reload r0 - r3
 	ldrcc	pc, [tbl, scno, lsl #2]		@ call sys_* routine
-	b	2b
+	cmp	scno, #-1			@ skip the syscall?
+	bne	2b
+	add	sp, sp, #S_OFF			@ restore stack
+	b	ret_slow_syscall
 
 __sys_trace_return:
 	str	r0, [sp, #S_R0 + S_OFF]!	@ save returned r0
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 90fa8b3..0ebff48 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -908,6 +908,15 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
 {
 	unsigned long ip;
 
+	current_thread_info()->syscall = scno;
+
+	/*
+	 * Only check seccomp on entry. Do the secure computing check first;
+	 * failures should be fast.
+	 */
+	if (why == 0 && secure_computing(scno) == -1)
+		return -1;
+
 	if (!test_thread_flag(TIF_SYSCALL_TRACE))
 		return scno;
 	if (!(current->ptrace & PT_PTRACED))
@@ -920,8 +929,6 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
 	ip = regs->ARM_ip;
 	regs->ARM_ip = why;
 
-	current_thread_info()->syscall = scno;
-
 	/* the 0x80 provides a way for the tracing parent to distinguish
 	   between a syscall stop and SIGTRAP delivery */
 	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index 306733e..41ff13b 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -25,7 +25,7 @@
 #define SECCOMP_RET_ALLOW	0x7fff0000U /* allow */
 
 /* Masks for the return value sections. */
-#define SECCOMP_RET_ACTION	0xffff0000U
+#define SECCOMP_RET_ACTION	0x7fff0000U
 #define SECCOMP_RET_DATA	0x0000ffffU
 
 /**
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index bc84054..533328d 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -414,8 +414,12 @@ int __secure_computing_int(int this_syscall)
 			goto skip;
 		case SECCOMP_RET_TRACE:
 			/* Skip these calls if there is no tracer. */
-			if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP))
+			if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) {
+				/* Make sure userspace sees an ENOSYS. */
+				syscall_set_return_value(current,
+					task_pt_regs(current), -ENOSYS, 0);
 				goto skip;
+			}
 			/* Allow the BPF to provide the event message */
 			ptrace_event(PTRACE_EVENT_SECCOMP, data);
 			if (fatal_signal_pending(current))
-- 
1.7.9.5


-- 
Kees Cook




More information about the kernel-team mailing list