aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2012-10-16 12:07:46 -0400
committerCatalin Marinas <catalin.marinas@arm.com>2012-10-18 15:14:01 -0400
commit16dd46bb781a1d37eeb2377e8e48276e9d14d15d (patch)
treef5f0626fdf4a841ffba5f7ce79e7e8cbfee6a56a
parentf71a1a42667f576ec736bb1200eba2118fee3a22 (diff)
arm64: No need to set the x0-x2 registers in start_thread()
For historical reasons, ARM used to set r0-r2 in start_thread() to the first values on the user stack when starting a new user application. The same logic has been inherited in AArch64. The x0 register is overridden by the sys_execve() return value so it's always zero on success. The x1 and x2 registers are ignored by AArch64 and EABI AArch32 applications, so we can safely remove the register setting for both native and compat user space. This also fixes a potential fault with the kernel accessing user space stack directly. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Reported-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--arch/arm64/include/asm/processor.h10
1 files changed, 0 insertions, 10 deletions
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 39a208a392f7..5d810044feda 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -92,30 +92,20 @@ static inline void start_thread_common(struct pt_regs *regs, unsigned long pc)
92static inline void start_thread(struct pt_regs *regs, unsigned long pc, 92static inline void start_thread(struct pt_regs *regs, unsigned long pc,
93 unsigned long sp) 93 unsigned long sp)
94{ 94{
95 unsigned long *stack = (unsigned long *)sp;
96
97 start_thread_common(regs, pc); 95 start_thread_common(regs, pc);
98 regs->pstate = PSR_MODE_EL0t; 96 regs->pstate = PSR_MODE_EL0t;
99 regs->sp = sp; 97 regs->sp = sp;
100 regs->regs[2] = stack[2]; /* x2 (envp) */
101 regs->regs[1] = stack[1]; /* x1 (argv) */
102 regs->regs[0] = stack[0]; /* x0 (argc) */
103} 98}
104 99
105#ifdef CONFIG_COMPAT 100#ifdef CONFIG_COMPAT
106static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc, 101static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc,
107 unsigned long sp) 102 unsigned long sp)
108{ 103{
109 unsigned int *stack = (unsigned int *)sp;
110
111 start_thread_common(regs, pc); 104 start_thread_common(regs, pc);
112 regs->pstate = COMPAT_PSR_MODE_USR; 105 regs->pstate = COMPAT_PSR_MODE_USR;
113 if (pc & 1) 106 if (pc & 1)
114 regs->pstate |= COMPAT_PSR_T_BIT; 107 regs->pstate |= COMPAT_PSR_T_BIT;
115 regs->compat_sp = sp; 108 regs->compat_sp = sp;
116 regs->regs[2] = stack[2]; /* x2 (envp) */
117 regs->regs[1] = stack[1]; /* x1 (argv) */
118 regs->regs[0] = stack[0]; /* x0 (argc) */
119} 109}
120#endif 110#endif
121 111