powerpc: switch to generic sys_execve()/kernel_execve()
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 31 Aug 2012 19:48:05 +0000 (15:48 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 1 Oct 2012 03:35:51 +0000 (23:35 -0400)
the only non-obvious part is that current_pt_regs() is really needed
here - task_pt_regs() is NULL for kernel threads; it's OK for ptrace
uses (the thing task_pt_regs() is intended for), but not for us.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
arch/powerpc/include/asm/ptrace.h
arch/powerpc/include/asm/syscalls.h
arch/powerpc/include/asm/unistd.h
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/misc.S
arch/powerpc/kernel/process.c
arch/powerpc/kernel/sys_ppc32.c

index 9c21ed4..f76b88c 100644 (file)
@@ -125,6 +125,8 @@ extern unsigned long ptrace_get_reg(struct task_struct *task, int regno);
 extern int ptrace_put_reg(struct task_struct *task, int regno,
                          unsigned long data);
 
+#define current_pt_regs() \
+       ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1)
 /*
  * We use the least-significant bit of the trap field to indicate
  * whether we have saved the full set of registers, or only a
index 4084e56..329db4e 100644 (file)
@@ -17,9 +17,6 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
 asmlinkage unsigned long sys_mmap2(unsigned long addr, size_t len,
                unsigned long prot, unsigned long flags,
                unsigned long fd, unsigned long pgoff);
-asmlinkage int sys_execve(unsigned long a0, unsigned long a1,
-               unsigned long a2, unsigned long a3, unsigned long a4,
-               unsigned long a5, struct pt_regs *regs);
 asmlinkage int sys_clone(unsigned long clone_flags, unsigned long usp,
                int __user *parent_tidp, void __user *child_threadptr,
                int __user *child_tidp, int p6, struct pt_regs *regs);
index bd377a3..26a6825 100644 (file)
 #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_SYS_NEWFSTATAT
 #endif
+#define __ARCH_WANT_SYS_EXECVE
+#define __ARCH_WANT_KERNEL_EXECVE
 
 /*
  * "Conditional" syscalls
index 6eb330a..e6be75f 100644 (file)
@@ -446,6 +446,11 @@ ret_from_kernel_thread:
        li      r3,0
        b       do_exit         # no return
 
+       .globl  __ret_from_kernel_execve
+__ret_from_kernel_execve:
+       addi    r1,r3,-STACK_FRAME_OVERHEAD
+       b       ret_from_syscall
+
 /* Traced system call support */
 syscall_dotrace:
        SAVE_NVGPRS(r1)
index d7f4faf..1ca3d9f 100644 (file)
@@ -380,6 +380,12 @@ _GLOBAL(ret_from_kernel_thread)
        li      r3,0
        b       .do_exit        # no return
 
+_GLOBAL(__ret_from_kernel_execve)
+       addi    r1,r3,-STACK_FRAME_OVERHEAD
+       li      r10,1
+       std     r10,SOFTE(r1)
+       b       syscall_exit
+
        .section        ".toc","aw"
 DSCR_DEFAULT:
        .tc dscr_default[TC],dscr_default
index ba16874..7ce26d4 100644 (file)
@@ -54,13 +54,6 @@ _GLOBAL(add_reloc_offset)
        .align  3
 2:     PPC_LONG 1b
 
-_GLOBAL(kernel_execve)
-       li      r0,__NR_execve
-       sc
-       bnslr
-       neg     r3,r3
-       blr
-
 _GLOBAL(setjmp)
        mflr    r0
        PPC_STL r0,0(r3)
index 3b06898..6fdf044 100644 (file)
@@ -1064,26 +1064,13 @@ int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3,
                        regs, 0, NULL, NULL);
 }
 
-int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
-              unsigned long a3, unsigned long a4, unsigned long a5,
-              struct pt_regs *regs)
+void __ret_from_kernel_execve(struct pt_regs *normal)
+__noreturn;
+
+void ret_from_kernel_execve(struct pt_regs *normal)
 {
-       int error;
-       char *filename;
-
-       filename = getname((const char __user *) a0);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       flush_fp_to_thread(current);
-       flush_altivec_to_thread(current);
-       flush_spe_to_thread(current);
-       error = do_execve(filename,
-                         (const char __user *const __user *) a1,
-                         (const char __user *const __user *) a2, regs);
-       putname(filename);
-out:
-       return error;
+       set_thread_flag(TIF_RESTOREALL);
+       __ret_from_kernel_execve(normal);
 }
 
 static inline int valid_irq_stack(unsigned long sp, struct task_struct *p,
index 81c5706..a1ae73a 100644 (file)
@@ -187,28 +187,6 @@ asmlinkage int compat_sys_sendfile64(int out_fd, int in_fd, compat_loff_t __user
        return ret;
 }
 
-long compat_sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
-                 unsigned long a3, unsigned long a4, unsigned long a5,
-                 struct pt_regs *regs)
-{
-       int error;
-       char * filename;
-       
-       filename = getname((char __user *) a0);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       flush_fp_to_thread(current);
-       flush_altivec_to_thread(current);
-
-       error = compat_do_execve(filename, compat_ptr(a1), compat_ptr(a2), regs);
-
-       putname(filename);
-
-out:
-       return error;
-}
-
 /* Note: it is necessary to treat option as an unsigned int, 
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)