Skip to content

Commit 69049d5

Browse files
Merge branch 'next/seccomp' into for-next
2 parents a99d808 + 5340627 commit 69049d5

File tree

6 files changed

+70
-4
lines changed

6 files changed

+70
-4
lines changed

arch/riscv/Kconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ config RISCV
3131
select GENERIC_SMP_IDLE_THREAD
3232
select GENERIC_ATOMIC64 if !64BIT
3333
select HAVE_ARCH_AUDITSYSCALL
34+
select HAVE_ARCH_SECCOMP_FILTER
3435
select HAVE_ASM_MODVERSIONS
3536
select HAVE_MEMBLOCK_NODE_MAP
3637
select HAVE_DMA_CONTIGUOUS
@@ -272,6 +273,19 @@ menu "Kernel features"
272273

273274
source "kernel/Kconfig.hz"
274275

276+
config SECCOMP
277+
bool "Enable seccomp to safely compute untrusted bytecode"
278+
help
279+
This kernel feature is useful for number crunching applications
280+
that may need to compute untrusted bytecode during their
281+
execution. By using pipes or other transports made available to
282+
the process as file descriptors supporting the read/write
283+
syscalls, it's possible to isolate those applications in
284+
their own address space using seccomp. Once seccomp is
285+
enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
286+
and the task is only allowed to execute a few safe syscalls
287+
defined by each seccomp mode.
288+
275289
endmenu
276290

277291
menu "Boot options"

arch/riscv/include/asm/seccomp.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
3+
#ifndef _ASM_SECCOMP_H
4+
#define _ASM_SECCOMP_H
5+
6+
#include <asm/unistd.h>
7+
8+
#include <asm-generic/seccomp.h>
9+
10+
#endif /* _ASM_SECCOMP_H */

arch/riscv/include/asm/thread_info.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,18 +75,21 @@ struct thread_info {
7575
#define TIF_MEMDIE 5 /* is terminating due to OOM killer */
7676
#define TIF_SYSCALL_TRACEPOINT 6 /* syscall tracepoint instrumentation */
7777
#define TIF_SYSCALL_AUDIT 7 /* syscall auditing */
78+
#define TIF_SECCOMP 8 /* syscall secure computing */
7879

7980
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
8081
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
8182
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
8283
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
8384
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
8485
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
86+
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
8587

8688
#define _TIF_WORK_MASK \
8789
(_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NEED_RESCHED)
8890

8991
#define _TIF_SYSCALL_WORK \
90-
(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT)
92+
(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT | \
93+
_TIF_SECCOMP)
9194

9295
#endif /* _ASM_RISCV_THREAD_INFO_H */

arch/riscv/kernel/entry.S

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,25 @@ check_syscall_nr:
226226
/* Check to make sure we don't jump to a bogus syscall number. */
227227
li t0, __NR_syscalls
228228
la s0, sys_ni_syscall
229-
/* Syscall number held in a7 */
230-
bgeu a7, t0, 1f
229+
/*
230+
* The tracer can change syscall number to valid/invalid value.
231+
* We use syscall_set_nr helper in syscall_trace_enter thus we
232+
* cannot trust the current value in a7 and have to reload from
233+
* the current task pt_regs.
234+
*/
235+
REG_L a7, PT_A7(sp)
236+
/*
237+
* Syscall number held in a7.
238+
* If syscall number is above allowed value, redirect to ni_syscall.
239+
*/
240+
bge a7, t0, 1f
241+
/*
242+
* Check if syscall is rejected by tracer or seccomp, i.e., a7 == -1.
243+
* If yes, we pretend it was executed.
244+
*/
245+
li t1, -1
246+
beq a7, t1, ret_from_syscall_rejected
247+
/* Call syscall */
231248
la s0, sys_call_table
232249
slli t0, a7, RISCV_LGPTR
233250
add s0, s0, t0
@@ -238,6 +255,12 @@ check_syscall_nr:
238255
ret_from_syscall:
239256
/* Set user a0 to kernel a0 */
240257
REG_S a0, PT_A0(sp)
258+
/*
259+
* We didn't execute the actual syscall.
260+
* Seccomp already set return value for the current task pt_regs.
261+
* (If it was configured with SECCOMP_RET_ERRNO/TRACE)
262+
*/
263+
ret_from_syscall_rejected:
241264
/* Trace syscalls, but only if requested by the user. */
242265
REG_L t0, TASK_TI_FLAGS(tp)
243266
andi t0, t0, _TIF_SYSCALL_WORK

arch/riscv/kernel/ptrace.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,16 @@ __visible void do_syscall_trace_enter(struct pt_regs *regs)
154154
if (tracehook_report_syscall_entry(regs))
155155
syscall_set_nr(current, regs, -1);
156156

157+
/*
158+
* Do the secure computing after ptrace; failures should be fast.
159+
* If this fails we might have return value in a0 from seccomp
160+
* (via SECCOMP_RET_ERRNO/TRACE).
161+
*/
162+
if (secure_computing(NULL) == -1) {
163+
syscall_set_nr(current, regs, -1);
164+
return;
165+
}
166+
157167
#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
158168
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
159169
trace_sys_enter(regs, syscall_get_nr(current, regs));

tools/testing/selftests/seccomp/seccomp_bpf.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ struct seccomp_data {
112112
# define __NR_seccomp 383
113113
# elif defined(__aarch64__)
114114
# define __NR_seccomp 277
115+
# elif defined(__riscv)
116+
# define __NR_seccomp 277
115117
# elif defined(__hppa__)
116118
# define __NR_seccomp 338
117119
# elif defined(__powerpc__)
@@ -1587,6 +1589,10 @@ TEST_F(TRACE_poke, getpid_runs_normally)
15871589
# define ARCH_REGS struct user_pt_regs
15881590
# define SYSCALL_NUM regs[8]
15891591
# define SYSCALL_RET regs[0]
1592+
#elif defined(__riscv) && __riscv_xlen == 64
1593+
# define ARCH_REGS struct user_regs_struct
1594+
# define SYSCALL_NUM a7
1595+
# define SYSCALL_RET a0
15901596
#elif defined(__hppa__)
15911597
# define ARCH_REGS struct user_regs_struct
15921598
# define SYSCALL_NUM gr[20]
@@ -1676,7 +1682,7 @@ void change_syscall(struct __test_metadata *_metadata,
16761682
EXPECT_EQ(0, ret) {}
16771683

16781684
#if defined(__x86_64__) || defined(__i386__) || defined(__powerpc__) || \
1679-
defined(__s390__) || defined(__hppa__)
1685+
defined(__s390__) || defined(__hppa__) || defined(__riscv)
16801686
{
16811687
regs.SYSCALL_NUM = syscall;
16821688
}

0 commit comments

Comments
 (0)