Commit 481bed45 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Linus Torvalds
Browse files

[PATCH] consolidate sys_ptrace()



The sys_ptrace boilerplate code (everything outside the big switch
statement for the arch-specific requests) is shared by most architectures.
This patch moves it to kernel/ptrace.c and leaves the arch-specific code as
arch_ptrace.

Some architectures have a too different ptrace so we have to exclude them.
They continue to keep their implementations.  For sh64 I had to add a
sh64_ptrace wrapper because it does some initialization on the first call.
For um I removed an ifdefed SUBARCH_PTRACE_SPECIAL block, but
SUBARCH_PTRACE_SPECIAL isn't defined anywhere in the tree.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Acked-by: default avatarPaul Mackerras <paulus@samba.org>
Acked-by: default avatarRalf Baechle <ralf@linux-mips.org>
Acked-By: default avatarDavid Howells <dhowells@redhat.com>
Acked-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
Acked-by: default avatarPaul Mundt <lethal@linux-sh.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent db73e9aa
...@@ -648,7 +648,7 @@ static int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp) ...@@ -648,7 +648,7 @@ static int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp)
#endif #endif
static int do_ptrace(int request, struct task_struct *child, long addr, long data) long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{ {
unsigned long tmp; unsigned long tmp;
int ret; int ret;
...@@ -782,53 +782,6 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat ...@@ -782,53 +782,6 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
return ret; return ret;
} }
asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
int ret;
lock_kernel();
ret = -EPERM;
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
if (current->ptrace & PT_PTRACED)
goto out;
ret = security_ptrace(current->parent, current);
if (ret)
goto out;
/* set the ptrace bit in the process flags. */
current->ptrace |= PT_PTRACED;
ret = 0;
goto out;
}
ret = -ESRCH;
read_lock(&tasklist_lock);
child = find_task_by_pid(pid);
if (child)
get_task_struct(child);
read_unlock(&tasklist_lock);
if (!child)
goto out;
ret = -EPERM;
if (pid == 1) /* you may not mess with init */
goto out_tsk;
if (request == PTRACE_ATTACH) {
ret = ptrace_attach(child);
goto out_tsk;
}
ret = ptrace_check_attach(child, request == PTRACE_KILL);
if (ret == 0)
ret = do_ptrace(request, child, addr, data);
out_tsk:
put_task_struct(child);
out:
unlock_kernel();
return ret;
}
asmlinkage void syscall_trace(int why, struct pt_regs *regs) asmlinkage void syscall_trace(int why, struct pt_regs *regs)
{ {
unsigned long ip; unsigned long ip;
......
...@@ -546,7 +546,7 @@ static int ptrace_setfpregs(struct task_struct *tsk, void *ufp) ...@@ -546,7 +546,7 @@ static int ptrace_setfpregs(struct task_struct *tsk, void *ufp)
sizeof(struct user_fp)) ? -EFAULT : 0; sizeof(struct user_fp)) ? -EFAULT : 0;
} }
static int do_ptrace(int request, struct task_struct *child, long addr, long data) long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{ {
unsigned long tmp; unsigned long tmp;
int ret; int ret;
...@@ -665,53 +665,6 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat ...@@ -665,53 +665,6 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
return ret; return ret;
} }
asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
int ret;
lock_kernel();
ret = -EPERM;
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
if (current->ptrace & PT_PTRACED)
goto out;
ret = security_ptrace(current->parent, current);
if (ret)
goto out;
/* set the ptrace bit in the process flags. */
current->ptrace |= PT_PTRACED;
ret = 0;
goto out;
}
ret = -ESRCH;
read_lock(&tasklist_lock);
child = find_task_by_pid(pid);
if (child)
get_task_struct(child);
read_unlock(&tasklist_lock);
if (!child)
goto out;
ret = -EPERM;
if (pid == 1) /* you may not mess with init */
goto out_tsk;
if (request == PTRACE_ATTACH) {
ret = ptrace_attach(child);
goto out_tsk;
}
ret = ptrace_check_attach(child, request == PTRACE_KILL);
if (ret == 0)
ret = do_ptrace(request, child, addr, data);
out_tsk:
put_task_struct(child);
out:
unlock_kernel();
return ret;
}
asmlinkage void syscall_trace(int why, struct pt_regs *regs) asmlinkage void syscall_trace(int why, struct pt_regs *regs)
{ {
unsigned long ip; unsigned long ip;
......
...@@ -76,55 +76,11 @@ ptrace_disable(struct task_struct *child) ...@@ -76,55 +76,11 @@ ptrace_disable(struct task_struct *child)
* (in user space) where the result of the ptrace call is written (instead of * (in user space) where the result of the ptrace call is written (instead of
* being returned). * being returned).
*/ */
asmlinkage int long arch_ptrace(struct task_struct *child, long request, long addr, long data)
sys_ptrace(long request, long pid, long addr, long data)
{ {
struct task_struct *child;
int ret; int ret;
unsigned long __user *datap = (unsigned long __user *)data; unsigned long __user *datap = (unsigned long __user *)data;
lock_kernel();
ret = -EPERM;
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
if (current->ptrace & PT_PTRACED)
goto out;
ret = security_ptrace(current->parent, current);
if (ret)
goto out;
/* set the ptrace bit in the process flags. */
current->ptrace |= PT_PTRACED;
ret = 0;
goto out;
}
ret = -ESRCH;
read_lock(&tasklist_lock);
child = find_task_by_pid(pid);
if (child)
get_task_struct(child);
read_unlock(&tasklist_lock);
if (!child)
goto out;
ret = -EPERM;
if (pid == 1) /* Leave the init process alone! */
goto out_tsk;
if (request == PTRACE_ATTACH) {
ret = ptrace_attach(child);
goto out_tsk;
}
ret = ptrace_check_attach(child, request == PTRACE_KILL);
if (ret < 0)
goto out_tsk;
switch (request) { switch (request) {
/* Read word at location address. */ /* Read word at location address. */
case PTRACE_PEEKTEXT: case PTRACE_PEEKTEXT:
...@@ -289,10 +245,7 @@ sys_ptrace(long request, long pid, long addr, long data) ...@@ -289,10 +245,7 @@ sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_request(child, request, addr, data); ret = ptrace_request(child, request, addr, data);
break; break;
} }
out_tsk:
put_task_struct(child);
out:
unlock_kernel();
return ret; return ret;
} }
......
...@@ -99,55 +99,11 @@ ptrace_disable(struct task_struct *child) ...@@ -99,55 +99,11 @@ ptrace_disable(struct task_struct *child)
} }
asmlinkage int long arch_ptrace(struct task_struct *child, long request, long addr, long data)
sys_ptrace(long request, long pid, long addr, long data)
{ {
struct task_struct *child;
int ret; int ret;
unsigned long __user *datap = (unsigned long __user *)data; unsigned long __user *datap = (unsigned long __user *)data;
lock_kernel();
ret = -EPERM;
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
if (current->ptrace & PT_PTRACED)
goto out;
ret = security_ptrace(current->parent, current);
if (ret)
goto out;
/* set the ptrace bit in the process flags. */
current->ptrace |= PT_PTRACED;
ret = 0;
goto out;
}
ret = -ESRCH;
read_lock(&tasklist_lock);
child = find_task_by_pid(pid);
if (child)
get_task_struct(child);
read_unlock(&tasklist_lock);
if (!child)
goto out;
ret = -EPERM;
if (pid == 1) /* Leave the init process alone! */
goto out_tsk;
if (request == PTRACE_ATTACH) {
ret = ptrace_attach(child);
goto out_tsk;
}
ret = ptrace_check_attach(child, request == PTRACE_KILL);
if (ret < 0)
goto out_tsk;
switch (request) { switch (request) {
/* Read word at location address. */ /* Read word at location address. */
case PTRACE_PEEKTEXT: case PTRACE_PEEKTEXT:
...@@ -347,10 +303,7 @@ sys_ptrace(long request, long pid, long addr, long data) ...@@ -347,10 +303,7 @@ sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_request(child, request, addr, data); ret = ptrace_request(child, request, addr, data);
break; break;
} }
out_tsk:
put_task_struct(child);
out:
unlock_kernel();
return ret; return ret;
} }
......
...@@ -106,48 +106,11 @@ void ptrace_enable(struct task_struct *child) ...@@ -106,48 +106,11 @@ void ptrace_enable(struct task_struct *child)
child->thread.frame0->__status |= REG__STATUS_STEP; child->thread.frame0->__status |= REG__STATUS_STEP;
} }
asmlinkage long sys_ptrace(long request, long pid, long addr, long data) long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{ {
struct task_struct *child;
unsigned long tmp; unsigned long tmp;
int ret; int ret;
lock_kernel();
ret = -EPERM;
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
if (current->ptrace & PT_PTRACED)
goto out;
ret = security_ptrace(current->parent, current);
if (ret)
goto out;
/* set the ptrace bit in the process flags. */
current->ptrace |= PT_PTRACED;
ret = 0;
goto out;
}
ret = -ESRCH;
read_lock(&tasklist_lock);
child = find_task_by_pid(pid);
if (child)
get_task_struct(child);
read_unlock(&tasklist_lock);
if (!child)
goto out;
ret = -EPERM;
if (pid == 1) /* you may not mess with init */
goto out_tsk;
if (request == PTRACE_ATTACH) {
ret = ptrace_attach(child);
goto out_tsk;
}
ret = ptrace_check_attach(child, request == PTRACE_KILL);
if (ret < 0)
goto out_tsk;
switch (request) { switch (request) {
/* when I and D space are separate, these will need to be fixed. */ /* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKTEXT: /* read word at location addr. */
...@@ -351,10 +314,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ...@@ -351,10 +314,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO; ret = -EIO;
break; break;
} }
out_tsk:
put_task_struct(child);
out:
unlock_kernel();
return ret; return ret;
} }
......
...@@ -57,43 +57,10 @@ void ptrace_disable(struct task_struct *child) ...@@ -57,43 +57,10 @@ void ptrace_disable(struct task_struct *child)
h8300_disable_trace(child); h8300_disable_trace(child);
} }
asmlinkage long sys_ptrace(long request, long pid, long addr, long data) long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{ {
struct task_struct *child;
int ret; int ret;
lock_kernel();
ret = -EPERM;
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
if (current->ptrace & PT_PTRACED)
goto out;
/* set the ptrace bit in the process flags. */
current->ptrace |= PT_PTRACED;
ret = 0;
goto out;
}
ret = -ESRCH;
read_lock(&tasklist_lock);
child = find_task_by_pid(pid);
if (child)
get_task_struct(child);
read_unlock(&tasklist_lock);
if (!child)
goto out;
ret = -EPERM;
if (pid == 1) /* you may not mess with init */
goto out_tsk;
if (request == PTRACE_ATTACH) {
ret = ptrace_attach(child);
goto out_tsk;
}
ret = ptrace_check_attach(child, request == PTRACE_KILL);
if (ret < 0)
goto out_tsk;
switch (request) { switch (request) {
case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: { case PTRACE_PEEKDATA: {
...@@ -251,10 +218,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ...@@ -251,10 +218,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO; ret = -EIO;
break; break;
} }
out_tsk:
put_task_struct(child);
out:
unlock_kernel();
return ret; return ret;
} }
......
...@@ -354,49 +354,12 @@ ptrace_set_thread_area(struct task_struct *child, ...@@ -354,49 +354,12 @@ ptrace_set_thread_area(struct task_struct *child,
return 0; return 0;
} }
asmlinkage long sys_ptrace(long request, long pid, long addr, long data) long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{ {
struct task_struct *child;
struct user * dummy = NULL; struct user * dummy = NULL;
int i, ret; int i, ret;
unsigned long __user *datap = (unsigned long __user *)data; unsigned long __user *datap = (unsigned long __user *)data;
lock_kernel();
ret = -EPERM;
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
if (current->ptrace & PT_PTRACED)
goto out;
ret = security_ptrace(current->parent, current);
if (ret)
goto out;
/* set the ptrace bit in the process flags. */
current->ptrace |= PT_PTRACED;
ret = 0;
goto out;
}
ret = -ESRCH;
read_lock(&tasklist_lock);
child = find_task_by_pid(pid);
if (child)
get_task_struct(child);
read_unlock(&tasklist_lock);
if (!child)
goto out;
ret = -EPERM;
if (pid == 1) /* you may not mess with init */
goto out_tsk;
if (request == PTRACE_ATTACH) {
ret = ptrace_attach(child);
goto out_tsk;
}
ret = ptrace_check_attach(child, request == PTRACE_KILL);
if (ret < 0)
goto out_tsk;
switch (request) { switch (request) {
/* when I and D space are separate, these will need to be fixed. */ /* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKTEXT: /* read word at location addr. */
...@@ -663,10 +626,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ...@@ -663,10 +626,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_request(child, request, addr, data); ret = ptrace_request(child, request, addr, data);
break; break;
} }
out_tsk: out_tsk:
put_task_struct(child);
out:
unlock_kernel();
return ret; return ret;
} }
......
...@@ -121,48 +121,11 @@ void ptrace_disable(struct task_struct *child) ...@@ -121,48 +121,11 @@ void ptrace_disable(struct task_struct *child)
child->thread.work.syscall_trace = 0; child->thread.work.syscall_trace = 0;
} }
asmlinkage long sys_ptrace(long request, long pid, long addr, long data) long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{ {
struct task_struct *child;
unsigned long tmp; unsigned long tmp;
int i, ret = 0; int i, ret = 0;
lock_kernel();
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
if (current->ptrace & PT_PTRACED) {
ret = -EPERM;
goto out;
}
/* set the ptrace bit in the process flags. */
current->ptrace |= PT_PTRACED;
goto out;
}
read_lock(&tasklist_lock);
child = find_task_by_pid(pid);
if (child)
get_task_struct(child);
read_unlock(&tasklist_lock);
if (unlikely(!child)) {
ret = -ESRCH;
goto out;
}
/* you may not mess with init */
if (unlikely(pid == 1)) {
ret = -EPERM;
goto out_tsk;
}
if (request == PTRACE_ATTACH) {
ret = ptrace_attach(child);
goto out_tsk;
}
ret = ptrace_check_attach(child, request == PTRACE_KILL);
if (ret)
goto out_tsk;
switch (request) { switch (request) {
/* when I and D space are separate, these will need to be fixed. */ /* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKTEXT: /* read word at location addr. */
...@@ -317,14 +280,10 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ...@@ -317,14 +280,10 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_request(child, request, addr, data); ret = ptrace_request(child, request, addr, data);
break; break;
} }
out_tsk:
put_task_struct(child);
out:
unlock_kernel();
return ret; return ret;
out_eio: out_eio:
ret = -EIO; return -EIO;
goto out_tsk;
} }
asmlinkage void syscall_trace(void) asmlinkage void syscall_trace(void)
......
...@@ -101,43 +101,10 @@ void ptrace_disable(struct task_struct *child) ...@@ -101,43 +101,10 @@ void ptrace_disable(struct task_struct *child)
put_reg(child, PT_SR, tmp); put_reg(child, PT_SR, tmp);
} }
asmlinkage long sys_ptrace(long request, long pid, long addr, long data) long arch_ptrace(truct task_struct *child, long request, long addr, long data)
{ {
struct task_struct *child;
int ret; int ret;