Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gcc-plugins: arm-ssp: Prepare for THREAD_INFO_IN_TASK support

We will be enabling THREAD_INFO_IN_TASK support for ARM, which means
that we can no longer load the stack canary value by masking the stack
pointer and taking the copy that lives in thread_info. Instead, we will
be able to load it from the task_struct directly, by using the TPIDRURO
register which will hold the current task pointer when
THREAD_INFO_IN_TASK is in effect. This is much more straight-forward,
and allows us to declutter this code a bit while at it.

Note that this means that ARMv6 (non-v6K) SMP systems can no longer use
this feature, but those are quite rare to begin with, so this is a
reasonable trade off.

Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Tested-by: Amit Daniel Kachhap <amit.kachhap@arm.com>

+8 -39
+1 -1
arch/arm/Kconfig
··· 1600 1600 1601 1601 config STACKPROTECTOR_PER_TASK 1602 1602 bool "Use a unique stack canary value for each task" 1603 - depends on GCC_PLUGINS && STACKPROTECTOR && SMP && !XIP_DEFLATED_DATA 1603 + depends on GCC_PLUGINS && STACKPROTECTOR && THREAD_INFO_IN_TASK && !XIP_DEFLATED_DATA 1604 1604 select GCC_PLUGIN_ARM_SSP_PER_TASK 1605 1605 default y 1606 1606 help
+1 -4
arch/arm/Makefile
··· 273 273 prepare: stack_protector_prepare 274 274 stack_protector_prepare: prepare0 275 275 $(eval SSP_PLUGIN_CFLAGS := \ 276 - -fplugin-arg-arm_ssp_per_task_plugin-tso=$(shell \ 277 - awk '{if ($$2 == "THREAD_SZ_ORDER") print $$3;}'\ 278 - include/generated/asm-offsets.h) \ 279 276 -fplugin-arg-arm_ssp_per_task_plugin-offset=$(shell \ 280 - awk '{if ($$2 == "TI_STACK_CANARY") print $$3;}'\ 277 + awk '{if ($$2 == "TSK_STACK_CANARY") print $$3;}'\ 281 278 include/generated/asm-offsets.h)) 282 279 $(eval KBUILD_CFLAGS += $(SSP_PLUGIN_CFLAGS)) 283 280 $(eval GCC_PLUGINS_CFLAGS += $(SSP_PLUGIN_CFLAGS))
-2
arch/arm/include/asm/stackprotector.h
··· 39 39 current->stack_canary = canary; 40 40 #ifndef CONFIG_STACKPROTECTOR_PER_TASK 41 41 __stack_chk_guard = current->stack_canary; 42 - #else 43 - current_thread_info()->stack_canary = current->stack_canary; 44 42 #endif 45 43 } 46 44
-3
arch/arm/include/asm/thread_info.h
··· 55 55 struct task_struct *task; /* main task structure */ 56 56 __u32 cpu; /* cpu */ 57 57 __u32 cpu_domain; /* cpu domain */ 58 - #ifdef CONFIG_STACKPROTECTOR_PER_TASK 59 - unsigned long stack_canary; 60 - #endif 61 58 struct cpu_context_save cpu_context; /* cpu context */ 62 59 __u32 abi_syscall; /* ABI type and syscall nr */ 63 60 __u8 used_cp[16]; /* thread used copro */
-4
arch/arm/kernel/asm-offsets.c
··· 63 63 #ifdef CONFIG_IWMMXT 64 64 DEFINE(TI_IWMMXT_STATE, offsetof(struct thread_info, fpstate.iwmmxt)); 65 65 #endif 66 - #ifdef CONFIG_STACKPROTECTOR_PER_TASK 67 - DEFINE(TI_STACK_CANARY, offsetof(struct thread_info, stack_canary)); 68 - #endif 69 - DEFINE(THREAD_SZ_ORDER, THREAD_SIZE_ORDER); 70 66 BLANK(); 71 67 DEFINE(S_R0, offsetof(struct pt_regs, ARM_r0)); 72 68 DEFINE(S_R1, offsetof(struct pt_regs, ARM_r1));
-4
arch/arm/kernel/process.c
··· 269 269 270 270 thread_notify(THREAD_NOTIFY_COPY, thread); 271 271 272 - #ifdef CONFIG_STACKPROTECTOR_PER_TASK 273 - thread->stack_canary = p->stack_canary; 274 - #endif 275 - 276 272 return 0; 277 273 } 278 274
+6 -21
scripts/gcc-plugins/arm_ssp_per_task_plugin.c
··· 4 4 5 5 __visible int plugin_is_GPL_compatible; 6 6 7 - static unsigned int sp_mask, canary_offset; 7 + static unsigned int canary_offset; 8 8 9 9 static unsigned int arm_pertask_ssp_rtl_execute(void) 10 10 { ··· 13 13 for (insn = get_insns(); insn; insn = NEXT_INSN(insn)) { 14 14 const char *sym; 15 15 rtx body; 16 - rtx mask, masked_sp; 16 + rtx current; 17 17 18 18 /* 19 19 * Find a SET insn involving a SYMBOL_REF to __stack_chk_guard ··· 30 30 31 31 /* 32 32 * Replace the source of the SET insn with an expression that 33 - * produces the address of the copy of the stack canary value 34 - * stored in struct thread_info 33 + * produces the address of the current task's stack canary value 35 34 */ 36 - mask = GEN_INT(sext_hwi(sp_mask, GET_MODE_PRECISION(Pmode))); 37 - masked_sp = gen_reg_rtx(Pmode); 35 + current = gen_reg_rtx(Pmode); 38 36 39 - emit_insn_before(gen_rtx_set(masked_sp, 40 - gen_rtx_AND(Pmode, 41 - stack_pointer_rtx, 42 - mask)), 43 - insn); 37 + emit_insn_before(gen_load_tp_hard(current), insn); 44 38 45 - SET_SRC(body) = gen_rtx_PLUS(Pmode, masked_sp, 39 + SET_SRC(body) = gen_rtx_PLUS(Pmode, current, 46 40 GEN_INT(canary_offset)); 47 41 } 48 42 return 0; ··· 66 72 const char * const plugin_name = plugin_info->base_name; 67 73 const int argc = plugin_info->argc; 68 74 const struct plugin_argument *argv = plugin_info->argv; 69 - int tso = 0; 70 75 int i; 71 76 72 77 if (!plugin_default_version_check(version, &gcc_version)) { ··· 84 91 return 1; 85 92 } 86 93 87 - if (!strcmp(argv[i].key, "tso")) { 88 - tso = atoi(argv[i].value); 89 - continue; 90 - } 91 - 92 94 if (!strcmp(argv[i].key, "offset")) { 93 95 canary_offset = atoi(argv[i].value); 94 96 continue; ··· 92 104 plugin_name, argv[i].key); 93 105 return 1; 94 106 } 95 - 96 - /* create the mask that produces the base of the stack */ 97 - sp_mask = ~((1U << (12 + tso)) - 1); 98 107 99 108 PASS_INFO(arm_pertask_ssp_rtl, "expand", 1, PASS_POS_INSERT_AFTER); 100 109