ARM: 8148/1: flush TLS and thumbee register state during exec

The TPIDRURO and TPIDRURW registers need to be flushed during exec;
otherwise TLS information is potentially leaked. TPIDRURO in
particular needs careful treatment. Since flush_thread basically
needs the same code used to set the TLS in arm_syscall, pull that into
a common set_tls helper in tls.h and use it in both places.

Similarly, TEEHBR needs to be cleared during exec as well. Clearing
its save slot in thread_info isn't right as there is no guarantee
that a thread switch will occur before the new program runs. Just
setting the register directly is sufficient.

Signed-off-by: Nathan Lynch <nathan_lynch@mentor.com>
Acked-by: Will Deacon <will.deacon@arm.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

authored by Nathan Lynch and committed by Russell King fbfb872f 7a0bd497

Changed files
+66 -17
arch
arm
include
asm
kernel
+62
arch/arm/include/asm/tls.h
··· 1 1 #ifndef __ASMARM_TLS_H 2 2 #define __ASMARM_TLS_H 3 3 4 + #include <linux/compiler.h> 5 + #include <asm/thread_info.h> 6 + 4 7 #ifdef __ASSEMBLY__ 5 8 #include <asm/asm-offsets.h> 6 9 .macro switch_tls_none, base, tp, tpuser, tmp1, tmp2 ··· 53 50 #endif 54 51 55 52 #ifndef __ASSEMBLY__ 53 + 54 + static inline void set_tls(unsigned long val) 55 + { 56 + struct thread_info *thread; 57 + 58 + thread = current_thread_info(); 59 + 60 + thread->tp_value[0] = val; 61 + 62 + /* 63 + * This code runs with preemption enabled and therefore must 64 + * be reentrant with respect to switch_tls. 65 + * 66 + * We need to ensure ordering between the shadow state and the 67 + * hardware state, so that we don't corrupt the hardware state 68 + * with a stale shadow state during context switch. 69 + * 70 + * If we're preempted here, switch_tls will load TPIDRURO from 71 + * thread_info upon resuming execution and the following mcr 72 + * is merely redundant. 73 + */ 74 + barrier(); 75 + 76 + if (!tls_emu) { 77 + if (has_tls_reg) { 78 + asm("mcr p15, 0, %0, c13, c0, 3" 79 + : : "r" (val)); 80 + } else { 81 + /* 82 + * User space must never try to access this 83 + * directly. Expect your app to break 84 + * eventually if you do so. The user helper 85 + * at 0xffff0fe0 must be used instead. (see 86 + * entry-armv.S for details) 87 + */ 88 + *((unsigned int *)0xffff0ff0) = val; 89 + } 90 + 91 + } 92 + } 93 + 56 94 static inline unsigned long get_tpuser(void) 57 95 { 58 96 unsigned long reg = 0; ··· 103 59 104 60 return reg; 105 61 } 62 + 63 + static inline void set_tpuser(unsigned long val) 64 + { 65 + /* Since TPIDRURW is fully context-switched (unlike TPIDRURO), 66 + * we need not update thread_info. 67 + */ 68 + if (has_tls_reg && !tls_emu) { 69 + asm("mcr p15, 0, %0, c13, c0, 2" 70 + : : "r" (val)); 71 + } 72 + } 73 + 74 + static inline void flush_tls(void) 75 + { 76 + set_tls(0); 77 + set_tpuser(0); 78 + } 79 + 106 80 #endif 107 81 #endif /* __ASMARM_TLS_H */
+2
arch/arm/kernel/process.c
··· 334 334 memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); 335 335 memset(&thread->fpstate, 0, sizeof(union fp_state)); 336 336 337 + flush_tls(); 338 + 337 339 thread_notify(THREAD_NOTIFY_FLUSH, thread); 338 340 } 339 341
+1 -1
arch/arm/kernel/thumbee.c
··· 45 45 46 46 switch (cmd) { 47 47 case THREAD_NOTIFY_FLUSH: 48 - thread->thumbee_state = 0; 48 + teehbr_write(0); 49 49 break; 50 50 case THREAD_NOTIFY_SWITCH: 51 51 current_thread_info()->thumbee_state = teehbr_read();
+1 -16
arch/arm/kernel/traps.c
··· 581 581 #define NR(x) ((__ARM_NR_##x) - __ARM_NR_BASE) 582 582 asmlinkage int arm_syscall(int no, struct pt_regs *regs) 583 583 { 584 - struct thread_info *thread = current_thread_info(); 585 584 siginfo_t info; 586 585 587 586 if ((no >> 16) != (__ARM_NR_BASE>> 16)) ··· 631 632 return regs->ARM_r0; 632 633 633 634 case NR(set_tls): 634 - thread->tp_value[0] = regs->ARM_r0; 635 - if (tls_emu) 636 - return 0; 637 - if (has_tls_reg) { 638 - asm ("mcr p15, 0, %0, c13, c0, 3" 639 - : : "r" (regs->ARM_r0)); 640 - } else { 641 - /* 642 - * User space must never try to access this directly. 643 - * Expect your app to break eventually if you do so. 644 - * The user helper at 0xffff0fe0 must be used instead. 645 - * (see entry-armv.S for details) 646 - */ 647 - *((unsigned int *)0xffff0ff0) = regs->ARM_r0; 648 - } 635 + set_tls(regs->ARM_r0); 649 636 return 0; 650 637 651 638 #ifdef CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG