diff options
| -rw-r--r-- | arch/tile/kernel/compat.c | 4 | ||||
| -rw-r--r-- | arch/tile/kernel/ptrace.c | 78 |
2 files changed, 38 insertions, 44 deletions
diff --git a/arch/tile/kernel/compat.c b/arch/tile/kernel/compat.c index 5f24e54bf3c5..77739cdd9462 100644 --- a/arch/tile/kernel/compat.c +++ b/arch/tile/kernel/compat.c | |||
| @@ -154,8 +154,8 @@ long tile_compat_sys_msgrcv(int msqid, | |||
| 154 | #define compat_sys_fstat64 sys_newfstat | 154 | #define compat_sys_fstat64 sys_newfstat |
| 155 | #define compat_sys_fstatat64 sys_newfstatat | 155 | #define compat_sys_fstatat64 sys_newfstatat |
| 156 | 156 | ||
| 157 | /* Pass full 64-bit values through ptrace. */ | 157 | /* The native sys_ptrace dynamically handles compat binaries. */ |
| 158 | #define compat_sys_ptrace tile_compat_sys_ptrace | 158 | #define compat_sys_ptrace sys_ptrace |
| 159 | 159 | ||
| 160 | /* Call the trampolines to manage pt_regs where necessary. */ | 160 | /* Call the trampolines to manage pt_regs where necessary. */ |
| 161 | #define compat_sys_execve _compat_sys_execve | 161 | #define compat_sys_execve _compat_sys_execve |
diff --git a/arch/tile/kernel/ptrace.c b/arch/tile/kernel/ptrace.c index 7161bd03d2fd..5b20c2874d51 100644 --- a/arch/tile/kernel/ptrace.c +++ b/arch/tile/kernel/ptrace.c | |||
| @@ -32,25 +32,6 @@ void user_disable_single_step(struct task_struct *child) | |||
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | /* | 34 | /* |
| 35 | * This routine will put a word on the process's privileged stack. | ||
| 36 | */ | ||
| 37 | static void putreg(struct task_struct *task, | ||
| 38 | unsigned long addr, unsigned long value) | ||
| 39 | { | ||
| 40 | unsigned int regno = addr / sizeof(unsigned long); | ||
| 41 | struct pt_regs *childregs = task_pt_regs(task); | ||
| 42 | childregs->regs[regno] = value; | ||
| 43 | childregs->flags |= PT_FLAGS_RESTORE_REGS; | ||
| 44 | } | ||
| 45 | |||
| 46 | static unsigned long getreg(struct task_struct *task, unsigned long addr) | ||
| 47 | { | ||
| 48 | unsigned int regno = addr / sizeof(unsigned long); | ||
| 49 | struct pt_regs *childregs = task_pt_regs(task); | ||
| 50 | return childregs->regs[regno]; | ||
| 51 | } | ||
| 52 | |||
| 53 | /* | ||
| 54 | * Called by kernel/ptrace.c when detaching.. | 35 | * Called by kernel/ptrace.c when detaching.. |
| 55 | */ | 36 | */ |
| 56 | void ptrace_disable(struct task_struct *child) | 37 | void ptrace_disable(struct task_struct *child) |
| @@ -66,59 +47,72 @@ void ptrace_disable(struct task_struct *child) | |||
| 66 | 47 | ||
| 67 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 48 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
| 68 | { | 49 | { |
| 69 | unsigned long __user *datap; | 50 | unsigned long __user *datap = (long __user __force *)data; |
| 70 | unsigned long tmp; | 51 | unsigned long tmp; |
| 71 | int i; | 52 | int i; |
| 72 | long ret = -EIO; | 53 | long ret = -EIO; |
| 73 | 54 | unsigned long *childregs; | |
| 74 | #ifdef CONFIG_COMPAT | 55 | char *childreg; |
| 75 | if (task_thread_info(current)->status & TS_COMPAT) | ||
| 76 | data = (u32)data; | ||
| 77 | if (task_thread_info(child)->status & TS_COMPAT) | ||
| 78 | addr = (u32)addr; | ||
| 79 | #endif | ||
| 80 | datap = (unsigned long __user __force *)data; | ||
| 81 | 56 | ||
| 82 | switch (request) { | 57 | switch (request) { |
| 83 | 58 | ||
| 84 | case PTRACE_PEEKUSR: /* Read register from pt_regs. */ | 59 | case PTRACE_PEEKUSR: /* Read register from pt_regs. */ |
| 85 | if (addr & (sizeof(data)-1)) | ||
| 86 | break; | ||
| 87 | if (addr < 0 || addr >= PTREGS_SIZE) | 60 | if (addr < 0 || addr >= PTREGS_SIZE) |
| 88 | break; | 61 | break; |
| 89 | tmp = getreg(child, addr); /* Read register */ | 62 | childreg = (char *)task_pt_regs(child) + addr; |
| 90 | ret = put_user(tmp, datap); | 63 | #ifdef CONFIG_COMPAT |
| 64 | if (is_compat_task()) { | ||
| 65 | if (addr & (sizeof(compat_long_t)-1)) | ||
| 66 | break; | ||
| 67 | ret = put_user(*(compat_long_t *)childreg, | ||
| 68 | (compat_long_t __user *)datap); | ||
| 69 | } else | ||
| 70 | #endif | ||
| 71 | { | ||
| 72 | if (addr & (sizeof(long)-1)) | ||
| 73 | break; | ||
| 74 | ret = put_user(*(long *)childreg, datap); | ||
| 75 | } | ||
| 91 | break; | 76 | break; |
| 92 | 77 | ||
| 93 | case PTRACE_POKEUSR: /* Write register in pt_regs. */ | 78 | case PTRACE_POKEUSR: /* Write register in pt_regs. */ |
| 94 | if (addr & (sizeof(data)-1)) | ||
| 95 | break; | ||
| 96 | if (addr < 0 || addr >= PTREGS_SIZE) | 79 | if (addr < 0 || addr >= PTREGS_SIZE) |
| 97 | break; | 80 | break; |
| 98 | putreg(child, addr, data); /* Write register */ | 81 | childreg = (char *)task_pt_regs(child) + addr; |
| 82 | #ifdef CONFIG_COMPAT | ||
| 83 | if (is_compat_task()) { | ||
| 84 | if (addr & (sizeof(compat_long_t)-1)) | ||
| 85 | break; | ||
| 86 | *(compat_long_t *)childreg = data; | ||
| 87 | } else | ||
| 88 | #endif | ||
| 89 | { | ||
| 90 | if (addr & (sizeof(long)-1)) | ||
| 91 | break; | ||
| 92 | *(long *)childreg = data; | ||
| 93 | } | ||
| 99 | ret = 0; | 94 | ret = 0; |
| 100 | break; | 95 | break; |
| 101 | 96 | ||
| 102 | case PTRACE_GETREGS: /* Get all registers from the child. */ | 97 | case PTRACE_GETREGS: /* Get all registers from the child. */ |
| 103 | if (!access_ok(VERIFY_WRITE, datap, PTREGS_SIZE)) | 98 | if (!access_ok(VERIFY_WRITE, datap, PTREGS_SIZE)) |
| 104 | break; | 99 | break; |
| 105 | for (i = 0; i < PTREGS_SIZE; i += sizeof(long)) { | 100 | childregs = (long *)task_pt_regs(child); |
| 106 | ret = __put_user(getreg(child, i), datap); | 101 | for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) { |
| 102 | ret = __put_user(childregs[i], &datap[i]); | ||
| 107 | if (ret != 0) | 103 | if (ret != 0) |
| 108 | break; | 104 | break; |
| 109 | datap++; | ||
| 110 | } | 105 | } |
| 111 | break; | 106 | break; |
| 112 | 107 | ||
| 113 | case PTRACE_SETREGS: /* Set all registers in the child. */ | 108 | case PTRACE_SETREGS: /* Set all registers in the child. */ |
| 114 | if (!access_ok(VERIFY_READ, datap, PTREGS_SIZE)) | 109 | if (!access_ok(VERIFY_READ, datap, PTREGS_SIZE)) |
| 115 | break; | 110 | break; |
| 116 | for (i = 0; i < PTREGS_SIZE; i += sizeof(long)) { | 111 | childregs = (long *)task_pt_regs(child); |
| 117 | ret = __get_user(tmp, datap); | 112 | for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) { |
| 113 | ret = __get_user(childregs[i], &datap[i]); | ||
| 118 | if (ret != 0) | 114 | if (ret != 0) |
| 119 | break; | 115 | break; |
| 120 | putreg(child, i, tmp); | ||
| 121 | datap++; | ||
| 122 | } | 116 | } |
| 123 | break; | 117 | break; |
| 124 | 118 | ||
