[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: Christoph Hellwig <hch@lst.de>
Acked-by: Paul Mackerras <paulus@samba.org>
Acked-by: Ralf Baechle <ralf@linux-mips.org>
Acked-By: David Howells <dhowells@redhat.com>
Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
Acked-by: Paul Mundt <lethal@linux-sh.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Christoph Hellwig 2005-11-07 00:59:47 -08:00 committed by Linus Torvalds
parent db73e9aa99
commit 481bed4542
27 changed files with 163 additions and 818 deletions

View File

@ -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
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;

View File

@ -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
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;

View File

@ -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)
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;
} }

View File

@ -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)
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;
} }

View File

@ -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)
ret = -EIO; ret = -EIO;
break; break;
} }
out_tsk:
put_task_struct(child);
out:
unlock_kernel();
return ret; return ret;
} }

View File

@ -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)
ret = -EIO; ret = -EIO;
break; break;
} }
out_tsk:
put_task_struct(child);
out:
unlock_kernel();
return ret; return ret;
} }

View File

@ -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)
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;
} }

View File

@ -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)
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)

View File

@ -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;
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) {
/* 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. */
@ -357,10 +324,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;
} }

View File

@ -174,51 +174,10 @@ int ptrace_setfpregs (struct task_struct *child, __u32 __user *data)
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;
int ret; int ret;
#if 0
printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
(int) request, (int) pid, (unsigned long) addr,
(unsigned long) data);
#endif
lock_kernel();
ret = -EPERM;
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
if (current->ptrace & PT_PTRACED)
goto out;
if ((ret = security_ptrace(current->parent, current)))
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. */
@ -319,7 +278,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
if (!cpu_has_dsp) { if (!cpu_has_dsp) {
tmp = 0; tmp = 0;
ret = -EIO; ret = -EIO;
goto out_tsk; goto out;
} }
if (child->thread.dsp.used_dsp) { if (child->thread.dsp.used_dsp) {
dregs = __get_dsp_regs(child); dregs = __get_dsp_regs(child);
@ -333,14 +292,14 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
if (!cpu_has_dsp) { if (!cpu_has_dsp) {
tmp = 0; tmp = 0;
ret = -EIO; ret = -EIO;
goto out_tsk; goto out;
} }
tmp = child->thread.dsp.dspcontrol; tmp = child->thread.dsp.dspcontrol;
break; break;
default: default:
tmp = 0; tmp = 0;
ret = -EIO; ret = -EIO;
goto out_tsk; goto out;
} }
ret = put_user(tmp, (unsigned long __user *) data); ret = put_user(tmp, (unsigned long __user *) data);
break; break;
@ -495,11 +454,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:
out_tsk:
put_task_struct(child);
out:
unlock_kernel();
return ret; return ret;
} }

View File

@ -78,52 +78,13 @@ void ptrace_disable(struct task_struct *child)
pa_psw(child)->l = 0; pa_psw(child)->l = 0;
} }
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;
long ret; long ret;
#ifdef DEBUG_PTRACE #ifdef DEBUG_PTRACE
long oaddr=addr, odata=data; long oaddr=addr, odata=data;
#endif #endif
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) /* no messing around 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: {
@ -383,11 +344,11 @@ long sys_ptrace(long request, long pid, long addr, long data)
case PTRACE_GETEVENTMSG: case PTRACE_GETEVENTMSG:
ret = put_user(child->ptrace_message, (unsigned int __user *) data); ret = put_user(child->ptrace_message, (unsigned int __user *) data);
goto out_tsk; goto out;
default: default:
ret = ptrace_request(child, request, addr, data); ret = ptrace_request(child, request, addr, data);
goto out_tsk; goto out;
} }
out_wake_notrap: out_wake_notrap:
@ -396,10 +357,7 @@ out_wake:
wake_up_process(child); wake_up_process(child);
ret = 0; ret = 0;
out_tsk: out_tsk:
put_task_struct(child); DBG("arch_ptrace(%ld, %d, %lx, %lx) returning %ld\n",
out:
unlock_kernel();
DBG("sys_ptrace(%ld, %d, %lx, %lx) returning %ld\n",
request, pid, oaddr, odata, ret); request, pid, oaddr, odata, ret);
return ret; return ret;
} }

View File

@ -248,46 +248,10 @@ void ptrace_disable(struct task_struct *child)
clear_single_step(child); clear_single_step(child);
} }
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 = -EPERM; int ret = -EPERM;
lock_kernel();
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. */
@ -540,10 +504,7 @@ 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;
} }

