linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 1/2] powerpc/32: add stack protector support
@ 2018-09-26 11:40 Christophe Leroy
  2018-09-26 11:40 ` [PATCH v4 2/2] powerpc/64: " Christophe Leroy
  2018-09-26 19:16 ` [PATCH v4 1/2] powerpc/32: " Segher Boessenkool
  0 siblings, 2 replies; 8+ messages in thread
From: Christophe Leroy @ 2018-09-26 11:40 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
  Cc: linux-kernel, linuxppc-dev

This functionality was tentatively added in the past
(commit 6533b7c16ee5 ("powerpc: Initial stack protector
(-fstack-protector) support")) but had to be reverted
(commit f2574030b0e3 ("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 #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>
---
 v4: disable stack protector in bootx_init

 v3: the offset is now defined by a rule in the Makefile. No need anymore
     to take stack_canary out of the randomised area of task_struct

 arch/powerpc/Kconfig                      |  1 +
 arch/powerpc/Makefile                     | 10 +++++++++
 arch/powerpc/include/asm/stackprotector.h | 34 +++++++++++++++++++++++++++++++
 arch/powerpc/kernel/Makefile              |  2 ++
 arch/powerpc/kernel/asm-offsets.c         |  3 +++
 arch/powerpc/platforms/powermac/Makefile  |  1 +
 6 files changed, 51 insertions(+)
 create mode 100644 arch/powerpc/include/asm/stackprotector.h

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index a80669209155..3bcb05929931 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -180,6 +180,7 @@ config PPC
 	select HAVE_ARCH_SECCOMP_FILTER
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_CBPF_JIT			if !PPC64
+	select HAVE_STACKPROTECTOR		if $(cc-option,-mstack-protector-guard=tls) && PPC32
 	select HAVE_CONTEXT_TRACKING		if PPC64
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DEBUG_STACKOVERFLOW
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 07d9dce7eda6..45b8eb4d8fe7 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -112,6 +112,9 @@ KBUILD_LDFLAGS	+= -m elf$(BITS)$(LDEMULATION)
 KBUILD_ARFLAGS	+= --target=elf$(BITS)-$(GNUTARGET)
 endif
 
+cflags-$(CONFIG_STACKPROTECTOR)	+= -mstack-protector-guard=tls
+cflags-$(CONFIG_STACKPROTECTOR)	+= -mstack-protector-guard-reg=r2
+
 LDFLAGS_vmlinux-y := -Bstatic
 LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) := -pie
 LDFLAGS_vmlinux	:= $(LDFLAGS_vmlinux-y)
@@ -404,6 +407,13 @@ archclean:
 
 archprepare: checkbin
 
+ifdef CONFIG_STACKPROTECTOR
+prepare: stack_protector_prepare
+
+stack_protector_prepare: prepare0
+	$(eval KBUILD_CFLAGS += -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "TASK_CANARY") print $$3;}' include/generated/asm-offsets.h))
+endif
+
 # Use the file '.tmp_gas_check' for binutils tests, as gas won't output
 # to stdout and these checks are run even on install targets.
 TOUT	:= .tmp_gas_check
diff --git a/arch/powerpc/include/asm/stackprotector.h b/arch/powerpc/include/asm/stackprotector.h
new file mode 100644
index 000000000000..263e2aab1862
--- /dev/null
+++ b/arch/powerpc/include/asm/stackprotector.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * GCC stack protector support.
+ *
+ */
+
+#ifndef _ASM_STACKPROTECTOR_H
+#define _ASM_STACKPROTECTOR_H
+
+#include <linux/random.h>
+#include <linux/version.h>
+#include <asm/reg.h>
+#include <asm/current.h>
+#include <asm/paca.h>
+
+/*
+ * 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 ^= mftb();
+	canary ^= LINUX_VERSION_CODE;
+
+	current->stack_canary = canary;
+}
+
+#endif	/* _ASM_STACKPROTECTOR_H */
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 1e64cfe22a83..85ffa488dfb5 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -20,6 +20,8 @@ CFLAGS_prom_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
 CFLAGS_btext.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
 CFLAGS_prom.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
 
+CFLAGS_prom_init.o += $(call cc-option, -fno-stack-protector)
+
 ifdef CONFIG_FUNCTION_TRACER
 # Do not trace early boot code
 CFLAGS_REMOVE_cputable.o = $(CC_FLAGS_FTRACE)
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index ba9d0fc98730..a992f7a53cf3 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -79,6 +79,9 @@ int main(void)
 {
 	OFFSET(THREAD, task_struct, thread);
 	OFFSET(MM, task_struct, mm);
+#ifdef CONFIG_STACKPROTECTOR
+	OFFSET(TASK_CANARY, task_struct, stack_canary);
+#endif
 	OFFSET(MMCONTEXTID, mm_struct, context.id);
 #ifdef CONFIG_PPC64
 	DEFINE(SIGSEGV, SIGSEGV);
diff --git a/arch/powerpc/platforms/powermac/Makefile b/arch/powerpc/platforms/powermac/Makefile
index 561a67d65e4d..923bfb340433 100644
--- a/arch/powerpc/platforms/powermac/Makefile
+++ b/arch/powerpc/platforms/powermac/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 CFLAGS_bootx_init.o  		+= -fPIC
+CFLAGS_bootx_init.o  		+= $(call cc-option, -fno-stack-protector)
 
 ifdef CONFIG_FUNCTION_TRACER
 # Do not trace early boot code
-- 
2.13.3


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v4 2/2] powerpc/64: add stack protector support
  2018-09-26 11:40 [PATCH v4 1/2] powerpc/32: add stack protector support Christophe Leroy
@ 2018-09-26 11:40 ` Christophe Leroy
  2018-09-26 19:16 ` [PATCH v4 1/2] powerpc/32: " Segher Boessenkool
  1 sibling, 0 replies; 8+ messages in thread
From: Christophe Leroy @ 2018-09-26 11:40 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
  Cc: linux-kernel, linuxppc-dev

On PPC64, as register r13 points to the paca_struct at all time,
this patch adds a copy of the canary there, which is copied at
task_switch.
That new canary is then used by using the following GCC options:
-mstack-protector-guard=tls
-mstack-protector-guard-reg=r13
-mstack-protector-guard-offset=offsetof(struct paca_struct, canary))

Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
 arch/powerpc/Kconfig                      | 2 +-
 arch/powerpc/Makefile                     | 8 ++++++++
 arch/powerpc/include/asm/paca.h           | 3 +++
 arch/powerpc/include/asm/stackprotector.h | 3 +++
 arch/powerpc/kernel/asm-offsets.c         | 3 +++
 arch/powerpc/kernel/entry_64.S            | 4 ++++
 6 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 3bcb05929931..602eea723624 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -180,7 +180,7 @@ config PPC
 	select HAVE_ARCH_SECCOMP_FILTER
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_CBPF_JIT			if !PPC64
-	select HAVE_STACKPROTECTOR		if $(cc-option,-mstack-protector-guard=tls) && PPC32
+	select HAVE_STACKPROTECTOR		if $(cc-option,-mstack-protector-guard=tls)
 	select HAVE_CONTEXT_TRACKING		if PPC64
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DEBUG_STACKOVERFLOW
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 45b8eb4d8fe7..81552c7b46eb 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -113,7 +113,11 @@ KBUILD_ARFLAGS	+= --target=elf$(BITS)-$(GNUTARGET)
 endif
 
 cflags-$(CONFIG_STACKPROTECTOR)	+= -mstack-protector-guard=tls
+ifdef CONFIG_PPC64
+cflags-$(CONFIG_STACKPROTECTOR)	+= -mstack-protector-guard-reg=r13
+else
 cflags-$(CONFIG_STACKPROTECTOR)	+= -mstack-protector-guard-reg=r2
+endif
 
 LDFLAGS_vmlinux-y := -Bstatic
 LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) := -pie
