riscv: Add STACKPROTECTOR supported
Subsystems (2)
[email protected]
maintainerPATCH v3 1/2 riscv: Add STACKPROTECTOR supported
From: Guo Ren <[email protected]>
The -fstack-protector & -fstack-protector-strong features are from gcc. The patch only add basic kernel support to stack-protector feature and some arch could have its own solution such as ARM64_PTR_AUTH.
After enabling STACKPROTECTOR and STACKPROTECTOR_STRONG, the .text size is expanded from 0x7de066 to 0x81fb32 (only 5%) to add canary checking code.
---
Change v2:
- Fixup rsicv32 compile warning
--- arch/riscv/Kconfig | 1 + arch/riscv/include/asm/stackprotector.h | 33 +++++++++++++++++++++++++++++++++ arch/riscv/kernel/process.c | 6 ++++++ 3 files changed, 40 insertions(+) create mode 100644 arch/riscv/include/asm/stackprotector.h
arch/riscv/Kconfig +1 -0
@@ -63,6 +63,7 @@ config RISCV select HAVE_PERF_EVENTS select HAVE_PERF_REGS select HAVE_PERF_USER_STACK_DUMP + select HAVE_STACKPROTECTOR select HAVE_SYSCALL_TRACEPOINTS select IRQ_DOMAIN select MODULES_USE_ELF_RELA if MODULES
arch/riscv/include/asm/stackprotector.h new file +33 -0
@@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _ASM_RISCV_STACKPROTECTOR_H +#define _ASM_RISCV_STACKPROTECTOR_H + +#include <linux/random.h> +#include <linux/version.h> +#include <asm/timex.h> + +extern unsigned long __stack_chk_guard; + +/* +* Initialize the stackprotector canary value. +* +* NOTE: this must only be called from functions that never return, +* and it must always be inlined. +*/ +static __always_inline void boot_init_stack_canary(void) +{ +unsigned long canary; +unsigned long tsc; + +/* Try to get a semi random initial value. */ +get_random_bytes (&canary,sizeof (canary)); + tsc =get_cycles (); + canary += tsc + (tsc <<BITS_PER_LONG /2 ); + canary ^=LINUX_VERSION_CODE ; + canary &=CANARY_MASK ; + + current->stack_canary = canary; + __stack_chk_guard = current->stack_canary; +} +#endif /* _ASM_RISCV_STACKPROTECTOR_H */
arch/riscv/kernel/process.c +6 -0
@@ -24,6 +24,12 @@ registerunsigned long gp_in_global __asm__("gp" ); +#ifdef CONFIG_STACKPROTECTOR +#include <linux/stackprotector.h> +unsigned long __stack_chk_guard__read_mostly ; +EXPORT_SYMBOL (__stack_chk_guard); +#endif + extern asmlinkage void ret_from_fork(void); extern asmlinkage void ret_from_kernel_thread(void);
Signature · 1 line
2.7.4
[email protected]
maintainerPATCH v3 2/2 riscv: Enable per-task stack canaries
From: Guo Ren <[email protected]>
This enables the use of per-task stack canary values if GCC has support for emitting the stack canary reference relative to the value of tp, which holds the task struct pointer in the riscv kernel.
After compare arm64 and x86 implementations, seems arm64's is more flexible and readable. The key point is how gcc get the offset of stack_canary from gs/el0_sp.
x86: Use a fix offset from gs, not flexible.
struct fixed_percpu_data {
/*
* GCC hardcodes the stack canary as %gs:40. Since the
* irq_stack is the object at %gs:0, we reserve the bottom
* 48 bytes of the irq stack for the canary.
*/
char gs_base[40]; // :(
unsigned long stack_canary;
};arm64: Use -mstack-protector-guard-offset & guard-reg
gcc options:
-mstack-protector-guard=sysreg -mstack-protector-guard-reg=sp_el0 -mstack-protector-guard-offset=xxx
riscv: Use -mstack-protector-guard-offset & guard-reg
gcc options:
-mstack-protector-guard=tls -mstack-protector-guard-reg=tp -mstack-protector-guard-offset=xxx
Here is riscv gcc's work [1].
[1] https://gcc.gnu.org/pipermail/gcc-patches/2020-July/549583.html
In the end, these codes are inserted by gcc before return:
* 0xffffffe00020b396 <+120>: ld a5,1008(tp) # 0x3f0 * 0xffffffe00020b39a <+124>: xor a5,a5,a4 * 0xffffffe00020b39c <+126>: mv a0,s5 * 0xffffffe00020b39e <+128>: bnez a5,0xffffffe00020b61c <_do_fork+766> 0xffffffe00020b3a2 <+132>: ld ra,136(sp) 0xffffffe00020b3a4 <+134>: ld s0,128(sp) 0xffffffe00020b3a6 <+136>: ld s1,120(sp) 0xffffffe00020b3a8 <+138>: ld s2,112(sp) 0xffffffe00020b3aa <+140>: ld s3,104(sp) 0xffffffe00020b3ac <+142>: ld s4,96(sp) 0xffffffe00020b3ae <+144>: ld s5,88(sp) 0xffffffe00020b3b0 <+146>: ld s6,80(sp) 0xffffffe00020b3b2 <+148>: ld s7,72(sp) 0xffffffe00020b3b4 <+150>: addi sp,sp,144 0xffffffe00020b3b6 <+152>: ret ... * 0xffffffe00020b61c <+766>: auipc ra,0x7f8 * 0xffffffe00020b620 <+770>: jalr -1764(ra) # 0xffffffe000a02f38 <__stack_chk_fail>
---
Change v2:
- Change to -mstack-protector-guard=tls for gcc final define
- Solve compile error by changing position of KBUILD_CFLAGS in Makefile
--- arch/riscv/Kconfig | 7 +++++++ arch/riscv/Makefile | 10 ++++++++++ arch/riscv/include/asm/stackprotector.h | 3 ++- arch/riscv/kernel/asm-offsets.c | 3 +++ arch/riscv/kernel/process.c | 2 +- 5 files changed, 23 insertions(+), 2 deletions(-)
arch/riscv/Kconfig +7 -0
@@ -394,6 +394,13 @@ config CMDLINE_FORCE endchoice +config CC_HAVE_STACKPROTECTOR_TLS + def_bool $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=tp -mstack-protector-guard-offset=0) + +config STACKPROTECTOR_PER_TASK + def_bool y + depends on STACKPROTECTOR && CC_HAVE_STACKPROTECTOR_TLS + endmenu config BUILTIN_DTB
arch/riscv/Makefile +10 -0
@@ -68,6 +68,16 @@ KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-relax) # architectures. It's faster to have GCC emit only aligned accesses. KBUILD_CFLAGS += $(call cc-option,-mstrict-align) +ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y) +prepare: stack_protector_prepare +stack_protector_prepare: prepare0 + $(eval KBUILD_CFLAGS += -mstack-protector-guard=tls \ + -mstack-protector-guard-reg=tp \ + -mstack-protector-guard-offset=$(shell \ + awk '{if ($$2 == "TSK_STACK_CANARY") print $$3;}' \ + include/generated/asm-offsets.h)) +endif + # arch specific predefines for sparse CHECKFLAGS += -D__riscv -D__riscv_xlen=$(BITS)
arch/riscv/include/asm/stackprotector.h +2 -1
@@ -28,6 +28,7 @@ static __always_inline void boot_init_stack_canary(void) canary &=CANARY_MASK ; current->stack_canary = canary; - __stack_chk_guard = current->stack_canary; +if (!IS_ENABLED (CONFIG_STACKPROTECTOR_PER_TASK )) + __stack_chk_guard = current->stack_canary; }#endif /* _ASM_RISCV_STACKPROTECTOR_H */
arch/riscv/kernel/asm-offsets.c +3 -0
@@ -29,6 +29,9 @@ void asm_offsets(void)OFFSET (TASK_THREAD_S11 , task_struct, thread.s[11 ]);OFFSET (TASK_THREAD_SP , task_struct, thread.sp);OFFSET (TASK_STACK , task_struct, stack); +#ifdef CONFIG_STACKPROTECTOR +OFFSET (TSK_STACK_CANARY , task_struct, stack_canary); +#endif OFFSET (TASK_TI , task_struct, thread_info);OFFSET (TASK_TI_FLAGS , task_struct, thread_info.flags);OFFSET (TASK_TI_PREEMPT_COUNT , task_struct, thread_info.preempt_count);
arch/riscv/kernel/process.c +1 -1
@@ -24,7 +24,7 @@ registerunsigned long gp_in_global __asm__("gp" ); -#ifdef CONFIG_STACKPROTECTOR +#if defined(CONFIG_STACKPROTECTOR ) && !defined(CONFIG_STACKPROTECTOR_PER_TASK )#include <linux/stackprotector.h> unsigned long __stack_chk_guard__read_mostly ;EXPORT_SYMBOL (__stack_chk_guard);
Signature · 1 line
2.7.4
Re: [PATCH v3 2/2] riscv: Enable per-task stack canaries
Quoted 136 lines · On Fri, Jul 10, 2020 at 04:19:58PM +0000, [email protected] wrote:
From: Guo Ren <[email protected]>
This enables the use of per-task stack canary values if GCC has support for emitting the stack canary reference relative to the value of tp, which holds the task struct pointer in the riscv kernel.
After compare arm64 and x86 implementations, seems arm64's is more flexible and readable. The key point is how gcc get the offset of
stack_canaryfrom gs/el0_sp.x86: Use a fix offset from gs, not flexible.
struct fixed_percpu_data { /* * GCC hardcodes the stack canary as %gs:40. Since the * irq_stack is the object at %gs:0, we reserve the bottom * 48 bytes of the irq stack for the canary. */ char gs_base[40]; // :( unsigned long stack_canary; };arm64: Use -mstack-protector-guard-offset & guard-reg
gcc options:
-mstack-protector-guard=sysreg -mstack-protector-guard-reg=sp_el0 -mstack-protector-guard-offset=xxxriscv: Use -mstack-protector-guard-offset & guard-reg
gcc options:
-mstack-protector-guard=tls -mstack-protector-guard-reg=tp -mstack-protector-guard-offset=xxxHere is riscv gcc's work [1].
[1] https://gcc.gnu.org/pipermail/gcc-patches/2020-July/549583.html
In the end, these codes are inserted by gcc before return:
* 0xffffffe00020b396 <+120>: ld a5,1008(tp) # 0x3f0 * 0xffffffe00020b39a <+124>: xor a5,a5,a4 * 0xffffffe00020b39c <+126>: mv a0,s5 * 0xffffffe00020b39e <+128>: bnez a5,0xffffffe00020b61c <_do_fork+766> 0xffffffe00020b3a2 <+132>: ld ra,136(sp) 0xffffffe00020b3a4 <+134>: ld s0,128(sp) 0xffffffe00020b3a6 <+136>: ld s1,120(sp) 0xffffffe00020b3a8 <+138>: ld s2,112(sp) 0xffffffe00020b3aa <+140>: ld s3,104(sp) 0xffffffe00020b3ac <+142>: ld s4,96(sp) 0xffffffe00020b3ae <+144>: ld s5,88(sp) 0xffffffe00020b3b0 <+146>: ld s6,80(sp) 0xffffffe00020b3b2 <+148>: ld s7,72(sp) 0xffffffe00020b3b4 <+150>: addi sp,sp,144 0xffffffe00020b3b6 <+152>: ret ... * 0xffffffe00020b61c <+766>: auipc ra,0x7f8 * 0xffffffe00020b620 <+770>: jalr -1764(ra) # 0xffffffe000a02f38 <__stack_chk_fail>Signed-off-by Guo Ren <[email protected]>Signed-off-by cooper <[email protected]>Cc cooper <[email protected]>Cc Kees Cook <[email protected]>---
Change v2:
- Change to -mstack-protector-guard=tls for gcc final define
- Solve compile error by changing position ofKBUILD_CFLAGSinMakefileSigned-off-by Guo Ren <[email protected]>--- arch/riscv/Kconfig | 7 +++++++ arch/riscv/Makefile | 10 ++++++++++ arch/riscv/include/asm/stackprotector.h | 3 ++- arch/riscv/kernel/asm-offsets.c | 3 +++ arch/riscv/kernel/process.c | 2 +- 5 files changed, 23 insertions(+), 2 deletions(-)arch/riscv/Kconfig +7
-0@@ -394,6 +394,13 @@ config CMDLINE_FORCE endchoice +config CC_HAVE_STACKPROTECTOR_TLS + def_bool $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=tp -mstack-protector-guard-offset=0) + +config STACKPROTECTOR_PER_TASK + def_bool y + depends on STACKPROTECTOR && CC_HAVE_STACKPROTECTOR_TLS + endmenu config BUILTIN_DTBarch/riscv/Makefile +10
-0@@ -68,6 +68,16 @@ KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-relax) # architectures. It's faster to have GCC emit only aligned accesses. KBUILD_CFLAGS += $(call cc-option,-mstrict-align) +ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y) +prepare: stack_protector_prepare +stack_protector_prepare: prepare0 + $(eval KBUILD_CFLAGS += -mstack-protector-guard=tls \ + -mstack-protector-guard-reg=tp \ + -mstack-protector-guard-offset=$(shell \ + awk '{if ($$2 == "TSK_STACK_CANARY") print $$3;}' \ + include/generated/asm-offsets.h)) +endif + # arch specific predefines for sparse CHECKFLAGS += -D__riscv -D__riscv_xlen=$(BITS)arch/riscv/include/asm/stackprotector.h +2
-1@@ -28,6 +28,7 @@ static __always_inline void boot_init_stack_canary(void) canary &=CANARY_MASK ; current->stack_canary = canary; - __stack_chk_guard = current->stack_canary; +if (!IS_ENABLED (CONFIG_STACKPROTECTOR_PER_TASK )) + __stack_chk_guard = current->stack_canary; }#endif /* _ASM_RISCV_STACKPROTECTOR_H */ arch/riscv/kernel/asm-offsets.c +0
-0
arch/riscv/kernel/asm-offsets.c void asm_offsets(void) · line 32
Quoted 4 lines
arch/riscv/kernel/asm-offsets.c +1
-0@@ -29,6 +29,9 @@ void asm_offsets(void)OFFSET (TASK_THREAD_S11 , task_struct, thread.s[11 ]);OFFSET (TASK_THREAD_SP , task_struct, thread.sp);OFFSET (TASK_STACK , task_struct, stack); +#ifdef CONFIG_STACKPROTECTOR
Should this be CONFIG_STACKPROTECTOR_PER_TASK ?
Quoted 21 lines
arch/riscv/kernel/asm-offsets.c +2
-0+OFFSET (TSK_STACK_CANARY , task_struct, stack_canary); +#endif OFFSET (TASK_TI , task_struct, thread_info);OFFSET (TASK_TI_FLAGS , task_struct, thread_info.flags);OFFSET (TASK_TI_PREEMPT_COUNT , task_struct, thread_info.preempt_count);arch/riscv/kernel/process.c +1
-1@@ -24,7 +24,7 @@ registerunsigned long gp_in_global __asm__("gp" ); -#ifdef CONFIG_STACKPROTECTOR +#if defined(CONFIG_STACKPROTECTOR ) && !defined(CONFIG_STACKPROTECTOR_PER_TASK )#include <linux/stackprotector.h> unsigned long __stack_chk_guard__read_mostly ;EXPORT_SYMBOL (__stack_chk_guard);Signature · 1 line
2.7.4
Signature · 1 line
Kees Cook
Guo Ren
maintainerRe: [PATCH v3 2/2] riscv: Enable per-task stack canaries
Hi Kees,
Quoted 136 lines · Kees Cook
Quoted 134 lines · On Fri, Jul 10, 2020 at 04:19:58PM +0000, [email protected] wrote:
From: Guo Ren <[email protected]>
This enables the use of per-task stack canary values if GCC has support for emitting the stack canary reference relative to the value of tp, which holds the task struct pointer in the riscv kernel.
After compare arm64 and x86 implementations, seems arm64's is more flexible and readable. The key point is how gcc get the offset of
stack_canaryfrom gs/el0_sp.x86: Use a fix offset from gs, not flexible.
struct fixed_percpu_data { /* * GCC hardcodes the stack canary as %gs:40. Since the * irq_stack is the object at %gs:0, we reserve the bottom * 48 bytes of the irq stack for the canary. */ char gs_base[40]; // :( unsigned long stack_canary; };arm64: Use -mstack-protector-guard-offset & guard-reg
gcc options:
-mstack-protector-guard=sysreg -mstack-protector-guard-reg=sp_el0 -mstack-protector-guard-offset=xxxriscv: Use -mstack-protector-guard-offset & guard-reg
gcc options:
-mstack-protector-guard=tls -mstack-protector-guard-reg=tp -mstack-protector-guard-offset=xxxHere is riscv gcc's work [1].
[1] https://gcc.gnu.org/pipermail/gcc-patches/2020-July/549583.html
In the end, these codes are inserted by gcc before return:
* 0xffffffe00020b396 <+120>: ld a5,1008(tp) # 0x3f0 * 0xffffffe00020b39a <+124>: xor a5,a5,a4 * 0xffffffe00020b39c <+126>: mv a0,s5 * 0xffffffe00020b39e <+128>: bnez a5,0xffffffe00020b61c <_do_fork+766> 0xffffffe00020b3a2 <+132>: ld ra,136(sp) 0xffffffe00020b3a4 <+134>: ld s0,128(sp) 0xffffffe00020b3a6 <+136>: ld s1,120(sp) 0xffffffe00020b3a8 <+138>: ld s2,112(sp) 0xffffffe00020b3aa <+140>: ld s3,104(sp) 0xffffffe00020b3ac <+142>: ld s4,96(sp) 0xffffffe00020b3ae <+144>: ld s5,88(sp) 0xffffffe00020b3b0 <+146>: ld s6,80(sp) 0xffffffe00020b3b2 <+148>: ld s7,72(sp) 0xffffffe00020b3b4 <+150>: addi sp,sp,144 0xffffffe00020b3b6 <+152>: ret ... * 0xffffffe00020b61c <+766>: auipc ra,0x7f8 * 0xffffffe00020b620 <+770>: jalr -1764(ra) # 0xffffffe000a02f38 <__stack_chk_fail>Signed-off-by Guo Ren <[email protected]>Signed-off-by cooper <[email protected]>Cc cooper <[email protected]>Cc Kees Cook <[email protected]>---
Change v2:
- Change to -mstack-protector-guard=tls for gcc final define
- Solve compile error by changing position ofKBUILD_CFLAGSinMakefileSigned-off-by Guo Ren <[email protected]>--- arch/riscv/Kconfig | 7 +++++++ arch/riscv/Makefile | 10 ++++++++++ arch/riscv/include/asm/stackprotector.h | 3 ++- arch/riscv/kernel/asm-offsets.c | 3 +++ arch/riscv/kernel/process.c | 2 +- 5 files changed, 23 insertions(+), 2 deletions(-)arch/riscv/Kconfig +7
-0@@ -394,6 +394,13 @@ config CMDLINE_FORCE endchoice +config CC_HAVE_STACKPROTECTOR_TLS + def_bool $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=tp -mstack-protector-guard-offset=0) + +config STACKPROTECTOR_PER_TASK + def_bool y + depends on STACKPROTECTOR && CC_HAVE_STACKPROTECTOR_TLS + endmenu config BUILTIN_DTBarch/riscv/Makefile +10
-0@@ -68,6 +68,16 @@ KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-relax) # architectures. It's faster to have GCC emit only aligned accesses. KBUILD_CFLAGS += $(call cc-option,-mstrict-align) +ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y) +prepare: stack_protector_prepare +stack_protector_prepare: prepare0 + $(eval KBUILD_CFLAGS += -mstack-protector-guard=tls \ + -mstack-protector-guard-reg=tp \ + -mstack-protector-guard-offset=$(shell \ + awk '{if ($$2 == "TSK_STACK_CANARY") print $$3;}' \ + include/generated/asm-offsets.h)) +endif + # arch specific predefines for sparse CHECKFLAGS += -D__riscv -D__riscv_xlen=$(BITS)arch/riscv/include/asm/stackprotector.h +2
-1@@ -28,6 +28,7 @@ static __always_inline void boot_init_stack_canary(void) canary &=CANARY_MASK ; current->stack_canary = canary; - __stack_chk_guard = current->stack_canary; +if (!IS_ENABLED (CONFIG_STACKPROTECTOR_PER_TASK )) + __stack_chk_guard = current->stack_canary; }#endif /* _ASM_RISCV_STACKPROTECTOR_H */ arch/riscv/kernel/asm-offsets.c +0
-1--- a/arch/riscv/kernel/asm-offsets.c
Quoted 8 lines
arch/riscv/kernel/asm-offsets.c void asm_offsets(void) · line 32
Quoted 6 lines
+++
b/arch/riscv/kernel/asm-offsets.carch/riscv/kernel/asm-offsets.c +1
-0@@ -29,6 +29,9 @@ void asm_offsets(void)OFFSET (TASK_THREAD_S11 , task_struct, thread.s[11 ]);OFFSET (TASK_THREAD_SP , task_struct, thread.sp);OFFSET (TASK_STACK , task_struct, stack); +#ifdef CONFIG_STACKPROTECTOR Should this be
CONFIG_STACKPROTECTOR_PER_TASK?
Yes, it's more accurate, Thx. I also send a patch [1] to arm64, and let's see how they reply?
[1] https://lore.kernel.org/linux-csky/[email protected]/T/#u
Signature · 4 lines
Best Regards Guo Ren ML: https://lore.kernel.org/linux-csky/
Re: [PATCH v3 2/2] riscv: Enable per-task stack canaries
In reply to [email protected]Quoted 60 lines · On Fri, 10 Jul 2020 09:19:58 PDT (-0700), [email protected] wrote:
From: Guo Ren <[email protected]>
This enables the use of per-task stack canary values if GCC has support for emitting the stack canary reference relative to the value of tp, which holds the task struct pointer in the riscv kernel.
After compare arm64 and x86 implementations, seems arm64's is more flexible and readable. The key point is how gcc get the offset of
stack_canaryfrom gs/el0_sp.x86: Use a fix offset from gs, not flexible.
struct fixed_percpu_data { /* * GCC hardcodes the stack canary as %gs:40. Since the * irq_stack is the object at %gs:0, we reserve the bottom * 48 bytes of the irq stack for the canary. */ char gs_base[40]; // :( unsigned long stack_canary; };arm64: Use -mstack-protector-guard-offset & guard-reg
gcc options:
-mstack-protector-guard=sysreg -mstack-protector-guard-reg=sp_el0 -mstack-protector-guard-offset=xxxriscv: Use -mstack-protector-guard-offset & guard-reg
gcc options:
-mstack-protector-guard=tls -mstack-protector-guard-reg=tp -mstack-protector-guard-offset=xxxHere is riscv gcc's work [1].
[1] https://gcc.gnu.org/pipermail/gcc-patches/2020-July/549583.html
In the end, these codes are inserted by gcc before return:
* 0xffffffe00020b396 <+120>: ld a5,1008(tp) # 0x3f0 * 0xffffffe00020b39a <+124>: xor a5,a5,a4 * 0xffffffe00020b39c <+126>: mv a0,s5 * 0xffffffe00020b39e <+128>: bnez a5,0xffffffe00020b61c <_do_fork+766> 0xffffffe00020b3a2 <+132>: ld ra,136(sp) 0xffffffe00020b3a4 <+134>: ld s0,128(sp) 0xffffffe00020b3a6 <+136>: ld s1,120(sp) 0xffffffe00020b3a8 <+138>: ld s2,112(sp) 0xffffffe00020b3aa <+140>: ld s3,104(sp) 0xffffffe00020b3ac <+142>: ld s4,96(sp) 0xffffffe00020b3ae <+144>: ld s5,88(sp) 0xffffffe00020b3b0 <+146>: ld s6,80(sp) 0xffffffe00020b3b2 <+148>: ld s7,72(sp) 0xffffffe00020b3b4 <+150>: addi sp,sp,144 0xffffffe00020b3b6 <+152>: ret ... * 0xffffffe00020b61c <+766>: auipc ra,0x7f8 * 0xffffffe00020b620 <+770>: jalr -1764(ra) # 0xffffffe000a02f38 <__stack_chk_fail>
Quoted 2 lines
Signed-off-by Guo Ren <[email protected]>Signed-off-by cooper <[email protected]>
IIRC we're required to use full names here. I'm assuming that's meant to be "Signed-off-by: Cooper Qu ...", and I know it's a bit procedural but I can't make that change.
Otherwise these two look good, the first one is on for-next. I can boot with a defconfig ammended with CONFIG_STACKPROTECTOR=y,
Thanks!
Quoted 96 lines
Cc cooper <[email protected]>Cc Kees Cook <[email protected]>---
Change v2:
- Change to -mstack-protector-guard=tls for gcc final define
- Solve compile error by changing position ofKBUILD_CFLAGSinMakefileSigned-off-by Guo Ren <[email protected]>--- arch/riscv/Kconfig | 7 +++++++ arch/riscv/Makefile | 10 ++++++++++ arch/riscv/include/asm/stackprotector.h | 3 ++- arch/riscv/kernel/asm-offsets.c | 3 +++ arch/riscv/kernel/process.c | 2 +- 5 files changed, 23 insertions(+), 2 deletions(-)arch/riscv/Kconfig +7
-0@@ -394,6 +394,13 @@ config CMDLINE_FORCE endchoice +config CC_HAVE_STACKPROTECTOR_TLS + def_bool $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=tp -mstack-protector-guard-offset=0) + +config STACKPROTECTOR_PER_TASK + def_bool y + depends on STACKPROTECTOR && CC_HAVE_STACKPROTECTOR_TLS + endmenu config BUILTIN_DTBarch/riscv/Makefile +10
-0@@ -68,6 +68,16 @@ KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-relax) # architectures. It's faster to have GCC emit only aligned accesses. KBUILD_CFLAGS += $(call cc-option,-mstrict-align) +ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y) +prepare: stack_protector_prepare +stack_protector_prepare: prepare0 + $(eval KBUILD_CFLAGS += -mstack-protector-guard=tls \ + -mstack-protector-guard-reg=tp \ + -mstack-protector-guard-offset=$(shell \ + awk '{if ($$2 == "TSK_STACK_CANARY") print $$3;}' \ + include/generated/asm-offsets.h)) +endif + # arch specific predefines for sparse CHECKFLAGS += -D__riscv -D__riscv_xlen=$(BITS)arch/riscv/include/asm/stackprotector.h +2
-1@@ -28,6 +28,7 @@ static __always_inline void boot_init_stack_canary(void) canary &=CANARY_MASK ; current->stack_canary = canary; - __stack_chk_guard = current->stack_canary; +if (!IS_ENABLED (CONFIG_STACKPROTECTOR_PER_TASK )) + __stack_chk_guard = current->stack_canary; }#endif /* _ASM_RISCV_STACKPROTECTOR_H */ arch/riscv/kernel/asm-offsets.c +3
-0@@ -29,6 +29,9 @@ void asm_offsets(void)OFFSET (TASK_THREAD_S11 , task_struct, thread.s[11 ]);OFFSET (TASK_THREAD_SP , task_struct, thread.sp);OFFSET (TASK_STACK , task_struct, stack); +#ifdef CONFIG_STACKPROTECTOR +OFFSET (TSK_STACK_CANARY , task_struct, stack_canary); +#endif OFFSET (TASK_TI , task_struct, thread_info);OFFSET (TASK_TI_FLAGS , task_struct, thread_info.flags);OFFSET (TASK_TI_PREEMPT_COUNT , task_struct, thread_info.preempt_count);arch/riscv/kernel/process.c +1
-1@@ -24,7 +24,7 @@ registerunsigned long gp_in_global __asm__("gp" ); -#ifdef CONFIG_STACKPROTECTOR +#if defined(CONFIG_STACKPROTECTOR ) && !defined(CONFIG_STACKPROTECTOR_PER_TASK )#include <linux/stackprotector.h> unsigned long __stack_chk_guard__read_mostly ;EXPORT_SYMBOL (__stack_chk_guard);
Re: [PATCH v3 2/2] riscv: Enable per-task stack canaries
Quoted 64 lines · Palmer Dabbelt
Quoted 60 lines · On Fri, 10 Jul 2020 09:19:58 PDT (-0700), [email protected] wrote:
From: Guo Ren <[email protected]>
This enables the use of per-task stack canary values if GCC has support for emitting the stack canary reference relative to the value of tp, which holds the task struct pointer in the riscv kernel.
After compare arm64 and x86 implementations, seems arm64's is more flexible and readable. The key point is how gcc get the offset of
stack_canaryfrom gs/el0_sp.x86: Use a fix offset from gs, not flexible.
struct
fixed_percpu_data{
/*
* GCC hardcodes the stack canary as %gs:40. Since the
*irq_stackis the object at %gs:0, we reserve the bottom
* 48 bytes of the irq stack for the canary.
*/
char gs_base[40]; // :(
unsigned longstack_canary;
};arm64: Use -mstack-protector-guard-offset & guard-reg gcc options:
-mstack-protector-guard=sysreg -mstack-protector-guard-reg=sp_el0 -mstack-protector-guard-offset=xxxriscv: Use -mstack-protector-guard-offset & guard-reg gcc options:
-mstack-protector-guard=tls -mstack-protector-guard-reg=tp -mstack-protector-guard-offset=xxxHere is riscv gcc's work [1].
[1] https://gcc.gnu.org/pipermail/gcc-patches/2020-July/549583.html
In the end, these codes are inserted by gcc before return:
*
0xffffffe00020b396<+120>: ld a5,1008(tp) #0x3f0
*0xffffffe00020b39a<+124>: xor a5,a5,a4
*0xffffffe00020b39c<+126>: mv a0,s5
*0xffffffe00020b39e<+128>: bnez a5,0xffffffe00020b61c <_do_fork+766>0xffffffe00020b3a2<+132>: ld ra,136(sp)
0xffffffe00020b3a4<+134>: ld s0,128(sp)
0xffffffe00020b3a6<+136>: ld s1,120(sp)
0xffffffe00020b3a8<+138>: ld s2,112(sp)
0xffffffe00020b3aa<+140>: ld s3,104(sp)
0xffffffe00020b3ac<+142>: ld s4,96(sp)
0xffffffe00020b3ae<+144>: ld s5,88(sp)
0xffffffe00020b3b0<+146>: ld s6,80(sp)
0xffffffe00020b3b2<+148>: ld s7,72(sp)
0xffffffe00020b3b4<+150>: addi sp,sp,144
0xffffffe00020b3b6<+152>: ret
...
*0xffffffe00020b61c<+766>: auipc ra,0x7f8
*0xffffffe00020b620<+770>: jalr -1764(ra) #0xffffffe000a02f38<__stack_chk_fail>Quoted 2 lines
Signed-off-by Guo Ren <[email protected]>Signed-off-by cooper <[email protected]>
Quoted 8 lines
IIRC we're required to use full names here. I'm assuming that's meant to be "Signed-off-by: Cooper Qu ...", and I know it's a bit procedural but I can't make that change.
Otherwise these two look good, the first one is on for-next. I can boot with a defconfig ammended with
CONFIG_STACKPROTECTOR=y,
Thanks!
Hi Palmer,
That's ok to change it to full names as follows.
Best Regards,
Cooper