| .. | .. |
|---|
| 26 | 26 | #include <linux/audit.h> |
|---|
| 27 | 27 | |
|---|
| 28 | 28 | #include <linux/uaccess.h> |
|---|
| 29 | | -#include <asm/pgtable.h> |
|---|
| 30 | 29 | #include <asm/processor.h> |
|---|
| 31 | 30 | #include <asm/asm-offsets.h> |
|---|
| 32 | 31 | |
|---|
| .. | .. |
|---|
| 88 | 87 | ptrace_disable(task); |
|---|
| 89 | 88 | /* Don't wake up the task, but let the |
|---|
| 90 | 89 | parent know something happened. */ |
|---|
| 91 | | - force_sig_fault(SIGTRAP, TRAP_TRACE, |
|---|
| 92 | | - (void __user *) (task_regs(task)->iaoq[0] & ~3), |
|---|
| 93 | | - task); |
|---|
| 90 | + force_sig_fault_to_task(SIGTRAP, TRAP_TRACE, |
|---|
| 91 | + (void __user *) (task_regs(task)->iaoq[0] & ~3), |
|---|
| 92 | + task); |
|---|
| 94 | 93 | /* notify_parent(task, SIGCHLD); */ |
|---|
| 95 | 94 | return; |
|---|
| 96 | 95 | } |
|---|
| .. | .. |
|---|
| 342 | 341 | } |
|---|
| 343 | 342 | |
|---|
| 344 | 343 | /* Do the secure computing check after ptrace. */ |
|---|
| 345 | | - if (secure_computing(NULL) == -1) |
|---|
| 344 | + if (secure_computing() == -1) |
|---|
| 346 | 345 | return -1; |
|---|
| 347 | 346 | |
|---|
| 348 | 347 | #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS |
|---|
| .. | .. |
|---|
| 392 | 391 | |
|---|
| 393 | 392 | static int fpr_get(struct task_struct *target, |
|---|
| 394 | 393 | const struct user_regset *regset, |
|---|
| 395 | | - unsigned int pos, unsigned int count, |
|---|
| 396 | | - void *kbuf, void __user *ubuf) |
|---|
| 394 | + struct membuf to) |
|---|
| 397 | 395 | { |
|---|
| 398 | 396 | struct pt_regs *regs = task_regs(target); |
|---|
| 399 | | - __u64 *k = kbuf; |
|---|
| 400 | | - __u64 __user *u = ubuf; |
|---|
| 401 | | - __u64 reg; |
|---|
| 402 | 397 | |
|---|
| 403 | | - pos /= sizeof(reg); |
|---|
| 404 | | - count /= sizeof(reg); |
|---|
| 405 | | - |
|---|
| 406 | | - if (kbuf) |
|---|
| 407 | | - for (; count > 0 && pos < ELF_NFPREG; --count) |
|---|
| 408 | | - *k++ = regs->fr[pos++]; |
|---|
| 409 | | - else |
|---|
| 410 | | - for (; count > 0 && pos < ELF_NFPREG; --count) |
|---|
| 411 | | - if (__put_user(regs->fr[pos++], u++)) |
|---|
| 412 | | - return -EFAULT; |
|---|
| 413 | | - |
|---|
| 414 | | - kbuf = k; |
|---|
| 415 | | - ubuf = u; |
|---|
| 416 | | - pos *= sizeof(reg); |
|---|
| 417 | | - count *= sizeof(reg); |
|---|
| 418 | | - return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, |
|---|
| 419 | | - ELF_NFPREG * sizeof(reg), -1); |
|---|
| 398 | + return membuf_write(&to, regs->fr, ELF_NFPREG * sizeof(__u64)); |
|---|
| 420 | 399 | } |
|---|
| 421 | 400 | |
|---|
| 422 | 401 | static int fpr_set(struct task_struct *target, |
|---|
| .. | .. |
|---|
| 528 | 507 | |
|---|
| 529 | 508 | static int gpr_get(struct task_struct *target, |
|---|
| 530 | 509 | const struct user_regset *regset, |
|---|
| 531 | | - unsigned int pos, unsigned int count, |
|---|
| 532 | | - void *kbuf, void __user *ubuf) |
|---|
| 510 | + struct membuf to) |
|---|
| 533 | 511 | { |
|---|
| 534 | 512 | struct pt_regs *regs = task_regs(target); |
|---|
| 535 | | - unsigned long *k = kbuf; |
|---|
| 536 | | - unsigned long __user *u = ubuf; |
|---|
| 537 | | - unsigned long reg; |
|---|
| 513 | + unsigned int pos; |
|---|
| 538 | 514 | |
|---|
| 539 | | - pos /= sizeof(reg); |
|---|
| 540 | | - count /= sizeof(reg); |
|---|
| 541 | | - |
|---|
| 542 | | - if (kbuf) |
|---|
| 543 | | - for (; count > 0 && pos < ELF_NGREG; --count) |
|---|
| 544 | | - *k++ = get_reg(regs, pos++); |
|---|
| 545 | | - else |
|---|
| 546 | | - for (; count > 0 && pos < ELF_NGREG; --count) |
|---|
| 547 | | - if (__put_user(get_reg(regs, pos++), u++)) |
|---|
| 548 | | - return -EFAULT; |
|---|
| 549 | | - kbuf = k; |
|---|
| 550 | | - ubuf = u; |
|---|
| 551 | | - pos *= sizeof(reg); |
|---|
| 552 | | - count *= sizeof(reg); |
|---|
| 553 | | - return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, |
|---|
| 554 | | - ELF_NGREG * sizeof(reg), -1); |
|---|
| 515 | + for (pos = 0; pos < ELF_NGREG; pos++) |
|---|
| 516 | + membuf_store(&to, get_reg(regs, pos)); |
|---|
| 517 | + return 0; |
|---|
| 555 | 518 | } |
|---|
| 556 | 519 | |
|---|
| 557 | 520 | static int gpr_set(struct task_struct *target, |
|---|
| .. | .. |
|---|
| 589 | 552 | [REGSET_GENERAL] = { |
|---|
| 590 | 553 | .core_note_type = NT_PRSTATUS, .n = ELF_NGREG, |
|---|
| 591 | 554 | .size = sizeof(long), .align = sizeof(long), |
|---|
| 592 | | - .get = gpr_get, .set = gpr_set |
|---|
| 555 | + .regset_get = gpr_get, .set = gpr_set |
|---|
| 593 | 556 | }, |
|---|
| 594 | 557 | [REGSET_FP] = { |
|---|
| 595 | 558 | .core_note_type = NT_PRFPREG, .n = ELF_NFPREG, |
|---|
| 596 | 559 | .size = sizeof(__u64), .align = sizeof(__u64), |
|---|
| 597 | | - .get = fpr_get, .set = fpr_set |
|---|
| 560 | + .regset_get = fpr_get, .set = fpr_set |
|---|
| 598 | 561 | } |
|---|
| 599 | 562 | }; |
|---|
| 600 | 563 | |
|---|
| .. | .. |
|---|
| 608 | 571 | |
|---|
| 609 | 572 | static int gpr32_get(struct task_struct *target, |
|---|
| 610 | 573 | const struct user_regset *regset, |
|---|
| 611 | | - unsigned int pos, unsigned int count, |
|---|
| 612 | | - void *kbuf, void __user *ubuf) |
|---|
| 574 | + struct membuf to) |
|---|
| 613 | 575 | { |
|---|
| 614 | 576 | struct pt_regs *regs = task_regs(target); |
|---|
| 615 | | - compat_ulong_t *k = kbuf; |
|---|
| 616 | | - compat_ulong_t __user *u = ubuf; |
|---|
| 617 | | - compat_ulong_t reg; |
|---|
| 577 | + unsigned int pos; |
|---|
| 618 | 578 | |
|---|
| 619 | | - pos /= sizeof(reg); |
|---|
| 620 | | - count /= sizeof(reg); |
|---|
| 579 | + for (pos = 0; pos < ELF_NGREG; pos++) |
|---|
| 580 | + membuf_store(&to, (compat_ulong_t)get_reg(regs, pos)); |
|---|
| 621 | 581 | |
|---|
| 622 | | - if (kbuf) |
|---|
| 623 | | - for (; count > 0 && pos < ELF_NGREG; --count) |
|---|
| 624 | | - *k++ = get_reg(regs, pos++); |
|---|
| 625 | | - else |
|---|
| 626 | | - for (; count > 0 && pos < ELF_NGREG; --count) |
|---|
| 627 | | - if (__put_user((compat_ulong_t) get_reg(regs, pos++), u++)) |
|---|
| 628 | | - return -EFAULT; |
|---|
| 629 | | - |
|---|
| 630 | | - kbuf = k; |
|---|
| 631 | | - ubuf = u; |
|---|
| 632 | | - pos *= sizeof(reg); |
|---|
| 633 | | - count *= sizeof(reg); |
|---|
| 634 | | - return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, |
|---|
| 635 | | - ELF_NGREG * sizeof(reg), -1); |
|---|
| 582 | + return 0; |
|---|
| 636 | 583 | } |
|---|
| 637 | 584 | |
|---|
| 638 | 585 | static int gpr32_set(struct task_struct *target, |
|---|
| .. | .. |
|---|
| 673 | 620 | [REGSET_GENERAL] = { |
|---|
| 674 | 621 | .core_note_type = NT_PRSTATUS, .n = ELF_NGREG, |
|---|
| 675 | 622 | .size = sizeof(compat_long_t), .align = sizeof(compat_long_t), |
|---|
| 676 | | - .get = gpr32_get, .set = gpr32_set |
|---|
| 623 | + .regset_get = gpr32_get, .set = gpr32_set |
|---|
| 677 | 624 | }, |
|---|
| 678 | 625 | [REGSET_FP] = { |
|---|
| 679 | 626 | .core_note_type = NT_PRFPREG, .n = ELF_NFPREG, |
|---|
| 680 | 627 | .size = sizeof(__u64), .align = sizeof(__u64), |
|---|
| 681 | | - .get = fpr_get, .set = fpr_set |
|---|
| 628 | + .regset_get = fpr_get, .set = fpr_set |
|---|
| 682 | 629 | } |
|---|
| 683 | 630 | }; |
|---|
| 684 | 631 | |
|---|
| .. | .. |
|---|
| 798 | 745 | return roff->name; |
|---|
| 799 | 746 | return NULL; |
|---|
| 800 | 747 | } |
|---|
| 748 | + |
|---|
| 749 | +/** |
|---|
| 750 | + * regs_within_kernel_stack() - check the address in the stack |
|---|
| 751 | + * @regs: pt_regs which contains kernel stack pointer. |
|---|
| 752 | + * @addr: address which is checked. |
|---|
| 753 | + * |
|---|
| 754 | + * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). |
|---|
| 755 | + * If @addr is within the kernel stack, it returns true. If not, returns false. |
|---|
| 756 | + */ |
|---|
| 757 | +int regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr) |
|---|
| 758 | +{ |
|---|
| 759 | + return ((addr & ~(THREAD_SIZE - 1)) == |
|---|
| 760 | + (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1))); |
|---|
| 761 | +} |
|---|
| 762 | + |
|---|
| 763 | +/** |
|---|
| 764 | + * regs_get_kernel_stack_nth() - get Nth entry of the stack |
|---|
| 765 | + * @regs: pt_regs which contains kernel stack pointer. |
|---|
| 766 | + * @n: stack entry number. |
|---|
| 767 | + * |
|---|
| 768 | + * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which |
|---|
| 769 | + * is specified by @regs. If the @n th entry is NOT in the kernel stack, |
|---|
| 770 | + * this returns 0. |
|---|
| 771 | + */ |
|---|
| 772 | +unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) |
|---|
| 773 | +{ |
|---|
| 774 | + unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); |
|---|
| 775 | + |
|---|
| 776 | + addr -= n; |
|---|
| 777 | + |
|---|
| 778 | + if (!regs_within_kernel_stack(regs, (unsigned long)addr)) |
|---|
| 779 | + return 0; |
|---|
| 780 | + |
|---|
| 781 | + return *addr; |
|---|
| 782 | +} |
|---|