@@ -411,8 +415,12 @@ ifdef CONFIG_STACKPROTECTOR
 prepare: stack_protector_prepare
 
 stack_protector_prepare: prepare0
+ifdef CONFIG_PPC64
+	$(eval KBUILD_CFLAGS += -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "PACA_CANARY") print $$3;}' include/generated/asm-offsets.h))
+else
 	$(eval KBUILD_CFLAGS += -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "TASK_CANARY") print $$3;}' include/generated/asm-offsets.h))
 endif
+endif
 
 # Use the file '.tmp_gas_check' for binutils tests, as gas won't output
 # to stdout and these checks are run even on install targets.
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index 6d6b3706232c..98d883e58945 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -246,6 +246,9 @@ struct paca_struct {
 	struct slb_entry *mce_faulty_slbs;
 	u16 slb_save_cache_ptr;
 #endif /* CONFIG_PPC_BOOK3S_64 */
+#ifdef CONFIG_STACKPROTECTOR
+	unsigned long canary;
+#endif
 } ____cacheline_aligned;
 
 extern struct paca_struct **paca_ptrs;
diff --git a/arch/powerpc/include/asm/stackprotector.h b/arch/powerpc/include/asm/stackprotector.h
index 263e2aab1862..e81991955c0d 100644
--- a/arch/powerpc/include/asm/stackprotector.h
+++ b/arch/powerpc/include/asm/stackprotector.h
@@ -29,6 +29,9 @@ static __always_inline void boot_init_stack_canary(void)
 	canary ^= LINUX_VERSION_CODE;
 
 	current->stack_canary = canary;
+#ifdef CONFIG_PPC64
+	get_paca()->canary = canary;
+#endif
 }
 
 #endif	/* _ASM_STACKPROTECTOR_H */
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index a992f7a53cf3..773dee55b3f6 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -81,6 +81,9 @@ int main(void)
 	OFFSET(MM, task_struct, mm);
 #ifdef CONFIG_STACKPROTECTOR
 	OFFSET(TASK_CANARY, task_struct, stack_canary);
+#ifdef CONFIG_PPC64
+	OFFSET(PACA_CANARY, paca_struct, canary);
+#endif
 #endif
 	OFFSET(MMCONTEXTID, mm_struct, context.id);
 #ifdef CONFIG_PPC64
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 77a888bfcb53..573fa879d785 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -624,6 +624,10 @@ _GLOBAL(_switch)
 
 	addi	r6,r4,-THREAD	/* Convert THREAD to 'current' */
 	std	r6,PACACURRENT(r13)	/* Set new 'current' */
+#if defined(CONFIG_STACKPROTECTOR)
+	ld	r6, TASK_CANARY(r6)
+	std	r6, PACA_CANARY(r13)
+#endif
 
 	ld	r8,KSP(r4)	/* new stack pointer */
 #ifdef CONFIG_PPC_BOOK3S_64
-- 
2.13.3


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v4 1/2] powerpc/32: add stack protector support
  2018-09-26 11:40 [PATCH v4 1/2] powerpc/32: add stack protector support Christophe Leroy
  2018-09-26 11:40 ` [PATCH v4 2/2] powerpc/64: " Christophe Leroy
@ 2018-09-26 19:16 ` Segher Boessenkool
  2018-09-27  6:20   ` Christophe LEROY
  1 sibling, 1 reply; 8+ messages in thread
From: Segher Boessenkool @ 2018-09-26 19:16 UTC (permalink / raw)
  To: Christophe Leroy
  Cc: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
	linuxppc-dev, linux-kernel

On Wed, Sep 26, 2018 at 11:40:38AM +0000, Christophe Leroy wrote:
> +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 ^= mftb();
> +	canary ^= LINUX_VERSION_CODE;
> +
> +	current->stack_canary = canary;
> +}

I still think you should wait until there is entropy available.  You
haven't answered my questions about that (or I didn't see them): what
does the kernel do in other similar cases?

Looks great otherwise!


Segher

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v4 1/2] powerpc/32: add stack protector support
  2018-09-26 19:16 ` [PATCH v4 1/2] powerpc/32: " Segher Boessenkool
