diff options
| author | Roland McGrath <roland@redhat.com> | 2007-12-20 06:59:04 -0500 |
|---|---|---|
| committer | Paul Mackerras <paulus@samba.org> | 2008-02-07 04:40:21 -0500 |
| commit | 0deef2c7ab9dcf82f6ad26fc2fca358cd56c9cb9 (patch) | |
| tree | 00e0b016d28ec2f4d717196fb43b0f70fcce5a69 | |
| parent | 81e695c026eeda9a97e412fa4f458e5cab2f6c85 (diff) | |
[POWERPC] Use regset code for compat PTRACE_*REGS* calls
This cleans up the 32-bit ptrace syscall support to use user_regset calls
to get at the register data for PTRACE_*REGS* calls.
Signed-off-by: Roland McGrath <roland@redhat.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
| -rw-r--r-- | arch/powerpc/kernel/ptrace32.c | 96 |
1 files changed, 25 insertions, 71 deletions
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c index 0f6eea086a23..4c1de6af4c09 100644 --- a/arch/powerpc/kernel/ptrace32.c +++ b/arch/powerpc/kernel/ptrace32.c | |||
| @@ -24,6 +24,7 @@ | |||
| 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> |
| @@ -46,43 +47,21 @@ | |||
| 46 | static long compat_ptrace_old(struct task_struct *child, long request, | 47 | static long compat_ptrace_old(struct task_struct *child, long request, |
| 47 | long addr, long data) | 48 | long addr, long data) |
| 48 | { | 49 | { |
| 49 | int ret = -EPERM; | 50 | switch (request) { |
| 50 | 51 | case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */ | |
| 51 | switch(request) { | 52 | return copy_regset_to_user(child, |
| 52 | case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ | 53 | task_user_regset_view(current), 0, |
| 53 | int i; | 54 | 0, 32 * sizeof(compat_long_t), |
| 54 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | 55 | compat_ptr(data)); |
| 55 | unsigned int __user *tmp = (unsigned int __user *)addr; | 56 | |
| 56 | 57 | case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */ | |
| 57 | CHECK_FULL_REGS(child->thread.regs); | 58 | return copy_regset_from_user(child, |
| 58 | for (i = 0; i < 32; i++) { | 59 | task_user_regset_view(current), 0, |
| 59 | ret = put_user(*reg, tmp); | 60 | 0, 32 * sizeof(compat_long_t), |
| 60 | if (ret) | 61 | compat_ptr(data)); |
| 61 | break; | ||
| 62 | reg++; | ||
| 63 | tmp++; | ||
| 64 | } | ||
| 65 | break; | ||
| 66 | } | ||
| 67 | |||
| 68 | case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ | ||
| 69 | int i; | ||
| 70 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||
| 71 | unsigned int __user *tmp = (unsigned int __user *)addr; | ||
| 72 | |||
| 73 | CHECK_FULL_REGS(child->thread.regs); | ||
| 74 | for (i = 0; i < 32; i++) { | ||
| 75 | ret = get_user(*reg, tmp); | ||
| 76 | if (ret) | ||
| 77 | break; | ||
| 78 | reg++; | ||
| 79 | tmp++; | ||
| 80 | } | ||
| 81 | break; | ||
| 82 | } | 62 | } |
| 83 | 63 | ||
| 84 | } | 64 | return -EPERM; |
| 85 | return ret; | ||
| 86 | } | 65 | } |
| 87 | 66 | ||
| 88 | long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | 67 | long compat_arch_ptrace(struct task_struct *child, compat_long_t request, |
| @@ -291,42 +270,17 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
| 291 | break; | 270 | break; |
| 292 | } | 271 | } |
| 293 | 272 | ||
| 294 | case PTRACE_GETREGS: { /* Get all pt_regs from the child. */ | 273 | case PTRACE_GETREGS: /* Get all pt_regs from the child. */ |
| 295 | int ui; | 274 | return copy_regset_to_user( |
| 296 | if (!access_ok(VERIFY_WRITE, (void __user *)data, | 275 | child, task_user_regset_view(current), 0, |
| 297 | PT_REGS_COUNT * sizeof(int))) { | 276 | 0, PT_REGS_COUNT * sizeof(compat_long_t), |
| 298 | ret = -EIO; | 277 | compat_ptr(data)); |
| 299 | break; | 278 | |
| 300 | } | 279 | case PTRACE_SETREGS: /* Set all gp regs in the child. */ |
| 301 | CHECK_FULL_REGS(child->thread.regs); | 280 | return copy_regset_from_user( |
| 302 | ret = 0; | 281 | child, task_user_regset_view(current), 0, |
| 303 | for (ui = 0; ui < PT_REGS_COUNT; ui ++) { | 282 | 0, PT_REGS_COUNT * sizeof(compat_long_t), |
| 304 | ret |= __put_user(ptrace_get_reg(child, ui), | 283 | compat_ptr(data)); |
| 305 | (unsigned int __user *) data); | ||
| 306 | data += sizeof(int); | ||
| 307 | } | ||
| 308 | break; | ||
| 309 | } | ||
| 310 | |||
| 311 | case PTRACE_SETREGS: { /* Set all gp regs in the child. */ | ||
| 312 | unsigned long tmp; | ||
| 313 | int ui; | ||
| 314 | if (!access_ok(VERIFY_READ, (void __user *)data, | ||
| 315 | PT_REGS_COUNT * sizeof(int))) { | ||
| 316 | ret = -EIO; | ||
| 317 | break; | ||
| 318 | } | ||
| 319 | CHECK_FULL_REGS(child->thread.regs); | ||
| 320 | ret = 0; | ||
| 321 | for (ui = 0; ui < PT_REGS_COUNT; ui ++) { | ||
| 322 | ret = __get_user(tmp, (unsigned int __user *) data); | ||
| 323 | if (ret) | ||
| 324 | break; | ||
| 325 | ptrace_put_reg(child, ui, tmp); | ||
| 326 | data += sizeof(int); | ||
| 327 | } | ||
| 328 | break; | ||
| 329 | } | ||
| 330 | 284 | ||
| 331 | case PTRACE_GETFPREGS: | 285 | case PTRACE_GETFPREGS: |
| 332 | case PTRACE_SETFPREGS: | 286 | case PTRACE_SETFPREGS: |
