diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-08-13 23:33:46 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-26 16:40:11 -0700 |
commit | c12a6717916079c1dfbd27fcfb9f88eada11356d (patch) | |
tree | c25cf0012947b61974e545b137da7b5a56f5e375 | |
parent | 59a8e9b92790ba035dbb3acaec00721b0cfeb32e (diff) |
ARM: Tighten check for allowable CPSR values
commit 41e2e8fd34fff909a0e40129f6ac4233ecfa67a9 upstream.
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>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | arch/arm/include/asm/ptrace.h | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index b415c0e8545..1c0447e7b08 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h @@ -124,15 +124,24 @@ struct pt_regs { */ static inline int valid_user_regs(struct pt_regs *regs) { - if (user_mode(regs) && (regs->ARM_cpsr & PSR_I_BIT) == 0) { - regs->ARM_cpsr &= ~(PSR_F_BIT | PSR_A_BIT); - return 1; + unsigned long mode = regs->ARM_cpsr & MODE_MASK; + + /* + * Always clear the F (FIQ) and A (delayed abort) bits + */ + regs->ARM_cpsr &= ~(PSR_F_BIT | PSR_A_BIT); + + if ((regs->ARM_cpsr & PSR_I_BIT) == 0) { + if (mode == USR_MODE) + return 1; + if (elf_hwcap & HWCAP_26BIT && mode == USR26_MODE) + return 1; } /* * Force CPSR to something logical... */ - regs->ARM_cpsr &= PSR_f | PSR_s | (PSR_x & ~PSR_A_BIT) | PSR_T_BIT | MODE32_BIT; + regs->ARM_cpsr &= PSR_f | PSR_s | PSR_x | PSR_T_BIT | MODE32_BIT; if (!(elf_hwcap & HWCAP_26BIT)) regs->ARM_cpsr |= USR_MODE; |