View File

@ -80,48 +80,11 @@ void ptrace_disable(struct task_struct *child)
/* nothing to do.. */ /* nothing to do.. */
} }
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 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. */
@ -289,10 +252,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:
put_task_struct(child);
out:
unlock_kernel();
return ret; return ret;
} }

View File

@ -28,6 +28,7 @@
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/user.h> #include <linux/user.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/syscalls.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
@ -121,61 +122,11 @@ put_fpu_long(struct task_struct *task, unsigned long addr, unsigned long data)
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;
extern void poke_real_address_q(unsigned long long addr, unsigned long long data);
#define WPC_DBRMODE 0x0d104008
static int first_call = 1;
int ret; int ret;
lock_kernel();
if (first_call) {
/* Set WPC.DBRMODE to 0. This makes all debug events get
* delivered through RESVEC, i.e. into the handlers in entry.S.
* (If the kernel was downloaded using a remote gdb, WPC.DBRMODE
* would normally be left set to 1, which makes debug events get
* delivered through DBRVEC, i.e. into the remote gdb's
* handlers. This prevents ptrace getting them, and confuses
* the remote gdb.) */
printk("DBRMODE set to 0 to permit native debugging\n");
poke_real_address_q(WPC_DBRMODE, 0);
first_call = 0;
}
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) {
/* 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. */
@ -313,13 +264,33 @@ 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;
} }
asmlinkage int sh64_ptrace(long request, long pid, long addr, long data)
{
extern void poke_real_address_q(unsigned long long addr, unsigned long long data);
#define WPC_DBRMODE 0x0d104008
static int first_call = 1;
lock_kernel();
if (first_call) {
/* Set WPC.DBRMODE to 0. This makes all debug events get
* delivered through RESVEC, i.e. into the handlers in entry.S.
* (If the kernel was downloaded using a remote gdb, WPC.DBRMODE
* would normally be left set to 1, which makes debug events get
* delivered through DBRVEC, i.e. into the remote gdb's
* handlers. This prevents ptrace getting them, and confuses
* the remote gdb.) */
printk("DBRMODE set to 0 to permit native debugging\n");
poke_real_address_q(WPC_DBRMODE, 0);
first_call = 0;
}
unlock_kernel();
return sys_ptrace(request, pid, addr, data);
}
asmlinkage void syscall_trace(void) asmlinkage void syscall_trace(void)
{ {
struct task_struct *tsk = current; struct task_struct *tsk = current;

View File

@ -46,7 +46,7 @@ sys_call_table:
.long sys_setuid16 .long sys_setuid16
.long sys_getuid16 .long sys_getuid16
.long sys_stime /* 25 */ .long sys_stime /* 25 */
.long sys_ptrace .long sh64_ptrace
.long sys_alarm .long sys_alarm
.long sys_fstat .long sys_fstat
.long sys_pause .long sys_pause

View File

@ -43,53 +43,10 @@ void ptrace_disable(struct task_struct *child)
extern int peek_user(struct task_struct * child, long addr, long data); extern int peek_user(struct task_struct * child, long addr, long data);
extern int poke_user(struct task_struct * child, long addr, long data); extern int poke_user(struct task_struct * child, long addr, long data);
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 i, ret; int i, 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;
}
#ifdef SUBACH_PTRACE_SPECIAL
SUBARCH_PTRACE_SPECIAL(child,request,addr,data);
#endif
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. */
@ -282,10 +239,7 @@ 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;
} }

View File

