Commit a7aea5bf authored by Russell King's avatar Russell King

[ARM] Convert execve() to be a function rather than a SWI call.

This eliminates the last SWI user from the kernel - now all SWI calls
will only come from userspace.  More importantly, this also allows us
to empty the kernel stack when starting userspace programs from
kernelspace, thereby ensuring that the user registers always appear
at the top of the kernel stack.
parent 31aa2bf6
......@@ -12,6 +12,7 @@
* have a non-standard calling sequence on the Linux/arm
* platform.
*/
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/slab.h>
......@@ -282,3 +283,43 @@ asmlinkage int sys_execve(char __user *filenamei, char __user * __user *argv,
out:
return error;
}
long execve(const char *filename, char **argv, char **envp)
{
struct pt_regs regs;
int ret;
memset(&regs, 0, sizeof(struct pt_regs));
ret = do_execve((char *)filename, (char __user * __user *)argv,
(char __user * __user *)envp, &regs);
if (ret < 0)
goto out;
/*
* Save argc to the register structure for userspace.
*/
regs.ARM_r0 = ret;
/*
* We were successful. We won't be returning to our caller, but
* instead to user space by manipulating the kernel stack.
*/
asm( "add r0, %0, %1\n\t"
"mov r1, %2\n\t"
"mov r2, %3\n\t"
"bl memmove\n\t" /* copy regs to top of stack */
"mov r8, #0\n\t" /* not a syscall */
"mov r9, %0\n\t" /* thread structure */
"mov sp, r0\n\t" /* reposition stack pointer */
"b ret_to_user"
:
: "r" (current_thread_info()),
"Ir" (THREAD_SIZE - 8 - sizeof(regs)),
"r" (&regs),
"Ir" (sizeof(regs))
: "r0", "r1", "r2", "r3", "ip", "memory");
out:
return ret;
}
EXPORT_SYMBOL(execve);
......@@ -499,6 +499,8 @@ static inline pid_t waitpid(pid_t pid, int *wait_stat, int options)
return sys_wait4((int)pid, wait_stat, options, NULL);
}
extern long execve(const char *file, char **argv, char **envp);
struct pt_regs;
asmlinkage int sys_execve(char *filenamei, char **argv, char **envp,
struct pt_regs *regs);
......@@ -514,12 +516,6 @@ asmlinkage long sys_rt_sigaction(int sig,
struct sigaction __user *oact,
size_t sigsetsize);
/*
* The following two can't be eliminated yet - they rely on
* specific conditions.
*/
static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp);
#endif
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment