diff options
Diffstat (limited to 'arch/powerpc/kernel/ptrace32.c')
-rw-r--r-- | arch/powerpc/kernel/ptrace32.c | 161 |
1 files changed, 31 insertions, 130 deletions
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c index fea6206ff90f..4c1de6af4c09 100644 --- a/arch/powerpc/kernel/ptrace32.c +++ b/arch/powerpc/kernel/ptrace32.c @@ -24,9 +24,11 @@ #include <linux/smp_lock.h> #include <linux/errno.h> #include <linux/ptrace.h> +#include <linux/regset.h> #include <linux/user.h> #include <linux/security.h> #include <linux/signal.h> +#include <linux/compat.h> #include <asm/uaccess.h> #include <asm/page.h> @@ -45,87 +47,31 @@ static long compat_ptrace_old(struct task_struct *child, long request, long addr, long data) { - int ret = -EPERM; - - switch(request) { - case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ - int i; - unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; - unsigned int __user *tmp = (unsigned int __user *)addr; - - CHECK_FULL_REGS(child->thread.regs); - for (i = 0; i < 32; i++) { - ret = put_user(*reg, tmp); - if (ret) - break; - reg++; - tmp++; - } - break; - } - - case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ - int i; - unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; - unsigned int __user *tmp = (unsigned int __user *)addr; - - CHECK_FULL_REGS(child->thread.regs); - for (i = 0; i < 32; i++) { - ret = get_user(*reg, tmp); - if (ret) - break; - reg++; - tmp++; - } - break; + switch (request) { + case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */ + return copy_regset_to_user(child, + task_user_regset_view(current), 0, + 0, 32 * sizeof(compat_long_t), + compat_ptr(data)); + + case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */ + return copy_regset_from_user(child, + task_user_regset_view(current), 0, + 0, 32 * sizeof(compat_long_t), + compat_ptr(data)); } - } - return ret; + return -EPERM; } -long compat_sys_ptrace(int request, int pid, unsigned long addr, - unsigned long data) +long compat_arch_ptrace(struct task_struct *child, compat_long_t request, + compat_ulong_t caddr, compat_ulong_t cdata) { - struct task_struct *child; + unsigned long addr = caddr; + unsigned long data = cdata; int ret; - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out; - } - - 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) { - /* when I and D space are separate, these will need to be fixed. */ - case PTRACE_PEEKTEXT: /* read word at location addr. */ - case PTRACE_PEEKDATA: { - unsigned int tmp; - int copied; - - copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); - ret = -EIO; - if (copied != sizeof(tmp)) - break; - ret = put_user(tmp, (u32 __user *)data); - break; - } - /* * Read 4 bytes of the other process' storage * data is a pointer specifying where the user wants the @@ -225,19 +171,6 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, break; } - /* If I and D space are separate, this will have to be fixed. */ - case PTRACE_POKETEXT: /* write the word at location addr. */ - case PTRACE_POKEDATA: { - unsigned int tmp; - tmp = data; - ret = 0; - if (access_process_vm(child, addr, &tmp, sizeof(tmp), 1) - == sizeof(tmp)) - break; - ret = -EIO; - break; - } - /* * Write 4 bytes into the other process' storage * data is the 4 bytes that the user wants written @@ -337,46 +270,17 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, break; } - case PTRACE_GETEVENTMSG: - ret = put_user(child->ptrace_message, (unsigned int __user *) data); - break; + case PTRACE_GETREGS: /* Get all pt_regs from the child. */ + return copy_regset_to_user( + child, task_user_regset_view(current), 0, + 0, PT_REGS_COUNT * sizeof(compat_long_t), + compat_ptr(data)); - case PTRACE_GETREGS: { /* Get all pt_regs from the child. */ - int ui; - if (!access_ok(VERIFY_WRITE, (void __user *)data, - PT_REGS_COUNT * sizeof(int))) { - ret = -EIO; - break; - } - CHECK_FULL_REGS(child->thread.regs); - ret = 0; - for (ui = 0; ui < PT_REGS_COUNT; ui ++) { - ret |= __put_user(ptrace_get_reg(child, ui), - (unsigned int __user *) data); - data += sizeof(int); - } - break; - } - - case PTRACE_SETREGS: { /* Set all gp regs in the child. */ - unsigned long tmp; - int ui; - if (!access_ok(VERIFY_READ, (void __user *)data, - PT_REGS_COUNT * sizeof(int))) { - ret = -EIO; - break; - } - CHECK_FULL_REGS(child->thread.regs); - ret = 0; - for (ui = 0; ui < PT_REGS_COUNT; ui ++) { - ret = __get_user(tmp, (unsigned int __user *) data); - if (ret) - break; - ptrace_put_reg(child, ui, tmp); - data += sizeof(int); - } - break; - } + case PTRACE_SETREGS: /* Set all gp regs in the child. */ + return copy_regset_from_user( + child, task_user_regset_view(current), 0, + 0, PT_REGS_COUNT * sizeof(compat_long_t), + compat_ptr(data)); case PTRACE_GETFPREGS: case PTRACE_SETFPREGS: @@ -402,12 +306,9 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr, break; default: - ret = ptrace_request(child, request, addr, data); + ret = compat_ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + return ret; } |