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

ARM: Tighten check for allowable CPSR values

Reviewed-by: Arve Hjønnevåg <arve@android.com>
Acked-by: Dima Zavin <dima@android.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

+13 -4
+13 -4
arch/arm/include/asm/ptrace.h
··· 158 158 */ 159 159 static inline int valid_user_regs(struct pt_regs *regs) 160 160 { 161 - if (user_mode(regs) && (regs->ARM_cpsr & PSR_I_BIT) == 0) { 162 - regs->ARM_cpsr &= ~(PSR_F_BIT | PSR_A_BIT); 163 - return 1; 161 + unsigned long mode = regs->ARM_cpsr & MODE_MASK; 162 + 163 + /* 164 + * Always clear the F (FIQ) and A (delayed abort) bits 165 + */ 166 + regs->ARM_cpsr &= ~(PSR_F_BIT | PSR_A_BIT); 167 + 168 + if ((regs->ARM_cpsr & PSR_I_BIT) == 0) { 169 + if (mode == USR_MODE) 170 + return 1; 171 + if (elf_hwcap & HWCAP_26BIT && mode == USR26_MODE) 172 + return 1; 164 173 } 165 174 166 175 /* 167 176 * Force CPSR to something logical... 168 177 */ 169 - regs->ARM_cpsr &= PSR_f | PSR_s | (PSR_x & ~PSR_A_BIT) | PSR_T_BIT | MODE32_BIT; 178 + regs->ARM_cpsr &= PSR_f | PSR_s | PSR_x | PSR_T_BIT | MODE32_BIT; 170 179 if (!(elf_hwcap & HWCAP_26BIT)) 171 180 regs->ARM_cpsr |= USR_MODE; 172 181