aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/ptrace32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/ptrace32.c')
-rw-r--r--arch/powerpc/kernel/ptrace32.c161
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 @@
24#include <linux/smp_lock.h> 24#include <linux/smp_lock.h>
25#include <linux/errno.h> 25#include <linux/errno.h>
26#include <linux/ptrace.h> 26#include <linux/ptrace.h>
27#include <linux/regset.h>
27#include <linux/user.h> 28#include <linux/user.h>
28#include <linux/security.h> 29#include <linux/security.h>
29#include <linux/signal.h> 30#include <linux/signal.h>
31#include <linux/compat.h>
30 32
31#include <asm/uaccess.h> 33#include <asm/uaccess.h>
32#include <asm/page.h> 34#include <asm/page.h>
@@ -45,87 +47,31 @@
45static long compat_ptrace_old(struct task_struct *child, long request, 47static long compat_ptrace_old(struct task_struct *child, long request,
46 long addr, long data) 48 long addr, long data)
47{ 49{
48 int ret = -EPERM; 50 switch (request) {
49 51 case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */
50 switch(request) { 52 return copy_regset_to_user(child,
51 case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ 53 task_user_regset_view(current), 0,
52 int i; 54 0, 32 * sizeof(compat_long_t),
53 unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; 55 compat_ptr(data));
54 unsigned int __user *tmp = (unsigned int __user *)addr; 56
55 57 case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */
56 CHECK_FULL_REGS(child->thread.regs); 58 return copy_regset_from_user(child,
57 for (i = 0; i < 32; i++) { 59 task_user_regset_view(current), 0,
58 ret = put_user(*reg, tmp); 60 0, 32 * sizeof(compat_long_t),
59 if (ret) 61 compat_ptr(data));
60 break;
61 reg++;
62 tmp++;
63 }
64 break;
65 }
66
67 case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
68 int i;
69 unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
70 unsigned int __user *tmp = (unsigned int __user *)addr;
71
72 CHECK_FULL_REGS(child->thread.regs);
73 for (i = 0; i < 32; i++) {
74 ret = get_user(*reg, tmp);
75 if (ret)
76 break;
77 reg++;
78 tmp++;
79 }
80 break;
81 } 62 }
82 63
83 } 64 return -EPERM;
84 return ret;
85} 65}
86 66
87long compat_sys_ptrace(int request, int pid, unsigned long addr, 67long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
88 unsigned long data) 68 compat_ulong_t caddr, compat_ulong_t cdata)
89{ 69{
90 struct task_struct *child; 70 unsigned long addr = caddr;
71 unsigned long data = cdata;
91 int ret; 72 int ret;
92 73
93 lock_kernel();
94 if (request == PTRACE_TRACEME) {
95 ret = ptrace_traceme();
96 goto out;
97 }
98
99 child = ptrace_get_task_struct(pid);
100 if (IS_ERR(child)) {
101 ret = PTR_ERR(child);
102 goto out;
103 }
104
105 if (request == PTRACE_ATTACH) {
106 ret = ptrace_attach(child);
107 goto out_tsk;
108 }
109
110 ret = ptrace_check_attach(child, request == PTRACE_KILL);
111 if (ret < 0)
112 goto out_tsk;
113
114 switch (request) { 74 switch (request) {
115 /* when I and D space are separate, these will need to be fixed. */
116 case PTRACE_PEEKTEXT: /* read word at location addr. */
117 case PTRACE_PEEKDATA: {
118 unsigned int tmp;
119 int copied;
120
121 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
122 ret = -EIO;
123 if (copied != sizeof(tmp))
124 break;
125 ret = put_user(tmp, (u32 __user *)data);
126 break;
127 }
128
129 /* 75 /*
130 * Read 4 bytes of the other process' storage 76 * Read 4 bytes of the other process' storage
131 * data is a pointer specifying where the user wants the 77 * 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,
225 break; 171 break;
226 } 172 }
227 173
228 /* If I and D space are separate, this will have to be fixed. */
229 case PTRACE_POKETEXT: /* write the word at location addr. */
230 case PTRACE_POKEDATA: {
231 unsigned int tmp;
232 tmp = data;
233 ret = 0;
234 if (access_process_vm(child, addr, &tmp, sizeof(tmp), 1)
235 == sizeof(tmp))
236 break;
237 ret = -EIO;
238 break;
239 }
240
241 /* 174 /*
242 * Write 4 bytes into the other process' storage 175 * Write 4 bytes into the other process' storage
243 * data is the 4 bytes that the user wants written 176 * 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,
337 break; 270 break;
338 } 271 }
339 272
340 case PTRACE_GETEVENTMSG: 273 case PTRACE_GETREGS: /* Get all pt_regs from the child. */
341 ret = put_user(child->ptrace_message, (unsigned int __user *) data); 274 return copy_regset_to_user(
342 break; 275 child, task_user_regset_view(current), 0,
276 0, PT_REGS_COUNT * sizeof(compat_long_t),
277 compat_ptr(data));
343 278
344 case PTRACE_GETREGS: { /* Get all pt_regs from the child. */ 279 case PTRACE_SETREGS: /* Set all gp regs in the child. */
345 int ui; 280 return copy_regset_from_user(
346 if (!access_ok(VERIFY_WRITE, (void __user *)data, 281 child, task_user_regset_view(current), 0,
347 PT_REGS_COUNT * sizeof(int))) { 282 0, PT_REGS_COUNT * sizeof(compat_long_t),
348 ret = -EIO; 283 compat_ptr(data));
349 break;
350 }
351 CHECK_FULL_REGS(child->thread.regs);
352 ret = 0;
353 for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
354 ret |= __put_user(ptrace_get_reg(child, ui),
355 (unsigned int __user *) data);
356 data += sizeof(int);
357 }
358 break;
359 }
360
361 case PTRACE_SETREGS: { /* Set all gp regs in the child. */
362 unsigned long tmp;
363 int ui;
364 if (!access_ok(VERIFY_READ, (void __user *)data,
365 PT_REGS_COUNT * sizeof(int))) {
366 ret = -EIO;
367 break;
368 }
369 CHECK_FULL_REGS(child->thread.regs);
370 ret = 0;
371 for (ui = 0; ui < PT_REGS_COUNT; ui ++) {
372 ret = __get_user(tmp, (unsigned int __user *) data);
373 if (ret)
374 break;
375 ptrace_put_reg(child, ui, tmp);
376 data += sizeof(int);
377 }
378 break;
379 }
380 284
381 case PTRACE_GETFPREGS: 285 case PTRACE_GETFPREGS:
382 case PTRACE_SETFPREGS: 286 case PTRACE_SETFPREGS:
@@ -402,12 +306,9 @@ long compat_sys_ptrace(int request, int pid, unsigned long addr,
402 break; 306 break;
403 307
404 default: 308 default:
405 ret = ptrace_request(child, request, addr, data); 309 ret = compat_ptrace_request(child, request, addr, data);
406 break; 310 break;
407 } 311 }
408out_tsk: 312
409 put_task_struct(child);
410out:
411 unlock_kernel();
412 return ret; 313 return ret;
413} 314}