@ 2018-09-27  6:20   ` Christophe LEROY
  2018-09-27  7:45     ` Segher Boessenkool
  0 siblings, 1 reply; 8+ messages in thread
From: Christophe LEROY @ 2018-09-27  6:20 UTC (permalink / raw)
  To: Segher Boessenkool
  Cc: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
	linuxppc-dev, linux-kernel



Le 26/09/2018 à 21:16, Segher Boessenkool a écrit :
> On Wed, Sep 26, 2018 at 11:40:38AM +0000, Christophe Leroy wrote:
>> +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 ^= mftb();
>> +	canary ^= LINUX_VERSION_CODE;
>> +
>> +	current->stack_canary = canary;
>> +}
> 
> I still think you should wait until there is entropy available.  You
> haven't answered my questions about that (or I didn't see them): what
> does the kernel do in other similar cases?
> 
> Looks great otherwise!
> 

What do you mean by 'other similar cases' ? All arches have similar 
boot_init_stack_canary(). x86 uses rdtsc() which is equivalent to our 
mftb(). Most arches xor it with LINUX_VERSION_CODE.

The issue is that it is called very early in start_kernel(), however 
they try to set some entropy anyway:

	boot_cpu_init();
	page_address_init();
	pr_notice("%s", linux_banner);
	setup_arch(&command_line);
	/*
	 * Set up the the initial canary and entropy after arch
	 * and after adding latent and command line entropy.
	 */
	add_latent_entropy();
	add_device_randomness(command_line, strlen(command_line));
	boot_init_stack_canary();

Apparently, it is too early for calling wait_for_random_bytes(), see below.

However this is the canary for initial startup only. Only idle() still 
uses this canary once the system is running. A new canary is set for any 
new forked task.

Maybe should the idle canary be updated later once there is more entropy 
? Today there is a new call to boot_init_stack_canary() in 
cpu_startup_entry(), but it is enclosed inside #ifdef CONFIG_X86.

[    0.000000] Unable to handle kernel paging request for data at 
address 0x00000200
[    0.000000] Faulting instruction address: 0xc0048e2c
[    0.000000] Oops: Kernel access of bad area, sig: 11 [#1]
[    0.000000] BE PREEMPT CMPC885
[    0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted 
4.19.0-rc4-s3k-dev-00498-g439f9fbadb38-dirty #6
[    0.000000] NIP:  c0048e2c LR: c05cf9ec CTR: c0018a68
[    0.000000] REGS: c07e9e40 TRAP: 0300   Not tainted 
(4.19.0-rc4-s3k-dev-00498-g439f9fbadb38-dirty)
[    0.000000] MSR:  00001032 <ME,IR,DR,RI>  CR: 28044222  XER: 00000000
[    0.000000] DAR: 00000200 DSISR: c0000000
[    0.000000] GPR00: c05cf9ec c07e9ef0 c078c560 00000000 00000000 
00000001 c080a405 626f6f74
[    0.000000] GPR08: 00001032 c07e8000 00000000 00000004 28044222 
100c82b6 00000000 07ff9580
[    0.000000] GPR16: 00000000 07ffb94c 00000000 00000000 00000000 
00000000 00000000 00000000
[    0.000000] GPR24: 00000000 07ff9580 c05cfb3c 00000000 c0790000 
c07e8000 c0797740 00000000
[    0.000000] NIP [c0048e2c] __schedule_bug+0x24/0x78
[    0.000000] LR [c05cf9ec] __schedule+0x4f4/0x614
[    0.000000] Call Trace:
[    0.000000] [c07e9ef0] [07ffb94c] 0x7ffb94c (unreliable)
[    0.000000] [c07e9f00] [c05cf9ec] __schedule+0x4f4/0x614
[    0.000000] [c07e9f50] [c05cfb3c] schedule+0x30/0x5c
[    0.000000] [c07e9f70] [c02bf15c] wait_for_random_bytes.part.4+0xa0/0xa8
[    0.000000] [c07e9fb0] [c06fc9c8] start_kernel+0x98/0x46c
[    0.000000] [c07e9ff0] [c00022cc] start_here+0x44/0x98
[    0.000000] Instruction dump:
[    0.000000] 419eff30 4bffff8c 4bfd6619 3d20c081 81298154 2f890000 
4cbe0020 9421fff0
[    0.000000] 7c0802a6 90010014 7c641b78 54290024 <80a40200> 80c90008 
3c60c06a 388402fc
[    0.000000] random: get_random_bytes called from 
print_oops_end_marker+0x34/0x6c with crng_init=0
[    0.000000] ---[ end trace 343b232a5e00519e ]---

Christophe

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v4 1/2] powerpc/32: add stack protector support
  2018-09-27  6:20   ` Christophe LEROY
@ 2018-09-27  7:45     ` Segher Boessenkool
  2018-09-27 11:51       ` Christophe LEROY
  0 siblings, 1 reply; 8+ messages in thread
From: Segher Boessenkool @ 2018-09-27  7:45 UTC (permalink / raw)
  To: Christophe LEROY
  Cc: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
	linuxppc-dev, linux-kernel

On Thu, Sep 27, 2018 at 08:20:00AM +0200, Christophe LEROY wrote:
> Le 26/09/2018 à 21:16, Segher Boessenkool a écrit :
> >On Wed, Sep 26, 2018 at 11:40:38AM +0000, Christophe Leroy wrote:
> >>+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 ^= mftb();
> >>+	canary ^= LINUX_VERSION_CODE;
> >>+
> >>+	current->stack_canary = canary;
> >>+}
> >
> >I still think you should wait until there is entropy available.  You
> >haven't answered my questions about that (or I didn't see them): what
> >does the kernel do in other similar cases?
> >
> >Looks great otherwise!
> 
> What do you mean by 'other similar cases' ? All arches have similar 
> boot_init_stack_canary().

Yes, those, and other things that want entropy early.

> x86 uses rdtsc() which is equivalent to our 
> mftb(). Most arches xor it with LINUX_VERSION_CODE.
> 
> The issue is that it is called very early in start_kernel(), however 
> they try to set some entropy anyway:
> 
> 	boot_cpu_init();
> 	page_address_init();
> 	pr_notice("%s", linux_banner);
> 	setup_arch(&command_line);
> 	/*
> 	 * Set up the the initial canary and entropy after arch
> 	 * and after adding latent and command line entropy.
> 	 */
> 	add_latent_entropy();
> 	add_device_randomness(command_line, strlen(command_line));
> 	boot_init_stack_canary();
> 
> Apparently, it is too early for calling wait_for_random_bytes(), see below.

Hrm.  Too early to call wait_event_interruptible?  From there it went
into schedule(), which blew up.  Well you say we have only one context
at this point, so that is not too surprising then :-)

> However this is the canary for initial startup only. Only idle() still 
> uses this canary once the system is running. A new canary is set for any 
> new forked task.

Ah, that makes things a lot better!  Do those new tasks get a canary
from something with sufficient entropy though?

> Maybe should the idle canary be updated later once there is more entropy 

That is tricky to do, but sure, if you can, that should help.

> ? Today there is a new call to boot_init_stack_canary() in 
> cpu_startup_entry(), but it is enclosed inside #ifdef CONFIG_X86.

It needs to know the details of how ssp works on each platform.


Segher

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v4 1/2] powerpc/32: add stack protector support
  2018-09-27  7:45     ` Segher Boessenkool
@ 2018-09-27 11:51       ` Christophe LEROY
  2018-09-28 12:56         ` Michael Ellerman
  0 siblings, 1 reply; 8+ messages in thread
From: Christophe LEROY @ 2018-09-27 11:51 UTC (permalink / raw)
  To: Segher Boessenkool
  Cc: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
	linuxppc-dev, linux-kernel



Le 27/09/2018 à 09:45, Segher Boessenkool a écrit :
> On Thu, Sep 27, 2018 at 08:20:00AM +0200, Christophe LEROY wrote:
>> Le 26/09/2018 à 21:16, Segher Boessenkool a écrit :
>>> On Wed, Sep 26, 2018 at 11:40:38AM +0000, Christophe Leroy wrote:
>>>> +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 ^= mftb();
>>>> +	canary ^= LINUX_VERSION_CODE;
>>>> +
>>>> +	current->stack_canary = canary;
>>>> +}
>>>
>>> I still think you should wait until there is entropy available.  You
>>> haven't answered my questions about that (or I didn't see them): what
>>> does the kernel do in other similar cases?
>>>
>>> Looks great otherwise!
>>
>> What do you mean by 'other similar cases' ? All arches have similar
>> boot_init_stack_canary().
> 
> Yes, those, and other things that want entropy early.

Functions add_latent_entropy() and add_device_randomness() are
there for that it seems, allthough it is not real entropy.

> 
>> x86 uses rdtsc() which is equivalent to our
>> mftb(). Most arches xor it with LINUX_VERSION_CODE.
>>
>> The issue is that it is called very early in start_kernel(), however
>> they try to set some entropy anyway:
>>
>> 	boot_cpu_init();
>> 	page_address_init();
>> 	pr_notice("%s", linux_banner);
>> 	setup_arch(&command_line);
>> 	/*
>> 	 * Set up the the initial canary and entropy after arch
>> 	 * and after adding latent and command line entropy.
>> 	 */
>> 	add_latent_entropy();
>> 	add_device_randomness(command_line, strlen(command_line));
>> 	boot_init_stack_canary();
>>
>> Apparently, it is too early for calling wait_for_random_bytes(), see below.
> 
> Hrm.  Too early to call wait_event_interruptible?  From there it went
> into schedule(), which blew up.  Well you say we have only one context
> at this point, so that is not too surprising then :-)
> 
>> However this is the canary for initial startup only. Only idle() still
>> uses this canary once the system is running. A new canary is set for any
>> new forked task.
> 
> Ah, that makes things a lot better!  Do those new tasks get a canary
> from something with sufficient entropy though?

For the kernel threads that are started early, probably not. For the 
ones started a bit later, and for user processes, I believe they have 
better entropy. Anyway, all this is handled by the kernel core and is 
out of control of individual arches, as its done in kernel/fork.c in 
function dup_task_struct(). However this function is declared as
static __latent_entropy struct task_struct *copy_process(). This 
__latent_entropy attibute must help in a way.

> 
>> Maybe should the idle canary be updated later once there is more entropy
> 
> That is tricky to do, but sure, if you can, that should help.
> 
>> ? Today there is a new call to boot_init_stack_canary() in
>> cpu_startup_entry(), but it is enclosed inside #ifdef CONFIG_X86.
> 
> It needs to know the details of how ssp works on each platform.

Well, that could be for another patch in the future. That's probably 
feasible on x86 and PPC because they both use TLS guard, but not for 
other arches where the guard is global at the moment. So we'll have to 
do it carefully.

I agree with you that we may not for the time being get all the expected 
security against hackers out of it due to that little entropy, but my 
main concern at the time being is to deter developper's bugs clobbering 
the stack, and for that any non trivial canary should make it, shouldn't 
it ?

