diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-08-31 15:48:05 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-09-30 23:35:51 -0400 |
commit | be6abfa769fa07ce89ac73273360b335ae978805 (patch) | |
tree | e6b9ba23767a93839c5e4e14f197d4781bf95cf4 /arch | |
parent | 58254e1002a82eb383c5977ad9fd5a451b91fe29 (diff) |
powerpc: switch to generic sys_execve()/kernel_execve()
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>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/include/asm/ptrace.h | 2 | ||||
-rw-r--r-- | arch/powerpc/include/asm/syscalls.h | 3 | ||||
-rw-r--r-- | arch/powerpc/include/asm/unistd.h | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/entry_32.S | 5 | ||||
-rw-r--r-- | arch/powerpc/kernel/entry_64.S | 6 | ||||
-rw-r--r-- | arch/powerpc/kernel/misc.S | 7 | ||||
-rw-r--r-- | arch/powerpc/kernel/process.c | 25 | ||||
-rw-r--r-- | arch/powerpc/kernel/sys_ppc32.c | 22 |
8 files changed, 21 insertions, 51 deletions
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h index 9c21ed42aba6..f76b88c367d1 100644 --- a/arch/powerpc/include/asm/ptrace.h +++ b/arch/powerpc/include/asm/ptrace.h | |||
@@ -125,6 +125,8 @@ extern unsigned long ptrace_get_reg(struct task_struct *task, int regno); | |||
125 | extern int ptrace_put_reg(struct task_struct *task, int regno, | 125 | extern int ptrace_put_reg(struct task_struct *task, int regno, |
126 | unsigned long data); | 126 | unsigned long data); |
127 | 127 | ||
128 | #define current_pt_regs() \ | ||
129 | ((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE) - 1) | ||
128 | /* | 130 | /* |
129 | * We use the least-significant bit of the trap field to indicate | 131 | * We use the least-significant bit of the trap field to indicate |
130 | * whether we have saved the full set of registers, or only a | 132 | * whether we have saved the full set of registers, or only a |
diff --git a/arch/powerpc/include/asm/syscalls.h b/arch/powerpc/include/asm/syscalls.h index 4084e567d28e..329db4ec12ca 100644 --- a/arch/powerpc/include/asm/syscalls.h +++ b/arch/powerpc/include/asm/syscalls.h | |||
@@ -17,9 +17,6 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, | |||
17 | asmlinkage unsigned long sys_mmap2(unsigned long addr, size_t len, | 17 | asmlinkage unsigned long sys_mmap2(unsigned long addr, size_t len, |
18 | unsigned long prot, unsigned long flags, | 18 | unsigned long prot, unsigned long flags, |
19 | unsigned long fd, unsigned long pgoff); | 19 | unsigned long fd, unsigned long pgoff); |
20 | asmlinkage int sys_execve(unsigned long a0, unsigned long a1, | ||
21 | unsigned long a2, unsigned long a3, unsigned long a4, | ||
22 | unsigned long a5, struct pt_regs *regs); | ||
23 | asmlinkage int sys_clone(unsigned long clone_flags, unsigned long usp, | 20 | asmlinkage int sys_clone(unsigned long clone_flags, unsigned long usp, |
24 | int __user *parent_tidp, void __user *child_threadptr, | 21 | int __user *parent_tidp, void __user *child_threadptr, |
25 | int __user *child_tidp, int p6, struct pt_regs *regs); | 22 | int __user *child_tidp, int p6, struct pt_regs *regs); |
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index bd377a368611..26a6825909b6 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h | |||
@@ -420,6 +420,8 @@ | |||
420 | #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND | 420 | #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND |
421 | #define __ARCH_WANT_SYS_NEWFSTATAT | 421 | #define __ARCH_WANT_SYS_NEWFSTATAT |
422 | #endif | 422 | #endif |
423 | #define __ARCH_WANT_SYS_EXECVE | ||
424 | #define __ARCH_WANT_KERNEL_EXECVE | ||
423 | 425 | ||
424 | /* | 426 | /* |
425 | * "Conditional" syscalls | 427 | * "Conditional" syscalls |
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 6eb330a87c36..e6be75fc491a 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
@@ -446,6 +446,11 @@ ret_from_kernel_thread: | |||
446 | li r3,0 | 446 | li r3,0 |
447 | b do_exit # no return | 447 | b do_exit # no return |
448 | 448 | ||
449 | .globl __ret_from_kernel_execve | ||
450 | __ret_from_kernel_execve: | ||
451 | addi r1,r3,-STACK_FRAME_OVERHEAD | ||
452 | b ret_from_syscall | ||
453 | |||
449 | /* Traced system call support */ | 454 | /* Traced system call support */ |
450 | syscall_dotrace: | 455 | syscall_dotrace: |
451 | SAVE_NVGPRS(r1) | 456 | SAVE_NVGPRS(r1) |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index d7f4fafc7515..1ca3d9fa48c4 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -380,6 +380,12 @@ _GLOBAL(ret_from_kernel_thread) | |||
380 | li r3,0 | 380 | li r3,0 |
381 | b .do_exit # no return | 381 | b .do_exit # no return |
382 | 382 | ||
383 | _GLOBAL(__ret_from_kernel_execve) | ||
384 | addi r1,r3,-STACK_FRAME_OVERHEAD | ||
385 | li r10,1 | ||
386 | std r10,SOFTE(r1) | ||
387 | b syscall_exit | ||
388 | |||
383 | .section ".toc","aw" | 389 | .section ".toc","aw" |
384 | DSCR_DEFAULT: | 390 | DSCR_DEFAULT: |
385 | .tc dscr_default[TC],dscr_default | 391 | .tc dscr_default[TC],dscr_default |
diff --git a/arch/powerpc/kernel/misc.S b/arch/powerpc/kernel/misc.S index ba16874fe294..7ce26d45777e 100644 --- a/arch/powerpc/kernel/misc.S +++ b/arch/powerpc/kernel/misc.S | |||
@@ -54,13 +54,6 @@ _GLOBAL(add_reloc_offset) | |||
54 | .align 3 | 54 | .align 3 |
55 | 2: PPC_LONG 1b | 55 | 2: PPC_LONG 1b |
56 | 56 | ||
57 | _GLOBAL(kernel_execve) | ||
58 | li r0,__NR_execve | ||
59 | sc | ||
60 | bnslr | ||
61 | neg r3,r3 | ||
62 | blr | ||
63 | |||
64 | _GLOBAL(setjmp) | 57 | _GLOBAL(setjmp) |
65 | mflr r0 | 58 | mflr r0 |
66 | PPC_STL r0,0(r3) | 59 | PPC_STL r0,0(r3) |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 3b06898fa175..6fdf044f475c 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -1064,26 +1064,13 @@ int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3, | |||
1064 | regs, 0, NULL, NULL); | 1064 | regs, 0, NULL, NULL); |
1065 | } | 1065 | } |
1066 | 1066 | ||
1067 | int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, | 1067 | void __ret_from_kernel_execve(struct pt_regs *normal) |
1068 | unsigned long a3, unsigned long a4, unsigned long a5, | 1068 | __noreturn; |
1069 | struct pt_regs *regs) | 1069 | |
1070 | void ret_from_kernel_execve(struct pt_regs *normal) | ||
1070 | { | 1071 | { |
1071 | int error; | 1072 | set_thread_flag(TIF_RESTOREALL); |
1072 | char *filename; | 1073 | __ret_from_kernel_execve(normal); |
1073 | |||
1074 | filename = getname((const char __user *) a0); | ||
1075 | error = PTR_ERR(filename); | ||
1076 | if (IS_ERR(filename)) | ||
1077 | goto out; | ||
1078 | flush_fp_to_thread(current); | ||
1079 | flush_altivec_to_thread(current); | ||
1080 | flush_spe_to_thread(current); | ||
1081 | error = do_execve(filename, | ||
1082 | (const char __user *const __user *) a1, | ||
1083 | (const char __user *const __user *) a2, regs); | ||
1084 | putname(filename); | ||
1085 | out: | ||
1086 | return error; | ||
1087 | } | 1074 | } |
1088 | 1075 | ||
1089 | static inline int valid_irq_stack(unsigned long sp, struct task_struct *p, | 1076 | static inline int valid_irq_stack(unsigned long sp, struct task_struct *p, |
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c index 81c570633ead..a1ae73a0f352 100644 --- a/arch/powerpc/kernel/sys_ppc32.c +++ b/arch/powerpc/kernel/sys_ppc32.c | |||
@@ -187,28 +187,6 @@ asmlinkage int compat_sys_sendfile64(int out_fd, int in_fd, compat_loff_t __user | |||
187 | return ret; | 187 | return ret; |
188 | } | 188 | } |
189 | 189 | ||
190 | long compat_sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, | ||
191 | unsigned long a3, unsigned long a4, unsigned long a5, | ||
192 | struct pt_regs *regs) | ||
193 | { | ||
194 | int error; | ||
195 | char * filename; | ||
196 | |||
197 | filename = getname((char __user *) a0); | ||
198 | error = PTR_ERR(filename); | ||
199 | if (IS_ERR(filename)) | ||
200 | goto out; | ||
201 | flush_fp_to_thread(current); | ||
202 | flush_altivec_to_thread(current); | ||
203 | |||
204 | error = compat_do_execve(filename, compat_ptr(a1), compat_ptr(a2), regs); | ||
205 | |||
206 | putname(filename); | ||
207 | |||
208 | out: | ||
209 | return error; | ||
210 | } | ||
211 | |||
212 | /* Note: it is necessary to treat option as an unsigned int, | 190 | /* Note: it is necessary to treat option as an unsigned int, |
213 | * with the corresponding cast to a signed int to insure that the | 191 | * with the corresponding cast to a signed int to insure that the |
214 | * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) | 192 | * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) |