Skip to content

Commit c3ff2a5

Browse files
chleroympe
authored andcommitted
powerpc/32: add stack protector support
This functionality was tentatively added in the past (commit 6533b7c ("powerpc: Initial stack protector (-fstack-protector) support")) but had to be reverted (commit f257403 ("powerpc: Revert the initial stack protector support") because of GCC implementing it differently whether it had been built with libc support or not. Now, GCC offers the possibility to manually set the stack-protector mode (global or tls) regardless of libc support. This time, the patch selects HAVE_STACKPROTECTOR only if -mstack-protector-guard=tls is supported by GCC. On PPC32, as register r2 points to current task_struct at all time, the stack_canary located inside task_struct can be used directly by using the following GCC options: -mstack-protector-guard=tls -mstack-protector-guard-reg=r2 -mstack-protector-guard-offset=offsetof(struct task_struct, stack_canary)) The protector is disabled for prom_init and bootx_init as it is too early to handle it properly. $ echo CORRUPT_STACK > /sys/kernel/debug/provoke-crash/DIRECT [ 134.943666] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: lkdtm_CORRUPT_STACK+0x64/0x64 [ 134.943666] [ 134.955414] CPU: 0 PID: 283 Comm: sh Not tainted 4.18.0-s3k-dev-12143-ga3272be41209 torvalds#835 [ 134.963380] Call Trace: [ 134.965860] [c6615d60] [c001f76c] panic+0x118/0x260 (unreliable) [ 134.971775] [c6615dc0] [c001f654] panic+0x0/0x260 [ 134.976435] [c6615dd0] [c032c368] lkdtm_CORRUPT_STACK_STRONG+0x0/0x64 [ 134.982769] [c6615e00] [ffffffff] 0xffffffff Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
1 parent cd5ff94 commit c3ff2a5

File tree

6 files changed

+51
-0
lines changed

6 files changed

+51
-0
lines changed

arch/powerpc/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ config PPC
180180
select HAVE_ARCH_SECCOMP_FILTER
181181
select HAVE_ARCH_TRACEHOOK
182182
select HAVE_CBPF_JIT if !PPC64
183+
select HAVE_STACKPROTECTOR if $(cc-option,-mstack-protector-guard=tls) && PPC32
183184
select HAVE_CONTEXT_TRACKING if PPC64
184185
select HAVE_DEBUG_KMEMLEAK
185186
select HAVE_DEBUG_STACKOVERFLOW

arch/powerpc/Makefile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ KBUILD_LDFLAGS += -m elf$(BITS)$(LDEMULATION)
112112
KBUILD_ARFLAGS += --target=elf$(BITS)-$(GNUTARGET)
113113
endif
114114

115+
cflags-$(CONFIG_STACKPROTECTOR) += -mstack-protector-guard=tls
116+
cflags-$(CONFIG_STACKPROTECTOR) += -mstack-protector-guard-reg=r2
117+
115118
LDFLAGS_vmlinux-y := -Bstatic
116119
LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) := -pie
117120
LDFLAGS_vmlinux := $(LDFLAGS_vmlinux-y)
@@ -404,6 +407,13 @@ archclean:
404407

405408
archprepare: checkbin
406409

410+
ifdef CONFIG_STACKPROTECTOR
411+
prepare: stack_protector_prepare
412+
413+
stack_protector_prepare: prepare0
414+
$(eval KBUILD_CFLAGS += -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "TASK_CANARY") print $$3;}' include/generated/asm-offsets.h))
415+
endif
416+
407417
# Use the file '.tmp_gas_check' for binutils tests, as gas won't output
408418
# to stdout and these checks are run even on install targets.
409419
TOUT := .tmp_gas_check
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* GCC stack protector support.
4+
*
5+
*/
6+
7+
#ifndef _ASM_STACKPROTECTOR_H
8+
#define _ASM_STACKPROTECTOR_H
9+
10+
#include <linux/random.h>
11+
#include <linux/version.h>
12+
#include <asm/reg.h>
13+
#include <asm/current.h>
14+
15+
/*
16+
* Initialize the stackprotector canary value.
17+
*
18+
* NOTE: this must only be called from functions that never return,
19+
* and it must always be inlined.
20+
*/
21+
static __always_inline void boot_init_stack_canary(void)
22+
{
23+
unsigned long canary;
24+
25+
/* Try to get a semi random initial value. */
26+
canary = get_random_canary();
27+
canary ^= mftb();
28+
canary ^= LINUX_VERSION_CODE;
29+
canary &= CANARY_MASK;
30+
31+
current->stack_canary = canary;
32+
}
33+
34+
#endif /* _ASM_STACKPROTECTOR_H */

arch/powerpc/kernel/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ CFLAGS_prom_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
2020
CFLAGS_btext.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
2121
CFLAGS_prom.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
2222

23+
CFLAGS_prom_init.o += $(call cc-option, -fno-stack-protector)
24+
2325
ifdef CONFIG_FUNCTION_TRACER
2426
# Do not trace early boot code
2527
CFLAGS_REMOVE_cputable.o = $(CC_FLAGS_FTRACE)

arch/powerpc/kernel/asm-offsets.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ int main(void)
7979
{
8080
OFFSET(THREAD, task_struct, thread);
8181
OFFSET(MM, task_struct, mm);
82+
#ifdef CONFIG_STACKPROTECTOR
83+
OFFSET(TASK_CANARY, task_struct, stack_canary);
84+
#endif
8285
OFFSET(MMCONTEXTID, mm_struct, context.id);
8386
#ifdef CONFIG_PPC64
8487
DEFINE(SIGSEGV, SIGSEGV);

arch/powerpc/platforms/powermac/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# SPDX-License-Identifier: GPL-2.0
22
CFLAGS_bootx_init.o += -fPIC
3+
CFLAGS_bootx_init.o += $(call cc-option, -fno-stack-protector)
34

45
ifdef CONFIG_FUNCTION_TRACER
56
# Do not trace early boot code

0 commit comments

Comments
 (0)