Christophe

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v4 1/2] powerpc/32: add stack protector support
  2018-09-27 11:51       ` Christophe LEROY
@ 2018-09-28 12:56         ` Michael Ellerman
  2018-09-28 16:26           ` Segher Boessenkool
  0 siblings, 1 reply; 8+ messages in thread
From: Michael Ellerman @ 2018-09-28 12:56 UTC (permalink / raw)
  To: Christophe LEROY, Segher Boessenkool
  Cc: Benjamin Herrenschmidt, Paul Mackerras, linuxppc-dev, linux-kernel

Christophe LEROY <christophe.leroy@c-s.fr> writes:
> Le 27/09/2018 à 09:45, Segher Boessenkool a écrit :
>> On Thu, Sep 27, 2018 at 08:20:00AM +0200, Christophe LEROY wrote:
...
>> 
>>> However this is the canary for initial startup only. Only idle() still
>>> uses this canary once the system is running. A new canary is set for any
>>> new forked task.
>> 
>> Ah, that makes things a lot better!  Do those new tasks get a canary
>> from something with sufficient entropy though?
>
> For the kernel threads that are started early, probably not. For the 
> ones started a bit later, and for user processes, I believe they have 
> better entropy. Anyway, all this is handled by the kernel core and is 
> out of control of individual arches, as its done in kernel/fork.c in 
> function dup_task_struct(). However this function is declared as
> static __latent_entropy struct task_struct *copy_process(). This 
> __latent_entropy attibute must help in a way.
>
>> 
>>> Maybe should the idle canary be updated later once there is more entropy
>> 
>> That is tricky to do, but sure, if you can, that should help.
>> 
>>> ? Today there is a new call to boot_init_stack_canary() in
>>> cpu_startup_entry(), but it is enclosed inside #ifdef CONFIG_X86.
>> 
>> It needs to know the details of how ssp works on each platform.
>
> Well, that could be for another patch in the future. That's probably 
> feasible on x86 and PPC because they both use TLS guard, but not for 
> other arches where the guard is global at the moment. So we'll have to 
> do it carefully.
>
> I agree with you that we may not for the time being get all the expected 
> security against hackers out of it due to that little entropy, but my 
> main concern at the time being is to deter developper's bugs clobbering 
> the stack, and for that any non trivial canary should make it, shouldn't 
> it ?

Yes.

The problem of low entropy at boot on systems without a good hardware
source is sort of unsolvable.

As you say it's up to the core kernel/random code, we shouldn't be
trying to do anything tricky in the arch code.

You don't want your system to take 3 hours to boot because it's waiting
for entropy for the stack canary.

If we can update the canary later once the entropy pool is setup that
would be ideal.

cheers

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v4 1/2] powerpc/32: add stack protector support
  2018-09-28 12:56         ` Michael Ellerman
@ 2018-09-28 16:26           ` Segher Boessenkool
  0 siblings, 0 replies; 8+ messages in thread
From: Segher Boessenkool @ 2018-09-28 16:26 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: Christophe LEROY, Benjamin Herrenschmidt, Paul Mackerras,
	linuxppc-dev, linux-kernel

On Fri, Sep 28, 2018 at 10:56:07PM +1000, Michael Ellerman wrote:
> The problem of low entropy at boot on systems without a good hardware
> source is sort of unsolvable.
> 
> As you say it's up to the core kernel/random code, we shouldn't be
> trying to do anything tricky in the arch code.
> 
> You don't want your system to take 3 hours to boot because it's waiting
> for entropy for the stack canary.
> 
> If we can update the canary later once the entropy pool is setup that
> would be ideal.

Yup, I agree with all that.

But we should *also* not say "oh, there may be cases where we cannot
do the right thing, so just do not even try, ever, anywhere".


Segher

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2018-09-28 16:27 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-26 11:40 [PATCH v4 1/2] powerpc/32: add stack protector support Christophe Leroy
2018-09-26 11:40 ` [PATCH v4 2/2] powerpc/64: " Christophe Leroy
2018-09-26 19:16 ` [PATCH v4 1/2] powerpc/32: " Segher Boessenkool
2018-09-27  6:20   ` Christophe LEROY
2018-09-27  7:45     ` Segher Boessenkool
2018-09-27 11:51       ` Christophe LEROY
2018-09-28 12:56         ` Michael Ellerman
2018-09-28 16:26           ` Segher Boessenkool

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).