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>
This commit is contained in:
Родитель
58254e1002
Коммит
be6abfa769
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -420,6 +420,8 @@
|
|||
#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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
int error;
|
||||
char *filename;
|
||||
void __ret_from_kernel_execve(struct pt_regs *normal)
|
||||
__noreturn;
|
||||
|
||||
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;
|
||||
void ret_from_kernel_execve(struct pt_regs *normal)
|
||||
{
|
||||
set_thread_flag(TIF_RESTOREALL);
|
||||
__ret_from_kernel_execve(normal);
|
||||
}
|
||||
|
||||
static inline int valid_irq_stack(unsigned long sp, struct task_struct *p,
|
||||
|
|
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче