[SPARC64]: Fix user accesses in regset code.

If target is not current we need to use access_process_vm().

Noticed by Roland McGrath.

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

+115 -21
+115 -21
arch/sparc64/kernel/ptrace.c
··· 138 (regs->u_regs[UREG_I6] + STACK_BIAS); 139 unsigned long window[16]; 140 141 - if (copy_from_user(window, reg_window, sizeof(window))) 142 - return -EFAULT; 143 144 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 145 window, ··· 199 (regs->u_regs[UREG_I6] + STACK_BIAS); 200 unsigned long window[16]; 201 202 - if (copy_from_user(window, reg_window, sizeof(window))) 203 - return -EFAULT; 204 205 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 206 window, 207 16 * sizeof(u64), 208 32 * sizeof(u64)); 209 - if (!ret && 210 - copy_to_user(reg_window, window, sizeof(window))) 211 - return -EFAULT; 212 } 213 214 if (!ret && count > 0) { ··· 442 *k++ = regs->u_regs[pos++]; 443 444 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; 445 - for (; count > 0 && pos < 32; count--) { 446 - if (get_user(*k++, &reg_window[pos++])) 447 - return -EFAULT; 448 } 449 } else { 450 for (; count > 0 && pos < 16; count--) { ··· 466 } 467 468 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; 469 - for (; count > 0 && pos < 32; count--) { 470 - if (get_user(reg, &reg_window[pos++]) || 471 - put_user(reg, u++)) 472 - return -EFAULT; 473 } 474 } 475 while (count > 0) { ··· 549 regs->u_regs[pos++] = *k++; 550 551 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; 552 - for (; count > 0 && pos < 32; count--) { 553 - if (put_user(*k++, &reg_window[pos++])) 554 - return -EFAULT; 555 } 556 } else { 557 for (; count > 0 && pos < 16; count--) { ··· 575 } 576 577 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; 578 - for (; count > 0 && pos < 32; count--) { 579 - if (get_user(reg, u++) || 580 - put_user(reg, &reg_window[pos++])) 581 - return -EFAULT; 582 } 583 } 584 while (count > 0) {
··· 138 (regs->u_regs[UREG_I6] + STACK_BIAS); 139 unsigned long window[16]; 140 141 + if (target == current) { 142 + if (copy_from_user(window, reg_window, sizeof(window))) 143 + return -EFAULT; 144 + } else { 145 + if (access_process_vm(target, 146 + (unsigned long) reg_window, 147 + window, 148 + sizeof(window), 0) != 149 + sizeof(window)) 150 + return -EFAULT; 151 + } 152 153 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, 154 window, ··· 190 (regs->u_regs[UREG_I6] + STACK_BIAS); 191 unsigned long window[16]; 192 193 + if (target == current) { 194 + if (copy_from_user(window, reg_window, sizeof(window))) 195 + return -EFAULT; 196 + } else { 197 + if (access_process_vm(target, 198 + (unsigned long) reg_window, 199 + window, 200 + sizeof(window), 0) != 201 + sizeof(window)) 202 + return -EFAULT; 203 + } 204 205 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 206 window, 207 16 * sizeof(u64), 208 32 * sizeof(u64)); 209 + if (!ret) { 210 + if (target == current) { 211 + if (copy_to_user(reg_window, window, 212 + sizeof(window))) 213 + return -EFAULT; 214 + } else { 215 + if (access_process_vm(target, 216 + (unsigned long) 217 + reg_window, 218 + window, 219 + sizeof(window), 1) != 220 + sizeof(window)) 221 + return -EFAULT; 222 + } 223 + } 224 } 225 226 if (!ret && count > 0) { ··· 412 *k++ = regs->u_regs[pos++]; 413 414 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; 415 + if (target == current) { 416 + for (; count > 0 && pos < 32; count--) { 417 + if (get_user(*k++, &reg_window[pos++])) 418 + return -EFAULT; 419 + } 420 + } else { 421 + for (; count > 0 && pos < 32; count--) { 422 + if (access_process_vm(target, 423 + (unsigned long) 424 + &reg_window[pos], 425 + k, sizeof(*k), 0) 426 + != sizeof(*k)) 427 + return -EFAULT; 428 + k++; 429 + pos++; 430 + } 431 } 432 } else { 433 for (; count > 0 && pos < 16; count--) { ··· 423 } 424 425 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; 426 + if (target == current) { 427 + for (; count > 0 && pos < 32; count--) { 428 + if (get_user(reg, &reg_window[pos++]) || 429 + put_user(reg, u++)) 430 + return -EFAULT; 431 + } 432 + } else { 433 + for (; count > 0 && pos < 32; count--) { 434 + if (access_process_vm(target, 435 + (unsigned long) 436 + &reg_window[pos], 437 + &reg, sizeof(reg), 0) 438 + != sizeof(reg)) 439 + return -EFAULT; 440 + if (access_process_vm(target, 441 + (unsigned long) u, 442 + &reg, sizeof(reg), 1) 443 + != sizeof(reg)) 444 + return -EFAULT; 445 + pos++; 446 + u++; 447 + } 448 } 449 } 450 while (count > 0) { ··· 488 regs->u_regs[pos++] = *k++; 489 490 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; 491 + if (target == current) { 492 + for (; count > 0 && pos < 32; count--) { 493 + if (put_user(*k++, &reg_window[pos++])) 494 + return -EFAULT; 495 + } 496 + } else { 497 + for (; count > 0 && pos < 32; count--) { 498 + if (access_process_vm(target, 499 + (unsigned long) 500 + &reg_window[pos], 501 + (void *) k, 502 + sizeof(*k), 1) 503 + != sizeof(*k)) 504 + return -EFAULT; 505 + k++; 506 + pos++; 507 + } 508 } 509 } else { 510 for (; count > 0 && pos < 16; count--) { ··· 500 } 501 502 reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6]; 503 + if (target == current) { 504 + for (; count > 0 && pos < 32; count--) { 505 + if (get_user(reg, u++) || 506 + put_user(reg, &reg_window[pos++])) 507 + return -EFAULT; 508 + } 509 + } else { 510 + for (; count > 0 && pos < 32; count--) { 511 + if (access_process_vm(target, 512 + (unsigned long) 513 + u, 514 + &reg, sizeof(reg), 0) 515 + != sizeof(reg)) 516 + return -EFAULT; 517 + if (access_process_vm(target, 518 + (unsigned long) 519 + &reg_window[pos], 520 + &reg, sizeof(reg), 1) 521 + != sizeof(reg)) 522 + return -EFAULT; 523 + pos++; 524 + u++; 525 + } 526 } 527 } 528 while (count > 0) {