diff options
-rw-r--r-- | Makefile.main | 26 | ||||
-rw-r--r-- | asm/head.S | 5 | ||||
-rw-r--r-- | core/cpu.c | 12 | ||||
-rw-r--r-- | core/utils.c | 3 | ||||
-rw-r--r-- | include/cpu.h | 5 | ||||
-rw-r--r-- | include/stack.h | 2 |
6 files changed, 40 insertions, 13 deletions
diff --git a/Makefile.main b/Makefile.main index 31cbab7..516afdd 100644 --- a/Makefile.main +++ b/Makefile.main @@ -19,6 +19,7 @@ try = $(shell set -e; if ($(1)) >/dev/null 2>&1; \ else echo "$(3)"; fi ) try-cflag = $(call try,$(1) $(2) -x c -c /dev/null -o /dev/null,$(2)) +test_cflag = $(call try,$(1) $(2) -x c -c /dev/null -o /dev/null,1,0) # Base warnings CWARNS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ @@ -90,20 +91,29 @@ else VALGRIND := endif -# Stack protector disabled for now. gcc tends to use the TLS to -# access the canary (depending on how gcc was built), and this won't -# work for us. -# +# Check if the new parametrized stack protector option is supported +# by gcc, otherwise disable stack protector +STACK_PROT_CFLAGS := -mstack-protector-guard=tls -mstack-protector-guard-reg=r13 +STACK_PROT_CFLAGS += -mstack-protector-guard-offset=0 +HAS_STACK_PROT := $(call test_cflag,$(CC),$(STACK_PROT_CFLAGS)) + ifeq ($(STACK_CHECK),1) -#CFLAGS += -fstack-protector-all -pg -CFLAGS += -fno-stack-protector -pg +STACK_PROT_CFLAGS += -fstack-protector-all CPPFLAGS += -DSTACK_CHECK_ENABLED +CFLAGS += -pg +else +STACK_PROT_CFLAGS += -fstack-protector +STACK_PROT_CFLAGS += $(call try-cflag,$(CC),-fstack-protector-strong) +endif + +ifeq ($(HAS_STACK_PROT),1) +CPPFLAGS += -DHAS_STACK_PROT +CFLAGS += $(STACK_PROT_CFLAGS) else CFLAGS += -fno-stack-protector -#CFLAGS += -fstack-protector -#CFLAGS += $(call try-cflag,$(CC),-fstack-protector-strong) endif + CFLAGS += $(call try-cflag,$(CC),-Wjump-misses-init) \ $(call try-cflag,$(CC),-Wsuggest-attribute=const) \ $(call try-cflag,$(CC),-Wsuggest-attribute=noreturn) \ @@ -389,6 +389,11 @@ boot_entry: li %r0,0 std %r0,CPUTHREAD_STACK_BOT_MARK(%r13) #endif + /* Initialize the stack guard */ + LOAD_IMM64(%r3,STACK_CHECK_GUARD_BASE); + xor %r3,%r3,%r31 + std %r3,0(%r13) + /* Jump to C */ mr %r3,%r27 bl main_cpu_entry @@ -822,6 +822,7 @@ static void init_cpu_thread(struct cpu_thread *t, init_lock(&t->dctl_lock); init_lock(&t->job_lock); list_head_init(&t->job_queue); + t->stack_guard = STACK_CHECK_GUARD_BASE ^ pir; t->state = state; t->pir = pir; #ifdef STACK_CHECK_ENABLED @@ -865,7 +866,8 @@ void __nomcount pre_init_boot_cpu(void) { struct cpu_thread *cpu = this_cpu(); - memset(cpu, 0, sizeof(struct cpu_thread)); + /* We skip the stack guard ! */ + memset(((void *)cpu) + 8, 0, sizeof(struct cpu_thread) - 8); } void init_boot_cpu(void) @@ -943,8 +945,14 @@ void init_boot_cpu(void) top_of_ram += (cpu_max_pir + 1) * STACK_SIZE; /* Clear the CPU structs */ - for (i = 0; i <= cpu_max_pir; i++) + for (i = 0; i <= cpu_max_pir; i++) { + /* boot CPU already cleared and we don't want to clobber + * its stack guard value. + */ + if (i == pir) + continue; memset(&cpu_stacks[i].cpu, 0, sizeof(struct cpu_thread)); + } /* Setup boot CPU state */ boot_cpu = &cpu_stacks[pir].cpu; diff --git a/core/utils.c b/core/utils.c index d21881e..9e2cb37 100644 --- a/core/utils.c +++ b/core/utils.c @@ -22,9 +22,6 @@ #include <cpu.h> #include <stack.h> -extern unsigned long __stack_chk_guard; -unsigned long __stack_chk_guard = 0xdeadf00dbaad300dULL; - void __noreturn assert_fail(const char *msg) { /** diff --git a/include/cpu.h b/include/cpu.h index 2804105..e3bc75f 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -45,6 +45,11 @@ struct cpu_job; struct xive_cpu_state; struct cpu_thread { + /* + * "stack_guard" must be at offset 0 to match the + * -mstack-protector-guard-offset=0 statement in the Makefile + */ + uint64_t stack_guard; uint32_t pir; uint32_t server_no; uint32_t chip_id; diff --git a/include/stack.h b/include/stack.h index 3c9799b..e50b34f 100644 --- a/include/stack.h +++ b/include/stack.h @@ -44,6 +44,8 @@ */ #define STACK_WARNING_GAP 2048 +#define STACK_CHECK_GUARD_BASE 0xdeadf00dbaad300 + #ifndef __ASSEMBLY__ #include <stdint.h> |