Partially copied from commit df0698be14c66 ("ARM: stack protector:
change the canary value per task")
A new random value for the canary is stored in the task struct whenever
a new task is forked. This is meant to allow for different canary values
per task. On powerpc, GCC expects the canary value to be found in a global
variable called __stack_chk_guard. So this variable has to be updated
with the value stored in the task struct whenever a task switch occurs.
Because the variable GCC expects is global, this cannot work on SMP
unfortunately. So, on SMP, the same initial canary value is kept
throughout, making this feature a bit less effective although it is still
useful.
Cc: Nicolas Pitre <redacted>
Signed-off-by: Christophe Leroy <redacted>
---
arch/powerpc/kernel/asm-offsets.c | 3 +++
arch/powerpc/kernel/entry_32.S | 6 +++++-
2 files changed, 8 insertions(+), 1 deletion(-)
Partialy copied from commit c743f38013aef ("ARM: initial stack protector
(-fstack-protector) support")
This is the very basic stuff without the changing canary upon
task switch yet. Just the Kconfig option and a constant canary
value initialized at boot time.
Cc: Nicolas Pitre <redacted>
Signed-off-by: Christophe Leroy <redacted>
---
arch/powerpc/Kconfig | 1 +
arch/powerpc/include/asm/stackprotector.h | 38 +++++++++++++++++++++++++++++++
arch/powerpc/kernel/Makefile | 5 ++++
arch/powerpc/kernel/process.c | 6 +++++
4 files changed, 50 insertions(+)
create mode 100644 arch/powerpc/include/asm/stackprotector.h
@@ -0,0 +1,38 @@+/*+*GCCstackprotectorsupport.+*+*Stackprotectorworksbyputtingpredefinedpatternatthestartof+*thestackframeandverifyingthatithasn'tbeenoverwrittenwhen+*returningfromthefunction.Thepatterniscalledstackcanary+*andgccexpectsittobedefinedbyaglobalvariablecalled+*"__stack_chk_guard"onARM.ThisunfortunatelymeansthatonSMP+*wecannothaveadifferentcanaryvaluepertask.+*/++#ifndef _ASM_STACKPROTECTOR_H+#define _ASM_STACKPROTECTOR_H 1++#include<linux/random.h>+#include<linux/version.h>++externunsignedlong__stack_chk_guard;++/*+*Initializethestackprotectorcanaryvalue.+*+*NOTE:thismustonlybecalledfromfunctionsthatneverreturn,+*anditmustalwaysbeinlined.+*/+static__always_inlinevoidboot_init_stack_canary(void)+{+unsignedlongcanary;++/* Try to get a semi random initial value. */+get_random_bytes(&canary,sizeof(canary));+canary^=LINUX_VERSION_CODE;++current->stack_canary=canary;+__stack_chk_guard=current->stack_canary;+}++#endif /* _ASM_STACKPROTECTOR_H */
@@ -19,6 +19,11 @@ CFLAGS_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)CFLAGS_btext.o+=$(DISABLE_LATENT_ENTROPY_PLUGIN)CFLAGS_prom.o+=$(DISABLE_LATENT_ENTROPY_PLUGIN)+# -fstack-protector triggers protection checks in this code,+# but it is being used too early to link to meaningful stack_chk logic.+nossp_flags:=$(callcc-option,-fno-stack-protector)+CFLAGS_prom_init.o:=$(nossp_flags)+ifdef CONFIG_FUNCTION_TRACER# Do not trace early boot codeCFLAGS_REMOVE_cputable.o=-mno-sched-epilog$(CC_FLAGS_FTRACE)
On Friday, September 30, 2016, Christophe Leroy <christophe.leroy@c-s.fr
<mailto:christophe.leroy@c-s.fr>> wrote:
Add HAVE_CC_STACKPROTECTOR to powerpc. This is copied from ARM.
Not tested on PPC64, compile ok with ppc64_
Hi Christophe,
are you going to test it on ppc64? If not, I can take it
Thanks Denis, you are welcome to test it.
I don't have any ppc64 target, I only have mpc8xx and mpc83xx which both
are ppc32
Christophe
+ * we cannot have a different canary value per task.
+ */
+
+#ifndef _ASM_STACKPROTECTOR_H
+#define _ASM_STACKPROTECTOR_H 1
We usually just define it, not define it to 1.
+
+#include <linux/random.h>
+#include <linux/version.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;
+
+ /* Try to get a semi random initial value. */
+ get_random_bytes(&canary, sizeof(canary));
+ canary ^= LINUX_VERSION_CODE;
@@ -19,6 +19,11 @@ CFLAGS_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)CFLAGS_btext.o+=$(DISABLE_LATENT_ENTROPY_PLUGIN)CFLAGS_prom.o+=$(DISABLE_LATENT_ENTROPY_PLUGIN)+# -fstack-protector triggers protection checks in this code,+# but it is being used too early to link to meaningful stack_chk logic.+nossp_flags:=$(callcc-option,-fno-stack-protector)+CFLAGS_prom_init.o:=$(nossp_flags)
We've already assigned to CFLAGS_prom_init.o so I think you should be
using += not := shouldn't you?
Also it could just be a single line:
CFLAGS_prom_init.o += $(call cc-option, -fno-stack-protector)
cheers
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2016-11-17 11:27:29
Denis Kirjanov [off-list ref] writes:
On Friday, September 30, 2016, Christophe Leroy [off-list ref]
wrote:
quoted
Add HAVE_CC_STACKPROTECTOR to powerpc. This is copied from ARM.
Not tested on PPC64, compile ok with ppc64_
Hi Christophe,
are you going to test it on ppc64? If not, I can take it
Did you get around to testing it?
It seems to be working here:
root@mpe-ubuntu-le:/sys/kernel/debug/provoke-crash# echo CORRUPT_STACK > DIRECT
Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: c000000000671ed8
CPU: 1 PID: 3835 Comm: bash Not tainted 4.9.0-rc5-compiler_gcc-6.2.0-00075-gf41db6c7a3c8-dirty #464
Call Trace:
[c0000000dbf73a30] [c000000000541728] dump_stack+0xb8/0x100 (unreliable)
[c0000000dbf73a70] [c000000000219ba8] panic+0x14c/0x320
[c0000000dbf73b10] [c0000000000c27ec] __stack_chk_fail+0x2c/0x30
[c0000000dbf73b70] [c000000000671ed8] lkdtm_CORRUPT_STACK+0x88/0x90
[c0000000dbf73bf0] [6161616161616161] 0x6161616161616161
Rebooting in 10 seconds..
cheers
On 11/17/16, Michael Ellerman [off-list ref] wrote:
Denis Kirjanov [off-list ref] writes:
quoted
On Friday, September 30, 2016, Christophe Leroy [off-list ref]
wrote:
quoted
Add HAVE_CC_STACKPROTECTOR to powerpc. This is copied from ARM.
Not tested on PPC64, compile ok with ppc64_
Hi Christophe,
are you going to test it on ppc64? If not, I can take it
Not yet, I've broken my test machine :/ I need some time to recover
Did you get around to testing it?
It seems to be working here:
root@mpe-ubuntu-le:/sys/kernel/debug/provoke-crash# echo CORRUPT_STACK >
DIRECT
Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in:
c000000000671ed8
CPU: 1 PID: 3835 Comm: bash Not tainted
4.9.0-rc5-compiler_gcc-6.2.0-00075-gf41db6c7a3c8-dirty #464
Call Trace:
[c0000000dbf73a30] [c000000000541728] dump_stack+0xb8/0x100 (unreliable)
[c0000000dbf73a70] [c000000000219ba8] panic+0x14c/0x320
[c0000000dbf73b10] [c0000000000c27ec] __stack_chk_fail+0x2c/0x30
[c0000000dbf73b70] [c000000000671ed8] lkdtm_CORRUPT_STACK+0x88/0x90
[c0000000dbf73bf0] [6161616161616161] 0x6161616161616161
Rebooting in 10 seconds..
cheers
Le 17/11/2016 à 12:05, Michael Ellerman a écrit :
Hi Michael,
I took your comments into account in v2. Shame on me, I forgot to add
the list of changes from v1 to v2 in the commit log.
Christophe
+ * we cannot have a different canary value per task.
+ */
+
+#ifndef _ASM_STACKPROTECTOR_H
+#define _ASM_STACKPROTECTOR_H 1
We usually just define it, not define it to 1.
quoted
+
+#include <linux/random.h>
+#include <linux/version.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;
+
+ /* Try to get a semi random initial value. */
+ get_random_bytes(&canary, sizeof(canary));
+ canary ^= LINUX_VERSION_CODE;
@@ -19,6 +19,11 @@ CFLAGS_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)CFLAGS_btext.o+=$(DISABLE_LATENT_ENTROPY_PLUGIN)CFLAGS_prom.o+=$(DISABLE_LATENT_ENTROPY_PLUGIN)+# -fstack-protector triggers protection checks in this code,+# but it is being used too early to link to meaningful stack_chk logic.+nossp_flags:=$(callcc-option,-fno-stack-protector)+CFLAGS_prom_init.o:=$(nossp_flags)
We've already assigned to CFLAGS_prom_init.o so I think you should be
using += not := shouldn't you?
Also it could just be a single line:
CFLAGS_prom_init.o += $(call cc-option, -fno-stack-protector)
cheers