@ -113,45 +113,10 @@ static int set_single_step (struct task_struct *t, int val)
return 1; return 1;
} }
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 rval; int rval;
lock_kernel();
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
if (current->ptrace & PT_PTRACED) {
rval = -EPERM;
goto out;
}
/* set the ptrace bit in the process flags. */
current->ptrace |= PT_PTRACED;
rval = 0;
goto out;
}
rval = -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;
rval = -EPERM;
if (pid == 1) /* you may not mess with init */
goto out_tsk;
if (request == PTRACE_ATTACH) {
rval = ptrace_attach(child);
goto out_tsk;
}
rval = ptrace_check_attach(child, request == PTRACE_KILL);
if (rval < 0)
goto out_tsk;
switch (request) { switch (request) {
unsigned long val, copied; unsigned long val, copied;
@ -248,11 +213,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
rval = -EIO; rval = -EIO;
goto out; goto out;
} }
out:
out_tsk:
put_task_struct(child);
out:
unlock_kernel();
return rval; return rval;
} }

View File

@ -313,48 +313,11 @@ static unsigned long getreg(struct task_struct *child, unsigned long regno)
} }
asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data) long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{ {
struct task_struct *child;
long i, ret; long i, ret;
unsigned ui; unsigned ui;
/* This lock_kernel fixes a subtle race with suid exec */
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. */
@ -608,10 +571,6 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned 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;
} }

View File

@ -45,58 +45,10 @@ void ptrace_disable(struct task_struct *child)
/* Nothing to do.. */ /* Nothing to do.. */
} }
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 = -EPERM; int ret = -EPERM;
lock_kernel();
#if 0
if ((int)request != 1)
printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
(int) request, (int) pid, (unsigned long) addr,
(unsigned long) data);
#endif
if (request == PTRACE_TRACEME) {
/* Are we already being traced? */
if (current->ptrace & PT_PTRACED)
goto out;
if ((ret = security_ptrace(current->parent, current)))
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;
if (request == PTRACE_ATTACH) {
ret = ptrace_attach(child);
goto out_tsk;
}
if ((ret = ptrace_check_attach(child, request == PTRACE_KILL)) < 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:
@ -375,10 +327,7 @@ 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);
goto out; goto out;
} }
out_tsk: out:
put_task_struct(child);
out:
unlock_kernel();
return ret; return ret;
} }

View File

@ -67,6 +67,9 @@ struct switch_stack {
}; };
#ifdef __KERNEL__ #ifdef __KERNEL__
#define __ARCH_SYS_PTRACE 1
#define user_mode(regs) (((regs)->ps & 8) != 0) #define user_mode(regs) (((regs)->ps & 8) != 0)
#define instruction_pointer(regs) ((regs)->pc) #define instruction_pointer(regs) ((regs)->pc)
#define profile_pc(regs) instruction_pointer(regs) #define profile_pc(regs) instruction_pointer(regs)

View File

