Commit 8c2379a4 authored by Richard Henderson's avatar Richard Henderson

[ALPHA] Sync with i386 ptrace changes.

parent 00742b03
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/user.h> #include <linux/user.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/security.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
...@@ -255,6 +256,8 @@ do_sys_ptrace(long request, long pid, long addr, long data, ...@@ -255,6 +256,8 @@ do_sys_ptrace(long request, long pid, long addr, long data,
struct pt_regs *regs) struct pt_regs *regs)
{ {
struct task_struct *child; struct task_struct *child;
unsigned long tmp;
size_t copied;
long ret; long ret;
lock_kernel(); lock_kernel();
...@@ -265,6 +268,9 @@ do_sys_ptrace(long request, long pid, long addr, long data, ...@@ -265,6 +268,9 @@ do_sys_ptrace(long request, long pid, long addr, long data,
/* are we already being traced? */ /* are we already being traced? */
if (current->ptrace & PT_PTRACED) if (current->ptrace & PT_PTRACED)
goto out_notsk; goto out_notsk;
ret = security_ptrace(current->parent, current);
if (ret)
goto out_notsk;
/* set the ptrace bit in the process ptrace flags. */ /* set the ptrace bit in the process ptrace flags. */
current->ptrace |= PT_PTRACED; current->ptrace |= PT_PTRACED;
ret = 0; ret = 0;
...@@ -272,6 +278,7 @@ do_sys_ptrace(long request, long pid, long addr, long data, ...@@ -272,6 +278,7 @@ do_sys_ptrace(long request, long pid, long addr, long data,
} }
if (pid == 1) /* you may not mess with init */ if (pid == 1) /* you may not mess with init */
goto out_notsk; goto out_notsk;
ret = -ESRCH; ret = -ESRCH;
read_lock(&tasklist_lock); read_lock(&tasklist_lock);
child = find_task_by_pid(pid); child = find_task_by_pid(pid);
...@@ -280,77 +287,65 @@ do_sys_ptrace(long request, long pid, long addr, long data, ...@@ -280,77 +287,65 @@ do_sys_ptrace(long request, long pid, long addr, long data,
read_unlock(&tasklist_lock); read_unlock(&tasklist_lock);
if (!child) if (!child)
goto out_notsk; goto out_notsk;
if (request == PTRACE_ATTACH) { if (request == PTRACE_ATTACH) {
ret = ptrace_attach(child); ret = ptrace_attach(child);
goto out; goto out;
} }
ret = -ESRCH;
if (!(child->ptrace & PT_PTRACED)) { ret = ptrace_check_attach(child, request == PTRACE_KILL);
DBG(DBG_MEM, ("child not traced\n")); if (ret < 0)
goto out;
}
if (child->state != TASK_STOPPED) {
DBG(DBG_MEM, ("child process not stopped\n"));
if (request != PTRACE_KILL)
goto out;
}
if (child->parent != current) {
DBG(DBG_MEM, ("child not parent of this process\n"));
goto out; goto out;
}
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. */
case PTRACE_PEEKDATA: { case PTRACE_PEEKDATA:
unsigned long tmp; copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
int copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
ret = -EIO; ret = -EIO;
if (copied != sizeof(tmp)) if (copied != sizeof(tmp))
goto out; break;
regs->r0 = 0; /* special return: no errors */ regs->r0 = 0; /* special return: no errors */
ret = tmp; ret = tmp;
goto out; break;
}
/* Read register number ADDR. */ /* Read register number ADDR. */
case PTRACE_PEEKUSR: case PTRACE_PEEKUSR:
regs->r0 = 0; /* special return: no errors */ regs->r0 = 0; /* special return: no errors */
ret = get_reg(child, addr); ret = get_reg(child, addr);
DBG(DBG_MEM, ("peek $%ld->%#lx\n", addr, ret)); DBG(DBG_MEM, ("peek $%ld->%#lx\n", addr, ret));
goto out; break;
/* When I and D space are separate, this will have to be fixed. */ /* When I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA: { case PTRACE_POKEDATA:
unsigned long tmp = data; tmp = data;
int copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 1); copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 1);
ret = (copied == sizeof(tmp)) ? 0 : -EIO; ret = (copied == sizeof(tmp)) ? 0 : -EIO;
goto out; break;
}
case PTRACE_POKEUSR: /* write the specified register */ case PTRACE_POKEUSR: /* write the specified register */
DBG(DBG_MEM, ("poke $%ld<-%#lx\n", addr, data)); DBG(DBG_MEM, ("poke $%ld<-%#lx\n", addr, data));
ret = put_reg(child, addr, data); ret = put_reg(child, addr, data);
goto out; break;
case PTRACE_SYSCALL: /* continue and stop at next case PTRACE_SYSCALL:
(return from) syscall */ /* continue and stop at next (return from) syscall */
case PTRACE_CONT: /* restart after signal. */ case PTRACE_CONT: /* restart after signal. */
ret = -EIO; ret = -EIO;
if ((unsigned long) data > _NSIG) if ((unsigned long) data > _NSIG)
goto out; break;
if (request == PTRACE_SYSCALL) if (request == PTRACE_SYSCALL)
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
else else
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
child->exit_code = data; child->exit_code = data;
wake_up_process(child);
/* make sure single-step breakpoint is gone. */ /* make sure single-step breakpoint is gone. */
ptrace_cancel_bpt(child); ptrace_cancel_bpt(child);
ret = data; wake_up_process(child);
goto out; ret = 0;
break;
/* /*
* Make the child exit. Best I can do is send it a sigkill. * Make the child exit. Best I can do is send it a sigkill.
...@@ -358,19 +353,19 @@ do_sys_ptrace(long request, long pid, long addr, long data, ...@@ -358,19 +353,19 @@ do_sys_ptrace(long request, long pid, long addr, long data,
* exit. * exit.
*/ */
case PTRACE_KILL: case PTRACE_KILL:
if (child->state != TASK_ZOMBIE) { ret = 0;
wake_up_process(child); if (child->state == TASK_ZOMBIE)
child->exit_code = SIGKILL; break;
} child->exit_code = SIGKILL;
/* make sure single-step breakpoint is gone. */ /* make sure single-step breakpoint is gone. */
ptrace_cancel_bpt(child); ptrace_cancel_bpt(child);
ret = 0; wake_up_process(child);
goto out; goto out;
case PTRACE_SINGLESTEP: /* execute single instruction. */ case PTRACE_SINGLESTEP: /* execute single instruction. */
ret = -EIO; ret = -EIO;
if ((unsigned long) data > _NSIG) if ((unsigned long) data > _NSIG)
goto out; break;
/* Mark single stepping. */ /* Mark single stepping. */
child->thread_info->bpt_nsaved = -1; child->thread_info->bpt_nsaved = -1;
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment