[SPARC]: Fix several regset and ptrace bugs.

1) ptrace should pass 'current' to task_user_regset_view()

2) When fetching general registers using a 64-bit view, and
the target is 32-bit, we have to convert.

3) Skip the whole register window get/set code block if
the user isn't asking to access anything in there.

Otherwise we have problems if the user doesn't have
an address space setup. Fetching ptrace register is
still valid at such a time, and ptrace does not try
to access the register window area of the regset.

Signed-off-by: David S. Miller <davem@davemloft.net>

+98 -52
+1 -1
arch/sparc/kernel/ptrace.c
··· 325 325 const struct user_regset_view *view; 326 326 int ret; 327 327 328 - view = task_user_regset_view(child); 328 + view = task_user_regset_view(current); 329 329 330 330 switch(request) { 331 331 case PTRACE_GETREGS: {
+97 -51
arch/sparc64/kernel/ptrace.c
··· 114 114 preempt_enable(); 115 115 } 116 116 117 + static int get_from_target(struct task_struct *target, unsigned long uaddr, 118 + void *kbuf, int len) 119 + { 120 + if (target == current) { 121 + if (copy_from_user(kbuf, (void __user *) uaddr, len)) 122 + return -EFAULT; 123 + } else { 124 + int len2 = access_process_vm(target, uaddr, kbuf, len, 0); 125 + if (len2 != len) 126 + return -EFAULT; 127 + } 128 + return 0; 129 + } 130 + 131 + static int set_to_target(struct task_struct *target, unsigned long uaddr, 132 + void *kbuf, int len) 133 + { 134 + if (target == current) { 135 + if (copy_to_user((void __user *) uaddr, kbuf, len)) 136 + return -EFAULT; 137 + } else { 138 + int len2 = access_process_vm(target, uaddr, kbuf, len, 1); 139 + if (len2 != len) 140 + return -EFAULT; 141 + } 142 + return 0; 143 + } 144 + 145 + static int regwindow64_get(struct task_struct *target, 146 + const struct pt_regs *regs, 147 + struct reg_window *wbuf) 148 + { 149 + unsigned long rw_addr = regs->u_regs[UREG_I6]; 150 + 151 + if (test_tsk_thread_flag(current, TIF_32BIT)) { 152 + struct reg_window32 win32; 153 + int i; 154 + 155 + if (get_from_target(target, rw_addr, &win32, sizeof(win32))) 156 + return -EFAULT; 157 + for (i = 0; i < 8; i++) 158 + wbuf->locals[i] = win32.locals[i]; 159 + for (i = 0; i < 8; i++) 160 + wbuf->ins[i] = win32.ins[i]; 161 + } else { 162 + rw_addr += STACK_BIAS; 163 + if (get_from_target(target, rw_addr, wbuf, sizeof(*wbuf))) 164 + return -EFAULT; 165 + } 166 + 167 + return 0; 168 + } 169 + 170 + static int regwindow64_set(struct task_struct *target, 171 + const struct pt_regs *regs, 172 + struct reg_window *wbuf) 173 + { 174 + unsigned long rw_addr = regs->u_regs[UREG_I6]; 175 + 176 + if (test_tsk_thread_flag(current, TIF_32BIT)) { 177 + struct reg_window32 win32; 178 + int i; 179 + 180 + for (i = 0; i < 8; i++) 181 + win32.locals[i] = wbuf->locals[i]; 182 + for (i = 0; i < 8; i++) 183 + win32.ins[i] = wbuf->ins[i]; 184 + 185 + if (set_to_target(target, rw_addr, &win32, sizeof(win32))) 186 + return -EFAULT; 187 + } else { 188 + rw_addr += STACK_BIAS; 189 + if (set_to_target(target, rw_addr, wbuf, sizeof(*wbuf))) 190 + return -EFAULT; 191 + } 192 + 193 + return 0; 194 + } 195 + 117 196 enum sparc_regset { 118 197 REGSET_GENERAL, 119 198 REGSET_FP, ··· 212 133 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 213 134 regs->u_regs, 214 135 0, 16 * sizeof(u64)); 215 - if (!ret) { 216 - unsigned long __user *reg_window = (unsigned long __user *) 217 - (regs->u_regs[UREG_I6] + STACK_BIAS); 218 - unsigned long window[16]; 136 + if (!ret && count && pos < (32 * sizeof(u64))) { 137 + struct reg_window window; 219 138 220 - if (target == current) { 221 - if (copy_from_user(window, reg_window, sizeof(window))) 222 - return -EFAULT; 223 - } else { 224 - if (access_process_vm(target, 225 - (unsigned long) reg_window, 226 - window, 227 - sizeof(window), 0) != 228 - sizeof(window)) 229 - return -EFAULT; 230 - } 231 - 139 + if (regwindow64_get(target, regs, &window)) 140 + return -EFAULT; 232 141 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 233 - window, 142 + &window, 234 143 16 * sizeof(u64), 235 144 32 * sizeof(u64)); 236 145 } ··· 240 173 36 * sizeof(u64)); 241 174 } 242 175 243 - if (!ret) 176 + if (!ret) { 244 177 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, 245 178 36 * sizeof(u64), -1); 246 179 180 + } 247 181 return ret; 248 182 } 249 183 ··· 262 194 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 263 195 regs->u_regs, 264 196 0, 16 * sizeof(u64)); 265 - if (!ret && count > 0) { 266 - unsigned long __user *reg_window = (unsigned long __user *) 267 - (regs->u_regs[UREG_I6] + STACK_BIAS); 268 - unsigned long window[16]; 197 + if (!ret && count && pos < (32 * sizeof(u64))) { 198 + struct reg_window window; 269 199 270 - if (target == current) { 271 - if (copy_from_user(window, reg_window, sizeof(window))) 272 - return -EFAULT; 273 - } else { 274 - if (access_process_vm(target, 275 - (unsigned long) reg_window, 276 - window, 277 - sizeof(window), 0) != 278 - sizeof(window)) 279 - return -EFAULT; 280 - } 200 + if (regwindow64_get(target, regs, &window)) 201 + return -EFAULT; 281 202 282 203 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 283 - window, 204 + &window, 284 205 16 * sizeof(u64), 285 206 32 * sizeof(u64)); 286 - if (!ret) { 287 - if (target == current) { 288 - if (copy_to_user(reg_window, window, 289 - sizeof(window))) 290 - return -EFAULT; 291 - } else { 292 - if (access_process_vm(target, 293 - (unsigned long) 294 - reg_window, 295 - window, 296 - sizeof(window), 1) != 297 - sizeof(window)) 298 - return -EFAULT; 299 - } 300 - } 207 + 208 + if (!ret && 209 + regwindow64_set(target, regs, &window)) 210 + return -EFAULT; 301 211 } 302 212 303 213 if (!ret && count > 0) { ··· 851 805 long compat_arch_ptrace(struct task_struct *child, compat_long_t request, 852 806 compat_ulong_t caddr, compat_ulong_t cdata) 853 807 { 854 - const struct user_regset_view *view = task_user_regset_view(child); 808 + const struct user_regset_view *view = task_user_regset_view(current); 855 809 compat_ulong_t caddr2 = task_pt_regs(current)->u_regs[UREG_I4]; 856 810 struct pt_regs32 __user *pregs; 857 811 struct compat_fps __user *fps; ··· 959 913 960 914 long arch_ptrace(struct task_struct *child, long request, long addr, long data) 961 915 { 962 - const struct user_regset_view *view = task_user_regset_view(child); 916 + const struct user_regset_view *view = task_user_regset_view(current); 963 917 unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4]; 964 918 struct pt_regs __user *pregs; 965 919 struct fps __user *fps;