In order to allow the use of non global stack protector canary,
the stack canary needs to be located at a know offset defined
in Makefile via -mstack-protector-guard-offset.
On powerpc/32, register r2 points to current task_struct at
all time, the stack_canary located inside task_struct can be
used directly if it is located in a known place.
In order to allow that, this patch moves the stack_canary field
out of the randomized area of task_struct.
Signed-off-by: Christophe Leroy <redacted>
---
include/linux/sched.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
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=global 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=4
(= offsetof(struct task_struct, stack_canary))
$ 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 <redacted>
---
arch/powerpc/Kconfig | 1 +
arch/powerpc/Makefile | 4 ++++
arch/powerpc/include/asm/stackprotector.h | 38 +++++++++++++++++++++++++++++++
arch/powerpc/kernel/Makefile | 4 ++++
4 files changed, 47 insertions(+)
create mode 100644 arch/powerpc/include/asm/stackprotector.h
@@ -20,6 +20,10 @@ CFLAGS_prom_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.+CFLAGS_prom_init.o+=$(callcc-option,-fno-stack-protector)+ifdef CONFIG_FUNCTION_TRACER# Do not trace early boot codeCFLAGS_REMOVE_cputable.o=-mno-sched-epilog$(CC_FLAGS_FTRACE)
From: Peter Zijlstra <peterz@infradead.org> Date: 2018-09-19 11:58:53
On Wed, Sep 19, 2018 at 11:14:43AM +0000, Christophe Leroy wrote:
In order to allow the use of non global stack protector canary,
the stack canary needs to be located at a know offset defined
in Makefile via -mstack-protector-guard-offset.
On powerpc/32, register r2 points to current task_struct at
all time, the stack_canary located inside task_struct can be
used directly if it is located in a known place.
In order to allow that, this patch moves the stack_canary field
out of the randomized area of task_struct.
And you cannot use something like asm-offsets to extract this?
On Wed, Sep 19, 2018 at 11:14:43AM +0000, Christophe Leroy wrote:
quoted
In order to allow the use of non global stack protector canary,
the stack canary needs to be located at a know offset defined
in Makefile via -mstack-protector-guard-offset.
On powerpc/32, register r2 points to current task_struct at
all time, the stack_canary located inside task_struct can be
used directly if it is located in a known place.
In order to allow that, this patch moves the stack_canary field
out of the randomized area of task_struct.
And you cannot use something like asm-offsets to extract this?
I have not been able to find a way to define the compilation flags AFTER
building asm-offsets.h, see https://patchwork.ozlabs.org/patch/971521/
If you have a suggestion, it is welcomed.
From: Peter Zijlstra <peterz@infradead.org> Date: 2018-09-19 12:53:11
On Wed, Sep 19, 2018 at 02:25:00PM +0200, Christophe LEROY wrote:
I have not been able to find a way to define the compilation flags AFTER
building asm-offsets.h, see https://patchwork.ozlabs.org/patch/971521/
If you have a suggestion, it is welcomed.
Not really; I always get lost in that stuff :/
quoted
Might as well put it before state, right after the task_info thing.
Yes, it doesn't make much difference, don't any arch expect state at offset
0 ?
Uhmm.. dunno. I would not expect so, but then I didn't check.
This last line is only correct if !CONFIG_THREAD_INFO_IN_TASK; is that
always true? Add an assert somewhere maybe?
+ /*
+ * The stack_canary must be located at the offset given to
+ * -mstack-protector-guard-offset in the Makefile
+ */
+ BUILD_BUG_ON(offsetof(struct task_struct, stack_canary) != sizeof(long));
Well this will help :-)
It looks like it will be easy to enable on 64 bit as well.
+ /* Try to get a semi random initial value. */
+ get_random_bytes(&canary, sizeof(canary));
+ canary ^= mftb();
+ canary ^= LINUX_VERSION_CODE;
These last two lines are useless (or worse, they may give people the idea
that they are not!)
You should use wait_for_random_bytes I think.
Segher
This last line is only correct if !CONFIG_THREAD_INFO_IN_TASK; is that
always true? Add an assert somewhere maybe?
At the time being powerpc doesn't select CONFIG_THREAD_INFO_IN_TASK.
A BUILD_BUG_ON() is added in stackprotector.h
quoted
+ /*
+ * The stack_canary must be located at the offset given to
+ * -mstack-protector-guard-offset in the Makefile
+ */
+ BUILD_BUG_ON(offsetof(struct task_struct, stack_canary) != sizeof(long));
Well this will help :-)
It looks like it will be easy to enable on 64 bit as well.
Will it ? It seems that PPC64 doesn't have r2 pointing to current task
struct, but instead it has r13 pointing to the paca struct. Which means
we should add a canary in the paca struct, and populate it at task
switch from current->stack_canary. Or am I missing something ?
quoted
+ /* Try to get a semi random initial value. */
+ get_random_bytes(&canary, sizeof(canary));
+ canary ^= mftb();
+ canary ^= LINUX_VERSION_CODE;
These last two lines are useless (or worse, they may give people the idea
that they are not!)
Well, the last line is in all arches except x86
The mftb() was suggested by Michael to add some entropy.
x86 does the same sort of thing with their rdtsc()
You should use wait_for_random_bytes I think.
On the 8xx, it takes several minutes before crnd_is_ready(), while
boot_init_stack_canary() is called quite early in start_kernel()
Christophe
On Wed, Sep 19, 2018 at 04:22:52PM +0200, Christophe LEROY wrote:
quoted
It looks like it will be easy to enable on 64 bit as well.
Will it ? It seems that PPC64 doesn't have r2 pointing to current task
struct, but instead it has r13 pointing to the paca struct. Which means
we should add a canary in the paca struct, and populate it at task
switch from current->stack_canary. Or am I missing something ?
No, I am just forgetting things :-)
quoted
quoted
+ /* Try to get a semi random initial value. */
+ get_random_bytes(&canary, sizeof(canary));
+ canary ^= mftb();
+ canary ^= LINUX_VERSION_CODE;
These last two lines are useless (or worse, they may give people the idea
that they are not!)
Well, the last line is in all arches except x86
The mftb() was suggested by Michael to add some entropy.
x86 does the same sort of thing with their rdtsc()
quoted
You should use wait_for_random_bytes I think.
On the 8xx, it takes several minutes before crnd_is_ready(), while
boot_init_stack_canary() is called quite early in start_kernel()
If you do not provide real entropy to the canary, the canary doesn't help
providing protection as much as you may hope.
Segher
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2018-09-19 23:57:03
Christophe LEROY [off-list ref] writes:
Le 19/09/2018 =C3=A0 13:58, Peter Zijlstra a =C3=A9crit=C2=A0:
quoted
On Wed, Sep 19, 2018 at 11:14:43AM +0000, Christophe Leroy wrote:
quoted
In order to allow the use of non global stack protector canary,
the stack canary needs to be located at a know offset defined
in Makefile via -mstack-protector-guard-offset.
On powerpc/32, register r2 points to current task_struct at
all time, the stack_canary located inside task_struct can be
used directly if it is located in a known place.
In order to allow that, this patch moves the stack_canary field
out of the randomized area of task_struct.
=20
And you cannot use something like asm-offsets to extract this?
I have not been able to find a way to define the compilation flags AFTER=
Hmm, that's something of a hard problem.
But the stack canary is one of the things we really *do* want to be
randomised, so we should probably try to come up with a solution.
cheers