Skip to content

Commit

Permalink
Merge branch 'execve' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/cmarinas/linux-aarch64 into no-rebases
  • Loading branch information
Al Viro committed Oct 17, 2012
2 parents 43cc05a + 6a87277 commit 0cea479
Show file tree
Hide file tree
Showing 10 changed files with 33 additions and 157 deletions.
2 changes: 2 additions & 0 deletions arch/arm64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ config ARM64
select GENERIC_IOMAP
select GENERIC_IRQ_PROBE
select GENERIC_IRQ_SHOW
select GENERIC_KERNEL_EXECVE
select GENERIC_KERNEL_THREAD
select GENERIC_SMP_IDLE_THREAD
select GENERIC_TIME_VSYSCALL
select HARDIRQS_SW_RESEND
Expand Down
5 changes: 0 additions & 5 deletions arch/arm64/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,6 @@ unsigned long get_wchan(struct task_struct *p);
extern struct task_struct *cpu_switch_to(struct task_struct *prev,
struct task_struct *next);

/*
* Create a new kernel thread
*/
extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);

#define task_pt_regs(p) \
((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)

Expand Down
3 changes: 0 additions & 3 deletions arch/arm64/include/asm/syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@
/*
* System call wrappers implemented in kernel/entry.S.
*/
asmlinkage long sys_execve_wrapper(const char __user *filename,
const char __user *const __user *argv,
const char __user *const __user *envp);
asmlinkage long sys_clone_wrapper(unsigned long clone_flags,
unsigned long newsp,
void __user *parent_tid,
Expand Down
1 change: 1 addition & 0 deletions arch/arm64/include/asm/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@
#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
#define __ARCH_WANT_COMPAT_SYS_SENDFILE
#endif
#define __ARCH_WANT_SYS_EXECVE
#include <uapi/asm/unistd.h>
2 changes: 1 addition & 1 deletion arch/arm64/include/asm/unistd32.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ __SYSCALL(7, sys_ni_syscall) /* 7 was sys_waitpid */
__SYSCALL(8, sys_creat)
__SYSCALL(9, sys_link)
__SYSCALL(10, sys_unlink)
__SYSCALL(11, compat_sys_execve_wrapper)
__SYSCALL(11, compat_sys_execve)
__SYSCALL(12, sys_chdir)
__SYSCALL(13, sys_ni_syscall) /* 13 was sys_time */
__SYSCALL(14, sys_mknod)
Expand Down
12 changes: 5 additions & 7 deletions arch/arm64/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ work_resched:
/*
* "slow" syscall return path.
*/
ENTRY(ret_to_user)
ret_to_user:
disable_irq // disable interrupts
ldr x1, [tsk, #TI_FLAGS]
and x2, x1, #_TIF_WORK_MASK
Expand All @@ -611,7 +611,10 @@ ENDPROC(ret_to_user)
*/
ENTRY(ret_from_fork)
bl schedule_tail
get_thread_info tsk
cbz x19, 1f // not a kernel thread
mov x0, x20
blr x19
1: get_thread_info tsk
b ret_to_user
ENDPROC(ret_from_fork)

Expand Down Expand Up @@ -673,11 +676,6 @@ __sys_trace_return:
/*
* Special system call wrappers.
*/
ENTRY(sys_execve_wrapper)
mov x3, sp
b sys_execve
ENDPROC(sys_execve_wrapper)

ENTRY(sys_clone_wrapper)
mov x5, sp
b sys_clone
Expand Down
77 changes: 24 additions & 53 deletions arch/arm64/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,27 +240,35 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
struct pt_regs *childregs = task_pt_regs(p);
unsigned long tls = p->thread.tp_value;

*childregs = *regs;
childregs->regs[0] = 0;
memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context));

if (is_compat_thread(task_thread_info(p)))
childregs->compat_sp = stack_start;
else {
if (likely(regs)) {
*childregs = *regs;
childregs->regs[0] = 0;
if (is_compat_thread(task_thread_info(p))) {
childregs->compat_sp = stack_start;
} else {
/*
* Read the current TLS pointer from tpidr_el0 as it may be
* out-of-sync with the saved value.
*/
asm("mrs %0, tpidr_el0" : "=r" (tls));
childregs->sp = stack_start;
}
/*
* Read the current TLS pointer from tpidr_el0 as it may be
* out-of-sync with the saved value.
* If a TLS pointer was passed to clone (4th argument), use it
* for the new thread.
*/
asm("mrs %0, tpidr_el0" : "=r" (tls));
childregs->sp = stack_start;
if (clone_flags & CLONE_SETTLS)
tls = regs->regs[3];
} else {
memset(childregs, 0, sizeof(struct pt_regs));
childregs->pstate = PSR_MODE_EL1h;
p->thread.cpu_context.x19 = stack_start;
p->thread.cpu_context.x20 = stk_sz;
}

memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context));
p->thread.cpu_context.sp = (unsigned long)childregs;
p->thread.cpu_context.pc = (unsigned long)ret_from_fork;

/* If a TLS pointer was passed to clone, use that for the new thread. */
if (clone_flags & CLONE_SETTLS)
tls = regs->regs[3];
p->thread.cpu_context.sp = (unsigned long)childregs;
p->thread.tp_value = tls;

ptrace_hw_copy_thread(p);
Expand Down Expand Up @@ -327,43 +335,6 @@ int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
}
EXPORT_SYMBOL(dump_fpu);

/*
* Shuffle the argument into the correct register before calling the
* thread function. x1 is the thread argument, x2 is the pointer to
* the thread function, and x3 points to the exit function.
*/
extern void kernel_thread_helper(void);
asm( ".section .text\n"
" .align\n"
" .type kernel_thread_helper, #function\n"
"kernel_thread_helper:\n"
" mov x0, x1\n"
" mov x30, x3\n"
" br x2\n"
" .size kernel_thread_helper, . - kernel_thread_helper\n"
" .previous");

#define kernel_thread_exit do_exit

/*
* Create a kernel thread.
*/
pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
{
struct pt_regs regs;

memset(&regs, 0, sizeof(regs));

regs.regs[1] = (unsigned long)arg;
regs.regs[2] = (unsigned long)fn;
regs.regs[3] = (unsigned long)kernel_thread_exit;
regs.pc = (unsigned long)kernel_thread_helper;
regs.pstate = PSR_MODE_EL1h;

return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
}
EXPORT_SYMBOL(kernel_thread);

unsigned long get_wchan(struct task_struct *p)
{
struct stackframe frame;
Expand Down
65 changes: 0 additions & 65 deletions arch/arm64/kernel/sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,70 +41,6 @@ asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
}

/*
* sys_execve() executes a new program.
*/
asmlinkage long sys_execve(const char __user *filenamei,
const char __user *const __user *argv,
const char __user *const __user *envp,
struct pt_regs *regs)
{
long error;
struct filename *filename;

filename = getname(filenamei);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = do_execve(filename->name, argv, envp, regs);
putname(filename);
out:
return error;
}

int kernel_execve(const char *filename,
const char *const argv[],
const char *const envp[])
{
struct pt_regs regs;
int ret;

memset(&regs, 0, sizeof(struct pt_regs));
ret = do_execve(filename,
(const char __user *const __user *)argv,
(const char __user *const __user *)envp, &regs);
if (ret < 0)
goto out;

/*
* Save argc to the register structure for userspace.
*/
regs.regs[0] = ret;

/*
* We were successful. We won't be returning to our caller, but
* instead to user space by manipulating the kernel stack.
*/
asm( "add x0, %0, %1\n\t"
"mov x1, %2\n\t"
"mov x2, %3\n\t"
"bl memmove\n\t" /* copy regs to top of stack */
"mov x27, #0\n\t" /* not a syscall */
"mov x28, %0\n\t" /* thread structure */
"mov sp, x0\n\t" /* reposition stack pointer */
"b ret_to_user"
:
: "r" (current_thread_info()),
"Ir" (THREAD_START_SP - sizeof(regs)),
"r" (&regs),
"Ir" (sizeof(regs))
: "x0", "x1", "x2", "x27", "x28", "x30", "memory");

out:
return ret;
}
EXPORT_SYMBOL(kernel_execve);

asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
unsigned long fd, off_t off)
Expand All @@ -118,7 +54,6 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
/*
* Wrappers to pass the pt_regs argument.
*/
#define sys_execve sys_execve_wrapper
#define sys_clone sys_clone_wrapper
#define sys_rt_sigreturn sys_rt_sigreturn_wrapper
#define sys_sigaltstack sys_sigaltstack_wrapper
Expand Down
5 changes: 0 additions & 5 deletions arch/arm64/kernel/sys32.S
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,6 @@ compat_sys_vfork_wrapper:
b compat_sys_vfork
ENDPROC(compat_sys_vfork_wrapper)

compat_sys_execve_wrapper:
mov x3, sp
b compat_sys_execve
ENDPROC(compat_sys_execve_wrapper)

compat_sys_clone_wrapper:
mov x5, sp
b compat_sys_clone
Expand Down
18 changes: 0 additions & 18 deletions arch/arm64/kernel/sys_compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,24 +49,6 @@ asmlinkage int compat_sys_vfork(struct pt_regs *regs)
regs, 0, NULL, NULL);
}

asmlinkage int compat_sys_execve(const char __user *filenamei,
compat_uptr_t argv, compat_uptr_t envp,
struct pt_regs *regs)
{
int error;
struct filename *filename;

filename = getname(filenamei);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = compat_do_execve(filename->name, compat_ptr(argv),
compat_ptr(envp), regs);
putname(filename);
out:
return error;
}

asmlinkage int compat_sys_sched_rr_get_interval(compat_pid_t pid,
struct compat_timespec __user *interval)
{
Expand Down

0 comments on commit 0cea479

Please sign in to comment.