summaryrefslogtreecommitdiff
path: root/arch/riscv/kernel
diff options
context:
space:
mode:
authorDavid Abdurachmanov <david.abdurachmanov@sifive.com>2019-10-04 17:12:22 -0700
committerPaul Walmsley <paul.walmsley@sifive.com>2019-10-29 11:32:10 -0700
commit5340627e3fe08030988bdda46dd86cd5d5fb7517 (patch)
treeb6c4e571320c67aaae6ade75feeee3420fcc55ac /arch/riscv/kernel
parent00a5bf3a8ca30d19f24219fc3cfb74f4eab3600d (diff)
riscv: add support for SECCOMP and SECCOMP_FILTER
This patch was extensively tested on Fedora/RISCV (applied by default on top of 5.2-rc7 kernel for <2 months). The patch was also tested with 5.3-rc on QEMU and SiFive Unleashed board. libseccomp (userspace) was rebased: https://github.com/seccomp/libseccomp/pull/134 Fully passes libseccomp regression testing (simulation and live). There is one failing kernel selftest: global.user_notification_signal v1 -> v2: - return immediately if secure_computing(NULL) returns -1 - fixed whitespace issues - add missing seccomp.h - remove patch #2 (solved now) - add riscv to seccomp kernel selftest Signed-off-by: David Abdurachmanov <david.abdurachmanov@sifive.com> Cc: keescook@chromium.org Cc: me@carlosedp.com Tested-by: Carlos de Paula <me@carlosedp.com> Reviewed-by: Kees Cook <keescook@chromium.org> Link: https://lore.kernel.org/linux-riscv/CAEn-LTp=ss0Dfv6J00=rCAy+N78U2AmhqJNjfqjr2FDpPYjxEQ@mail.gmail.com/ Link: https://lore.kernel.org/linux-riscv/CAJr-aD=UnCN9E_mdVJ2H5nt=6juRSWikZnA5HxDLQxXLbsRz-w@mail.gmail.com/ [paul.walmsley@sifive.com: cleaned up Cc: lines; fixed spelling and checkpatch issues; updated to apply] Signed-off-by: Paul Walmsley <paul.walmsley@sifive.com>
Diffstat (limited to 'arch/riscv/kernel')
-rw-r--r--arch/riscv/kernel/entry.S27
-rw-r--r--arch/riscv/kernel/ptrace.c10
2 files changed, 35 insertions, 2 deletions
diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index 8ca479831142..c68b987e623e 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -226,8 +226,25 @@ check_syscall_nr:
/* Check to make sure we don't jump to a bogus syscall number. */
li t0, __NR_syscalls
la s0, sys_ni_syscall
- /* Syscall number held in a7 */
- bgeu a7, t0, 1f
+ /*
+ * The tracer can change syscall number to valid/invalid value.
+ * We use syscall_set_nr helper in syscall_trace_enter thus we
+ * cannot trust the current value in a7 and have to reload from
+ * the current task pt_regs.
+ */
+ REG_L a7, PT_A7(sp)
+ /*
+ * Syscall number held in a7.
+ * If syscall number is above allowed value, redirect to ni_syscall.
+ */
+ bge a7, t0, 1f
+ /*
+ * Check if syscall is rejected by tracer or seccomp, i.e., a7 == -1.
+ * If yes, we pretend it was executed.
+ */
+ li t1, -1
+ beq a7, t1, ret_from_syscall_rejected
+ /* Call syscall */
la s0, sys_call_table
slli t0, a7, RISCV_LGPTR
add s0, s0, t0
@@ -238,6 +255,12 @@ check_syscall_nr:
ret_from_syscall:
/* Set user a0 to kernel a0 */
REG_S a0, PT_A0(sp)
+ /*
+ * We didn't execute the actual syscall.
+ * Seccomp already set return value for the current task pt_regs.
+ * (If it was configured with SECCOMP_RET_ERRNO/TRACE)
+ */
+ret_from_syscall_rejected:
/* Trace syscalls, but only if requested by the user. */
REG_L t0, TASK_TI_FLAGS(tp)
andi t0, t0, _TIF_SYSCALL_WORK
diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c
index 1252113ef8b2..0f84628b9385 100644
--- a/arch/riscv/kernel/ptrace.c
+++ b/arch/riscv/kernel/ptrace.c
@@ -154,6 +154,16 @@ __visible void do_syscall_trace_enter(struct pt_regs *regs)
if (tracehook_report_syscall_entry(regs))
syscall_set_nr(current, regs, -1);
+ /*
+ * Do the secure computing after ptrace; failures should be fast.
+ * If this fails we might have return value in a0 from seccomp
+ * (via SECCOMP_RET_ERRNO/TRACE).
+ */
+ if (secure_computing(NULL) == -1) {
+ syscall_set_nr(current, regs, -1);
+ return;
+ }
+
#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
trace_sys_enter(regs, syscall_get_nr(current, regs));