Skip to content

Commit 05d450a

Browse files
Song Shuaipalmer-dabbelt
authored andcommitted
riscv: Support RANDOMIZE_KSTACK_OFFSET
Inspired from arm64's implement -- commit 7091877 ("arm64: entry: Enable random_kstack_offset support") Add support of kernel stack offset randomization while handling syscall, the offset is defaultly limited by KSTACK_OFFSET_MAX() (i.e. 10 bits). In order to avoid trigger stack canaries (due to __builtin_alloca) and slowing down the entry path, use __no_stack_protector attribute to disable stack protector for do_trap_ecall_u() at the function level. Acked-by: Palmer Dabbelt <palmer@rivosinc.com> Reviewed-by: Kees Cook <keescook@chromium.org> Signed-off-by: Song Shuai <songshuaishuai@tinylab.org> Link: https://lore.kernel.org/r/20231109133751.212079-1-songshuaishuai@tinylab.org Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
1 parent dded618 commit 05d450a

File tree

2 files changed

+17
-1
lines changed

2 files changed

+17
-1
lines changed

arch/riscv/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ config RISCV
109109
select HAVE_ARCH_KGDB_QXFER_PKT
110110
select HAVE_ARCH_MMAP_RND_BITS if MMU
111111
select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
112+
select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
112113
select HAVE_ARCH_SECCOMP_FILTER
113114
select HAVE_ARCH_THREAD_STRUCT_WHITELIST
114115
select HAVE_ARCH_TRACEHOOK

arch/riscv/kernel/traps.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <linux/cpu.h>
77
#include <linux/kernel.h>
88
#include <linux/init.h>
9+
#include <linux/randomize_kstack.h>
910
#include <linux/sched.h>
1011
#include <linux/sched/debug.h>
1112
#include <linux/sched/signal.h>
@@ -310,7 +311,8 @@ asmlinkage __visible __trap_section void do_trap_break(struct pt_regs *regs)
310311
}
311312
}
312313

313-
asmlinkage __visible __trap_section void do_trap_ecall_u(struct pt_regs *regs)
314+
asmlinkage __visible __trap_section __no_stack_protector
315+
void do_trap_ecall_u(struct pt_regs *regs)
314316
{
315317
if (user_mode(regs)) {
316318
long syscall = regs->a7;
@@ -322,10 +324,23 @@ asmlinkage __visible __trap_section void do_trap_ecall_u(struct pt_regs *regs)
322324

323325
syscall = syscall_enter_from_user_mode(regs, syscall);
324326

327+
add_random_kstack_offset();
328+
325329
if (syscall >= 0 && syscall < NR_syscalls)
326330
syscall_handler(regs, syscall);
327331
else if (syscall != -1)
328332
regs->a0 = -ENOSYS;
333+
/*
334+
* Ultimately, this value will get limited by KSTACK_OFFSET_MAX(),
335+
* so the maximum stack offset is 1k bytes (10 bits).
336+
*
337+
* The actual entropy will be further reduced by the compiler when
338+
* applying stack alignment constraints: 16-byte (i.e. 4-bit) aligned
339+
* for RV32I or RV64I.
340+
*
341+
* The resulting 6 bits of entropy is seen in SP[9:4].
342+
*/
343+
choose_random_kstack_offset(get_random_u16());
329344

330345
syscall_exit_to_user_mode(regs);
331346
} else {

0 commit comments

Comments
 (0)