aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAKASHI Takahiro <takahiro.akashi@linaro.org>2014-09-04 16:01:08 +0100
committerDaniel Rosenberg <drosen@google.com>2015-01-12 16:49:10 -0800
commitf1777808cb2692d5863a8598a7dbe69db299c62d (patch)
tree49ba0a308852a9580b27615a34e36faf30d211e4
parent440668e690d024882f630b193ea9b27969c273df (diff)
arm64: add seccomp support
Note: This patch is from v6 of Takahiro's proposed "arm64: add seccomp support" patchset (leecam@google.com) secure_computing() is called first in syscall_trace_enter() so that a system call will be aborted quickly without doing succeeding syscall tracing, contrary to other cases, if seccomp rules deny that system call. On compat task, syscall numbers for system calls allowed in seccomp mode 1 are different from those on normal tasks, and so _NR_seccomp_xxx_32's need to be redefined. Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org> Conflicts: arch/arm64/Kconfig arch/arm64/kernel/entry.S Change-Id: I5ec44507d7e536df7ec9d62d30a418c26ef15100
-rw-r--r--arch/arm64/Kconfig14
-rw-r--r--arch/arm64/include/asm/ptrace.h1
-rw-r--r--arch/arm64/include/asm/seccomp.h25
-rw-r--r--arch/arm64/include/asm/unistd.h3
-rw-r--r--arch/arm64/kernel/entry.S2
-rw-r--r--arch/arm64/kernel/ptrace.c5
6 files changed, 50 insertions, 0 deletions
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 2a86113299dd..0b52c82fd2ab 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -29,6 +29,7 @@ config ARM64
select HARDIRQS_SW_RESEND
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_JUMP_LABEL
+ select HAVE_ARCH_SECCOMP_FILTER
select HAVE_ARCH_TRACEHOOK
select HAVE_DEBUG_BUGVERBOSE
select HAVE_DEBUG_KMEMLEAK
@@ -287,6 +288,19 @@ config FORCE_MAX_ZONEORDER
default "14" if (ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
default "11"
+config SECCOMP
+ bool "Enable seccomp to safely compute untrusted bytecode"
+ ---help---
+ This kernel feature is useful for number crunching applications
+ that may need to compute untrusted bytecode during their
+ execution. By using pipes or other transports made available to
+ the process as file descriptors supporting the read/write
+ syscalls, it's possible to isolate those applications in
+ their own address space using seccomp. Once seccomp is
+ enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
+ and the task is only allowed to execute a few safe syscalls
+ defined by each seccomp mode.
+
endmenu
menu "Boot options"
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index 1eae0b0b784a..ad084b7fd5c3 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -67,6 +67,7 @@
* with ptrace(PTRACE_SET_SYSCALL)
*/
#define RET_SKIP_SYSCALL -1
+#define RET_SKIP_SYSCALL_TRACE -2
#define IS_SKIP_SYSCALL(no) ((int)(no & 0xffffffff) == -1)
#ifndef __ASSEMBLY__
diff --git a/arch/arm64/include/asm/seccomp.h b/arch/arm64/include/asm/seccomp.h
new file mode 100644
index 000000000000..bec3a43f7b17
--- /dev/null
+++ b/arch/arm64/include/asm/seccomp.h
@@ -0,0 +1,25 @@
+/*
+ * arch/arm64/include/asm/seccomp.h
+ *
+ * Copyright (C) 2014 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi <at> linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _ASM_SECCOMP_H
+#define _ASM_SECCOMP_H
+
+#include <asm/unistd.h>
+
+#ifdef CONFIG_COMPAT
+#define __NR_seccomp_read_32 __NR_compat_read
+#define __NR_seccomp_write_32 __NR_compat_write
+#define __NR_seccomp_exit_32 __NR_compat_exit
+#define __NR_seccomp_sigreturn_32 __NR_compat_rt_sigreturn
+#endif /* CONFIG_COMPAT */
+
+#include <asm-generic/seccomp.h>
+
+#endif /* _ASM_SECCOMP_H */
diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
index 53f67c64a6af..2a3957faa702 100644
--- a/arch/arm64/include/asm/unistd.h
+++ b/arch/arm64/include/asm/unistd.h
@@ -30,6 +30,9 @@
* Compat syscall numbers used by the AArch64 kernel.
*/
#define __NR_compat_restart_syscall 0
+#define __NR_compat_exit 1
+#define __NR_compat_read 3
+#define __NR_compat_write 4
#define __NR_compat_sigreturn 119
#define __NR_compat_rt_sigreturn 173
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 86557327c8d7..243f6704120b 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -652,6 +652,8 @@ __sys_trace:
mov x0, sp
bl syscall_trace_enter
adr lr, __sys_trace_return // return address
+ cmp w0, #RET_SKIP_SYSCALL_TRACE // skip syscall and tracing?
+ b.eq ret_to_user
cmp w0, #RET_SKIP_SYSCALL // skip syscall?
b.eq __sys_trace_return_skipped
uxtw scno, w0 // syscall number (possibly new)
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 5a4246affe05..195e98501d8b 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -27,6 +27,7 @@
#include <linux/smp.h>
#include <linux/ptrace.h>
#include <linux/user.h>
+#include <linux/seccomp.h>
#include <linux/security.h>
#include <linux/init.h>
#include <linux/signal.h>
@@ -1106,6 +1107,10 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
{
unsigned int saved_syscallno = regs->syscallno;
+ /* Do the secure computing check first; failures should be fast. */
+ if (secure_computing(regs->syscallno) == -1)
+ return RET_SKIP_SYSCALL_TRACE;
+
if (test_thread_flag(TIF_SYSCALL_TRACE))
tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);