diff mbox

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

Message ID 20131106205710.GN4994@outflux.net
State New
Headers show

Commit Message

Kees Cook Nov. 6, 2013, 8:57 p.m. UTC
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@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(-)

Comments

Andy Whitcroft Nov. 7, 2013, 2:32 p.m. UTC | #1
On Wed, Nov 06, 2013 at 12:57:10PM -0800, Kees Cook wrote:
> 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.

Could you drop in a pointer to this test suite for us, we might well be
interested in using that.

Could you confirm that this should not affect operations but is mostly
fixing up holes that might be exploitable.

Otherwise I assume what this does is bring what is in Precise up to the
same level as mainline, allowing us to guarentee that more modern
consumers of this interface will work consistantly on all releases back
to Precice.

Thanks!

-apw
Kees Cook Nov. 7, 2013, 5:21 p.m. UTC | #2
Hi,

On Thu, Nov 7, 2013 at 6:32 AM, Andy Whitcroft <apw@canonical.com> wrote:
> On Wed, Nov 06, 2013 at 12:57:10PM -0800, Kees Cook wrote:
>> 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.
>
> Could you drop in a pointer to this test suite for us, we might well be
> interested in using that.

Sure! I actually already added that to the bug[1] report, since that
seemed the right place to collect the SRU details. Repeating it here
for good measure:

[Test Case]
git clone https://github.com/redpig/seccomp.git
cd seccomp/tests
make
./seccomp_bpf_tests
All tests should pass

> Could you confirm that this should not affect operations but is mostly
> fixing up holes that might be exploitable.

It does not change x86 operation, and does not fix exploitable holes.
It simply makes seccomp-bpf available at all on ARM. Before this
patch, seccomp-bpf couldn't be used on ARM. The driving motivation
here is to get Chrome on ARM on Precise making use of its full
sandboxing capabilities.

> Otherwise I assume what this does is bring what is in Precise up to the
> same level as mainline, allowing us to guarentee that more modern
> consumers of this interface will work consistantly on all releases back
> to Precice.

Correct -- in the core seccomp, it fixes 1 extremely minor difference
between Precise and mainline (the action masks), but that change has
no behavioral difference for "real" seccomp filters, and the old
situation posed no risk to the system for a "bad" seccomp filter. It
was simply noticed during the much more strict test case execution.

Besides that, it just wires up everything that is required on ARM to
call into seccomp correctly.

-Kees

[1] https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1183616
Tim Gardner Nov. 8, 2013, 9:19 p.m. UTC | #3
Bad news. This is the highbank flavour compiled on native armhf.

kernel/seccomp.c:28:25: fatal error: asm/syscall.h: No such file or
directory
compilation terminated.
make[1]: *** [kernel/seccomp.o] Error 1
make: *** [_module_kernel] Error 2
Kees Cook Nov. 8, 2013, 9:23 p.m. UTC | #4
On Fri, Nov 8, 2013 at 1:19 PM, Tim Gardner <tim.gardner@canonical.com> wrote:
> Bad news. This is the highbank flavour compiled on native armhf.

Errrg.

> kernel/seccomp.c:28:25: fatal error: asm/syscall.h: No such file or
> directory
> compilation terminated.
> make[1]: *** [kernel/seccomp.o] Error 1
> make: *** [_module_kernel] Error 2
> --
> Tim Gardner tim.gardner@canonical.com

Did all the syscall backporting work from the main Ubuntu kernel tree
not end up in the highbank tree?

Regardless, if you can point me to the tree, I can find the missing commits.

-Kees
Tim Gardner Nov. 8, 2013, 9:33 p.m. UTC | #5
On 11/08/2013 01:23 PM, Kees Cook wrote:
> On Fri, Nov 8, 2013 at 1:19 PM, Tim Gardner <tim.gardner@canonical.com> wrote:
>> Bad news. This is the highbank flavour compiled on native armhf.
> 
> Errrg.
> 
>> kernel/seccomp.c:28:25: fatal error: asm/syscall.h: No such file or
>> directory
>> compilation terminated.
>> make[1]: *** [kernel/seccomp.o] Error 1
>> make: *** [_module_kernel] Error 2
>> --
>> Tim Gardner tim.gardner@canonical.com
> 
> Did all the syscall backporting work from the main Ubuntu kernel tree
> not end up in the highbank tree?
> 
> Regardless, if you can point me to the tree, I can find the missing commits.
> 
> -Kees
> 

git://kernel.ubuntu.com/ubuntu/ubuntu-precise.git
Kees Cook Nov. 8, 2013, 9:58 p.m. UTC | #6
On Fri, Nov 8, 2013 at 1:33 PM, Tim Gardner <tim.gardner@canonical.com> wrote:
> On 11/08/2013 01:23 PM, Kees Cook wrote:
>> On Fri, Nov 8, 2013 at 1:19 PM, Tim Gardner <tim.gardner@canonical.com> wrote:
>>> Bad news. This is the highbank flavour compiled on native armhf.
>>
>> Errrg.
>>
>>> kernel/seccomp.c:28:25: fatal error: asm/syscall.h: No such file or
>>> directory
>>> compilation terminated.
>>> make[1]: *** [kernel/seccomp.o] Error 1
>>> make: *** [_module_kernel] Error 2
>>> --
>>> Tim Gardner tim.gardner@canonical.com
>>
>> Did all the syscall backporting work from the main Ubuntu kernel tree
>> not end up in the highbank tree?
>>
>> Regardless, if you can point me to the tree, I can find the missing commits.
>>
>> -Kees
>>
>
> git://kernel.ubuntu.com/ubuntu/ubuntu-precise.git

That is very odd. I have 2 commits in my check out of that tree that I
don't see in there. Perhaps I was building on my prior attempt and
didn't realize it. Ugh, yeah, looks like I accidentally pulled in two
patches months ago in my "master" check out. One moment, I'll clean
this up and send a pull request with the 3 pieces. Sorry about that!

-Kees
Andy Whitcroft Nov. 10, 2013, 1:58 p.m. UTC | #7
On Thu, Nov 07, 2013 at 09:21:40AM -0800, Kees Cook wrote:

> Sure! I actually already added that to the bug[1] report, since that
> seemed the right place to collect the SRU details. Repeating it here
> for good measure:
> 
> [Test Case]
> git clone https://github.com/redpig/seccomp.git
> cd seccomp/tests
> make
> ./seccomp_bpf_tests
> All tests should pass
> 
> > Could you confirm that this should not affect operations but is mostly
> > fixing up holes that might be exploitable.
> 
> It does not change x86 operation, and does not fix exploitable holes.
> It simply makes seccomp-bpf available at all on ARM. Before this
> patch, seccomp-bpf couldn't be used on ARM. The driving motivation
> here is to get Chrome on ARM on Precise making use of its full
> sandboxing capabilities.
> 
> > Otherwise I assume what this does is bring what is in Precise up to the
> > same level as mainline, allowing us to guarentee that more modern
> > consumers of this interface will work consistantly on all releases back
> > to Precice.
> 
> Correct -- in the core seccomp, it fixes 1 extremely minor difference
> between Precise and mainline (the action masks), but that change has
> no behavioral difference for "real" seccomp filters, and the old
> situation posed no risk to the system for a "bad" seccomp filter. It
> was simply noticed during the much more strict test case execution.
> 
> Besides that, it just wires up everything that is required on ARM to
> call into seccomp correctly.
> 
> -Kees
> 
> [1] https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1183616

Thanks for all those juicy details.  Just what I was trying to
understand.

-apw
diff mbox

Patch

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))