@ -229,6 +229,9 @@ struct switch_stack {
}; };
#ifdef __KERNEL__ #ifdef __KERNEL__
#define __ARCH_SYS_PTRACE 1
/* /*
* We use the ia64_psr(regs)->ri to determine which of the three * We use the ia64_psr(regs)->ri to determine which of the three
* instructions in bundle (16 bytes) took the sample. Generate * instructions in bundle (16 bytes) took the sample. Generate

View File

@ -145,6 +145,9 @@ struct pt_regs {
#define PTRACE_O_TRACESYSGOOD 0x00000001 #define PTRACE_O_TRACESYSGOOD 0x00000001
#ifdef __KERNEL__ #ifdef __KERNEL__
#define __ARCH_SYS_PTRACE 1
#if defined(CONFIG_ISA_M32R2) || defined(CONFIG_CHIP_VDEC2) #if defined(CONFIG_ISA_M32R2) || defined(CONFIG_CHIP_VDEC2)
#define user_mode(regs) ((M32R_PSW_BPM & (regs)->psw) != 0) #define user_mode(regs) ((M32R_PSW_BPM & (regs)->psw) != 0)
#elif defined(CONFIG_ISA_M32R) #elif defined(CONFIG_ISA_M32R)

View File

@ -468,6 +468,8 @@ struct user_regs_struct
}; };
#ifdef __KERNEL__ #ifdef __KERNEL__
#define __ARCH_SYS_PTRACE 1
#define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0) #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
#define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN) #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
#define profile_pc(regs) instruction_pointer(regs) #define profile_pc(regs) instruction_pointer(regs)

View File

@ -60,6 +60,9 @@ struct sparc_stackf {
#define STACKFRAME_SZ sizeof(struct sparc_stackf) #define STACKFRAME_SZ sizeof(struct sparc_stackf)
#ifdef __KERNEL__ #ifdef __KERNEL__
#define __ARCH_SYS_PTRACE 1
#define user_mode(regs) (!((regs)->psr & PSR_PS)) #define user_mode(regs) (!((regs)->psr & PSR_PS))
#define instruction_pointer(regs) ((regs)->pc) #define instruction_pointer(regs) ((regs)->pc)
unsigned long profile_pc(struct pt_regs *); unsigned long profile_pc(struct pt_regs *);

View File

@ -94,6 +94,9 @@ struct sparc_trapf {
#define STACKFRAME32_SZ sizeof(struct sparc_stackf32) #define STACKFRAME32_SZ sizeof(struct sparc_stackf32)
#ifdef __KERNEL__ #ifdef __KERNEL__
#define __ARCH_SYS_PTRACE 1
#define force_successful_syscall_return() \ #define force_successful_syscall_return() \
do { current_thread_info()->syscall_noerror = 1; \ do { current_thread_info()->syscall_noerror = 1; \
} while (0) } while (0)

View File

@ -78,6 +78,8 @@
#include <linux/compiler.h> /* For unlikely. */ #include <linux/compiler.h> /* For unlikely. */
#include <linux/sched.h> /* For struct task_struct. */ #include <linux/sched.h> /* For struct task_struct. */
extern long arch_ptrace(struct task_struct *child, long request, long addr, long data);
extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
extern int ptrace_attach(struct task_struct *tsk); extern int ptrace_attach(struct task_struct *tsk);

View File

@ -406,3 +406,85 @@ int ptrace_request(struct task_struct *child, long request,
return ret; return ret;
} }
#ifndef __ARCH_SYS_PTRACE
static int ptrace_get_task_struct(long request, long pid,
struct task_struct **childp)
{
struct task_struct *child;
int ret;
/*
* Callers use child == NULL as an indication to exit early even
* when the return value is 0, so make sure it is non-NULL here.
*/
*childp = NULL;
if (request == PTRACE_TRACEME) {
/*
* Are we already being traced?
*/
if (current->ptrace & PT_PTRACED)
return -EPERM;
ret = security_ptrace(current->parent, current);
if (ret)
return -EPERM;
/*
* Set the ptrace bit in the process ptrace flags.
*/
current->ptrace |= PT_PTRACED;
return 0;
}
/*
* You may not mess with init
*/
if (pid == 1)
return -EPERM;
ret = -ESRCH;
read_lock(&tasklist_lock);
child = find_task_by_pid(pid);
if (child)
get_task_struct(child);
read_unlock(&tasklist_lock);
if (!child)
return -ESRCH;
*childp = child;
return 0;
}
asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
long ret;
/*
* This lock_kernel fixes a subtle race with suid exec
*/
lock_kernel();
ret = ptrace_get_task_struct(request, pid, &child);
if (!child)
goto out;
if (request == PTRACE_ATTACH) {
ret = ptrace_attach(child);
goto out;
}
ret = ptrace_check_attach(child, request == PTRACE_KILL);
if (ret < 0)
goto out_put_task_struct;
ret = arch_ptrace(child, request, addr, data);
if (ret < 0)
goto out_put_task_struct;
out_put_task_struct:
put_task_struct(child);
out:
unlock_kernel();
return ret;
}
#endif /* __ARCH_SYS_PTRACE */