diff options
Diffstat (limited to 'arch/x86/kernel/ptrace.c')
-rw-r--r-- | arch/x86/kernel/ptrace.c | 494 |
1 files changed, 374 insertions, 120 deletions
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 7b058a2dc66a..2e9b55027b7e 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/mm.h> | 12 | #include <linux/mm.h> |
13 | #include <linux/smp.h> | 13 | #include <linux/smp.h> |
14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
15 | #include <linux/slab.h> | ||
15 | #include <linux/ptrace.h> | 16 | #include <linux/ptrace.h> |
16 | #include <linux/regset.h> | 17 | #include <linux/regset.h> |
17 | #include <linux/tracehook.h> | 18 | #include <linux/tracehook.h> |
@@ -22,6 +23,8 @@ | |||
22 | #include <linux/seccomp.h> | 23 | #include <linux/seccomp.h> |
23 | #include <linux/signal.h> | 24 | #include <linux/signal.h> |
24 | #include <linux/workqueue.h> | 25 | #include <linux/workqueue.h> |
26 | #include <linux/perf_event.h> | ||
27 | #include <linux/hw_breakpoint.h> | ||
25 | 28 | ||
26 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
27 | #include <asm/pgtable.h> | 30 | #include <asm/pgtable.h> |
@@ -34,6 +37,7 @@ | |||
34 | #include <asm/prctl.h> | 37 | #include <asm/prctl.h> |
35 | #include <asm/proto.h> | 38 | #include <asm/proto.h> |
36 | #include <asm/ds.h> | 39 | #include <asm/ds.h> |
40 | #include <asm/hw_breakpoint.h> | ||
37 | 41 | ||
38 | #include "tls.h" | 42 | #include "tls.h" |
39 | 43 | ||
@@ -45,10 +49,99 @@ enum x86_regset { | |||
45 | REGSET_FP, | 49 | REGSET_FP, |
46 | REGSET_XFP, | 50 | REGSET_XFP, |
47 | REGSET_IOPERM64 = REGSET_XFP, | 51 | REGSET_IOPERM64 = REGSET_XFP, |
52 | REGSET_XSTATE, | ||
48 | REGSET_TLS, | 53 | REGSET_TLS, |
49 | REGSET_IOPERM32, | 54 | REGSET_IOPERM32, |
50 | }; | 55 | }; |
51 | 56 | ||
57 | struct pt_regs_offset { | ||
58 | const char *name; | ||
59 | int offset; | ||
60 | }; | ||
61 | |||
62 | #define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)} | ||
63 | #define REG_OFFSET_END {.name = NULL, .offset = 0} | ||
64 | |||
65 | static const struct pt_regs_offset regoffset_table[] = { | ||
66 | #ifdef CONFIG_X86_64 | ||
67 | REG_OFFSET_NAME(r15), | ||
68 | REG_OFFSET_NAME(r14), | ||
69 | REG_OFFSET_NAME(r13), | ||
70 | REG_OFFSET_NAME(r12), | ||
71 | REG_OFFSET_NAME(r11), | ||
72 | REG_OFFSET_NAME(r10), | ||
73 | REG_OFFSET_NAME(r9), | ||
74 | REG_OFFSET_NAME(r8), | ||
75 | #endif | ||
76 | REG_OFFSET_NAME(bx), | ||
77 | REG_OFFSET_NAME(cx), | ||
78 | REG_OFFSET_NAME(dx), | ||
79 | REG_OFFSET_NAME(si), | ||
80 | REG_OFFSET_NAME(di), | ||
81 | REG_OFFSET_NAME(bp), | ||
82 | REG_OFFSET_NAME(ax), | ||
83 | #ifdef CONFIG_X86_32 | ||
84 | REG_OFFSET_NAME(ds), | ||
85 | REG_OFFSET_NAME(es), | ||
86 | REG_OFFSET_NAME(fs), | ||
87 | REG_OFFSET_NAME(gs), | ||
88 | #endif | ||
89 | REG_OFFSET_NAME(orig_ax), | ||
90 | REG_OFFSET_NAME(ip), | ||
91 | REG_OFFSET_NAME(cs), | ||
92 | REG_OFFSET_NAME(flags), | ||
93 | REG_OFFSET_NAME(sp), | ||
94 | REG_OFFSET_NAME(ss), | ||
95 | REG_OFFSET_END, | ||
96 | }; | ||
97 | |||
98 | /** | ||
99 | * regs_query_register_offset() - query register offset from its name | ||
100 | * @name: the name of a register | ||
101 | * | ||
102 | * regs_query_register_offset() returns the offset of a register in struct | ||
103 | * pt_regs from its name. If the name is invalid, this returns -EINVAL; | ||
104 | */ | ||
105 | int regs_query_register_offset(const char *name) | ||
106 | { | ||
107 | const struct pt_regs_offset *roff; | ||
108 | for (roff = regoffset_table; roff->name != NULL; roff++) | ||
109 | if (!strcmp(roff->name, name)) | ||
110 | return roff->offset; | ||
111 | return -EINVAL; | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * regs_query_register_name() - query register name from its offset | ||
116 | * @offset: the offset of a register in struct pt_regs. | ||
117 | * | ||
118 | * regs_query_register_name() returns the name of a register from its | ||
119 | * offset in struct pt_regs. If the @offset is invalid, this returns NULL; | ||
120 | */ | ||
121 | const char *regs_query_register_name(unsigned int offset) | ||
122 | { | ||
123 | const struct pt_regs_offset *roff; | ||
124 | for (roff = regoffset_table; roff->name != NULL; roff++) | ||
125 | if (roff->offset == offset) | ||
126 | return roff->name; | ||
127 | return NULL; | ||
128 | } | ||
129 | |||
130 | static const int arg_offs_table[] = { | ||
131 | #ifdef CONFIG_X86_32 | ||
132 | [0] = offsetof(struct pt_regs, ax), | ||
133 | [1] = offsetof(struct pt_regs, dx), | ||
134 | [2] = offsetof(struct pt_regs, cx) | ||
135 | #else /* CONFIG_X86_64 */ | ||
136 | [0] = offsetof(struct pt_regs, di), | ||
137 | [1] = offsetof(struct pt_regs, si), | ||
138 | [2] = offsetof(struct pt_regs, dx), | ||
139 | [3] = offsetof(struct pt_regs, cx), | ||
140 | [4] = offsetof(struct pt_regs, r8), | ||
141 | [5] = offsetof(struct pt_regs, r9) | ||
142 | #endif | ||
143 | }; | ||
144 | |||
52 | /* | 145 | /* |
53 | * does not yet catch signals sent when the child dies. | 146 | * does not yet catch signals sent when the child dies. |
54 | * in exit.c or in signal.c. | 147 | * in exit.c or in signal.c. |
@@ -137,11 +230,6 @@ static int set_segment_reg(struct task_struct *task, | |||
137 | return 0; | 230 | return 0; |
138 | } | 231 | } |
139 | 232 | ||
140 | static unsigned long debugreg_addr_limit(struct task_struct *task) | ||
141 | { | ||
142 | return TASK_SIZE - 3; | ||
143 | } | ||
144 | |||
145 | #else /* CONFIG_X86_64 */ | 233 | #else /* CONFIG_X86_64 */ |
146 | 234 | ||
147 | #define FLAG_MASK (FLAG_MASK_32 | X86_EFLAGS_NT) | 235 | #define FLAG_MASK (FLAG_MASK_32 | X86_EFLAGS_NT) |
@@ -266,15 +354,6 @@ static int set_segment_reg(struct task_struct *task, | |||
266 | return 0; | 354 | return 0; |
267 | } | 355 | } |
268 | 356 | ||
269 | static unsigned long debugreg_addr_limit(struct task_struct *task) | ||
270 | { | ||
271 | #ifdef CONFIG_IA32_EMULATION | ||
272 | if (test_tsk_thread_flag(task, TIF_IA32)) | ||
273 | return IA32_PAGE_OFFSET - 3; | ||
274 | #endif | ||
275 | return TASK_SIZE_MAX - 7; | ||
276 | } | ||
277 | |||
278 | #endif /* CONFIG_X86_32 */ | 357 | #endif /* CONFIG_X86_32 */ |
279 | 358 | ||
280 | static unsigned long get_flags(struct task_struct *task) | 359 | static unsigned long get_flags(struct task_struct *task) |
@@ -408,14 +487,14 @@ static int genregs_get(struct task_struct *target, | |||
408 | { | 487 | { |
409 | if (kbuf) { | 488 | if (kbuf) { |
410 | unsigned long *k = kbuf; | 489 | unsigned long *k = kbuf; |
411 | while (count > 0) { | 490 | while (count >= sizeof(*k)) { |
412 | *k++ = getreg(target, pos); | 491 | *k++ = getreg(target, pos); |
413 | count -= sizeof(*k); | 492 | count -= sizeof(*k); |
414 | pos += sizeof(*k); | 493 | pos += sizeof(*k); |
415 | } | 494 | } |
416 | } else { | 495 | } else { |
417 | unsigned long __user *u = ubuf; | 496 | unsigned long __user *u = ubuf; |
418 | while (count > 0) { | 497 | while (count >= sizeof(*u)) { |
419 | if (__put_user(getreg(target, pos), u++)) | 498 | if (__put_user(getreg(target, pos), u++)) |
420 | return -EFAULT; | 499 | return -EFAULT; |
421 | count -= sizeof(*u); | 500 | count -= sizeof(*u); |
@@ -434,14 +513,14 @@ static int genregs_set(struct task_struct *target, | |||
434 | int ret = 0; | 513 | int ret = 0; |
435 | if (kbuf) { | 514 | if (kbuf) { |
436 | const unsigned long *k = kbuf; | 515 | const unsigned long *k = kbuf; |
437 | while (count > 0 && !ret) { | 516 | while (count >= sizeof(*k) && !ret) { |
438 | ret = putreg(target, pos, *k++); | 517 | ret = putreg(target, pos, *k++); |
439 | count -= sizeof(*k); | 518 | count -= sizeof(*k); |
440 | pos += sizeof(*k); | 519 | pos += sizeof(*k); |
441 | } | 520 | } |
442 | } else { | 521 | } else { |
443 | const unsigned long __user *u = ubuf; | 522 | const unsigned long __user *u = ubuf; |
444 | while (count > 0 && !ret) { | 523 | while (count >= sizeof(*u) && !ret) { |
445 | unsigned long word; | 524 | unsigned long word; |
446 | ret = __get_user(word, u++); | 525 | ret = __get_user(word, u++); |
447 | if (ret) | 526 | if (ret) |
@@ -454,99 +533,240 @@ static int genregs_set(struct task_struct *target, | |||
454 | return ret; | 533 | return ret; |
455 | } | 534 | } |
456 | 535 | ||
536 | static void ptrace_triggered(struct perf_event *bp, int nmi, | ||
537 | struct perf_sample_data *data, | ||
538 | struct pt_regs *regs) | ||
539 | { | ||
540 | int i; | ||
541 | struct thread_struct *thread = &(current->thread); | ||
542 | |||
543 | /* | ||
544 | * Store in the virtual DR6 register the fact that the breakpoint | ||
545 | * was hit so the thread's debugger will see it. | ||
546 | */ | ||
547 | for (i = 0; i < HBP_NUM; i++) { | ||
548 | if (thread->ptrace_bps[i] == bp) | ||
549 | break; | ||
550 | } | ||
551 | |||
552 | thread->debugreg6 |= (DR_TRAP0 << i); | ||
553 | } | ||
554 | |||
457 | /* | 555 | /* |
458 | * This function is trivial and will be inlined by the compiler. | 556 | * Walk through every ptrace breakpoints for this thread and |
459 | * Having it separates the implementation details of debug | 557 | * build the dr7 value on top of their attributes. |
460 | * registers from the interface details of ptrace. | 558 | * |
461 | */ | 559 | */ |
462 | static unsigned long ptrace_get_debugreg(struct task_struct *child, int n) | 560 | static unsigned long ptrace_get_dr7(struct perf_event *bp[]) |
463 | { | 561 | { |
464 | switch (n) { | 562 | int i; |
465 | case 0: return child->thread.debugreg0; | 563 | int dr7 = 0; |
466 | case 1: return child->thread.debugreg1; | 564 | struct arch_hw_breakpoint *info; |
467 | case 2: return child->thread.debugreg2; | 565 | |
468 | case 3: return child->thread.debugreg3; | 566 | for (i = 0; i < HBP_NUM; i++) { |
469 | case 6: return child->thread.debugreg6; | 567 | if (bp[i] && !bp[i]->attr.disabled) { |
470 | case 7: return child->thread.debugreg7; | 568 | info = counter_arch_bp(bp[i]); |
569 | dr7 |= encode_dr7(i, info->len, info->type); | ||
570 | } | ||
471 | } | 571 | } |
472 | return 0; | 572 | |
573 | return dr7; | ||
473 | } | 574 | } |
474 | 575 | ||
475 | static int ptrace_set_debugreg(struct task_struct *child, | 576 | static int |
476 | int n, unsigned long data) | 577 | ptrace_modify_breakpoint(struct perf_event *bp, int len, int type, |
578 | struct task_struct *tsk, int disabled) | ||
477 | { | 579 | { |
478 | int i; | 580 | int err; |
581 | int gen_len, gen_type; | ||
582 | struct perf_event_attr attr; | ||
479 | 583 | ||
480 | if (unlikely(n == 4 || n == 5)) | 584 | /* |
481 | return -EIO; | 585 | * We should have at least an inactive breakpoint at this |
586 | * slot. It means the user is writing dr7 without having | ||
587 | * written the address register first | ||
588 | */ | ||
589 | if (!bp) | ||
590 | return -EINVAL; | ||
482 | 591 | ||
483 | if (n < 4 && unlikely(data >= debugreg_addr_limit(child))) | 592 | err = arch_bp_generic_fields(len, type, &gen_len, &gen_type); |
484 | return -EIO; | 593 | if (err) |
594 | return err; | ||
485 | 595 | ||
486 | switch (n) { | 596 | attr = bp->attr; |
487 | case 0: child->thread.debugreg0 = data; break; | 597 | attr.bp_len = gen_len; |
488 | case 1: child->thread.debugreg1 = data; break; | 598 | attr.bp_type = gen_type; |
489 | case 2: child->thread.debugreg2 = data; break; | 599 | attr.disabled = disabled; |
490 | case 3: child->thread.debugreg3 = data; break; | ||
491 | 600 | ||
492 | case 6: | 601 | return modify_user_hw_breakpoint(bp, &attr); |
493 | if ((data & ~0xffffffffUL) != 0) | 602 | } |
494 | return -EIO; | ||
495 | child->thread.debugreg6 = data; | ||
496 | break; | ||
497 | 603 | ||
498 | case 7: | 604 | /* |
605 | * Handle ptrace writes to debug register 7. | ||
606 | */ | ||
607 | static int ptrace_write_dr7(struct task_struct *tsk, unsigned long data) | ||
608 | { | ||
609 | struct thread_struct *thread = &(tsk->thread); | ||
610 | unsigned long old_dr7; | ||
611 | int i, orig_ret = 0, rc = 0; | ||
612 | int enabled, second_pass = 0; | ||
613 | unsigned len, type; | ||
614 | struct perf_event *bp; | ||
615 | |||
616 | data &= ~DR_CONTROL_RESERVED; | ||
617 | old_dr7 = ptrace_get_dr7(thread->ptrace_bps); | ||
618 | restore: | ||
619 | /* | ||
620 | * Loop through all the hardware breakpoints, making the | ||
621 | * appropriate changes to each. | ||
622 | */ | ||
623 | for (i = 0; i < HBP_NUM; i++) { | ||
624 | enabled = decode_dr7(data, i, &len, &type); | ||
625 | bp = thread->ptrace_bps[i]; | ||
626 | |||
627 | if (!enabled) { | ||
628 | if (bp) { | ||
629 | /* | ||
630 | * Don't unregister the breakpoints right-away, | ||
631 | * unless all register_user_hw_breakpoint() | ||
632 | * requests have succeeded. This prevents | ||
633 | * any window of opportunity for debug | ||
634 | * register grabbing by other users. | ||
635 | */ | ||
636 | if (!second_pass) | ||
637 | continue; | ||
638 | |||
639 | rc = ptrace_modify_breakpoint(bp, len, type, | ||
640 | tsk, 1); | ||
641 | if (rc) | ||
642 | break; | ||
643 | } | ||
644 | continue; | ||
645 | } | ||
646 | |||
647 | rc = ptrace_modify_breakpoint(bp, len, type, tsk, 0); | ||
648 | if (rc) | ||
649 | break; | ||
650 | } | ||
651 | /* | ||
652 | * Make a second pass to free the remaining unused breakpoints | ||
653 | * or to restore the original breakpoints if an error occurred. | ||
654 | */ | ||
655 | if (!second_pass) { | ||
656 | second_pass = 1; | ||
657 | if (rc < 0) { | ||
658 | orig_ret = rc; | ||
659 | data = old_dr7; | ||
660 | } | ||
661 | goto restore; | ||
662 | } | ||
663 | return ((orig_ret < 0) ? orig_ret : rc); | ||
664 | } | ||
665 | |||
666 | /* | ||
667 | * Handle PTRACE_PEEKUSR calls for the debug register area. | ||
668 | */ | ||
669 | static unsigned long ptrace_get_debugreg(struct task_struct *tsk, int n) | ||
670 | { | ||
671 | struct thread_struct *thread = &(tsk->thread); | ||
672 | unsigned long val = 0; | ||
673 | |||
674 | if (n < HBP_NUM) { | ||
675 | struct perf_event *bp; | ||
676 | bp = thread->ptrace_bps[n]; | ||
677 | if (!bp) | ||
678 | return 0; | ||
679 | val = bp->hw.info.address; | ||
680 | } else if (n == 6) { | ||
681 | val = thread->debugreg6; | ||
682 | } else if (n == 7) { | ||
683 | val = thread->ptrace_dr7; | ||
684 | } | ||
685 | return val; | ||
686 | } | ||
687 | |||
688 | static int ptrace_set_breakpoint_addr(struct task_struct *tsk, int nr, | ||
689 | unsigned long addr) | ||
690 | { | ||
691 | struct perf_event *bp; | ||
692 | struct thread_struct *t = &tsk->thread; | ||
693 | struct perf_event_attr attr; | ||
694 | |||
695 | if (!t->ptrace_bps[nr]) { | ||
696 | hw_breakpoint_init(&attr); | ||
499 | /* | 697 | /* |
500 | * Sanity-check data. Take one half-byte at once with | 698 | * Put stub len and type to register (reserve) an inactive but |
501 | * check = (val >> (16 + 4*i)) & 0xf. It contains the | 699 | * correct bp |
502 | * R/Wi and LENi bits; bits 0 and 1 are R/Wi, and bits | ||
503 | * 2 and 3 are LENi. Given a list of invalid values, | ||
504 | * we do mask |= 1 << invalid_value, so that | ||
505 | * (mask >> check) & 1 is a correct test for invalid | ||
506 | * values. | ||
507 | * | ||
508 | * R/Wi contains the type of the breakpoint / | ||
509 | * watchpoint, LENi contains the length of the watched | ||
510 | * data in the watchpoint case. | ||
511 | * | ||
512 | * The invalid values are: | ||
513 | * - LENi == 0x10 (undefined), so mask |= 0x0f00. [32-bit] | ||
514 | * - R/Wi == 0x10 (break on I/O reads or writes), so | ||
515 | * mask |= 0x4444. | ||
516 | * - R/Wi == 0x00 && LENi != 0x00, so we have mask |= | ||
517 | * 0x1110. | ||
518 | * | ||
519 | * Finally, mask = 0x0f00 | 0x4444 | 0x1110 == 0x5f54. | ||
520 | * | ||
521 | * See the Intel Manual "System Programming Guide", | ||
522 | * 15.2.4 | ||
523 | * | ||
524 | * Note that LENi == 0x10 is defined on x86_64 in long | ||
525 | * mode (i.e. even for 32-bit userspace software, but | ||
526 | * 64-bit kernel), so the x86_64 mask value is 0x5454. | ||
527 | * See the AMD manual no. 24593 (AMD64 System Programming) | ||
528 | */ | 700 | */ |
529 | #ifdef CONFIG_X86_32 | 701 | attr.bp_addr = addr; |
530 | #define DR7_MASK 0x5f54 | 702 | attr.bp_len = HW_BREAKPOINT_LEN_1; |
531 | #else | 703 | attr.bp_type = HW_BREAKPOINT_W; |
532 | #define DR7_MASK 0x5554 | 704 | attr.disabled = 1; |
533 | #endif | 705 | |
534 | data &= ~DR_CONTROL_RESERVED; | 706 | bp = register_user_hw_breakpoint(&attr, ptrace_triggered, tsk); |
535 | for (i = 0; i < 4; i++) | 707 | |
536 | if ((DR7_MASK >> ((data >> (16 + 4*i)) & 0xf)) & 1) | 708 | /* |
537 | return -EIO; | 709 | * CHECKME: the previous code returned -EIO if the addr wasn't |
538 | child->thread.debugreg7 = data; | 710 | * a valid task virtual addr. The new one will return -EINVAL in |
539 | if (data) | 711 | * this case. |
540 | set_tsk_thread_flag(child, TIF_DEBUG); | 712 | * -EINVAL may be what we want for in-kernel breakpoints users, |
541 | else | 713 | * but -EIO looks better for ptrace, since we refuse a register |
542 | clear_tsk_thread_flag(child, TIF_DEBUG); | 714 | * writing for the user. And anyway this is the previous |
543 | break; | 715 | * behaviour. |
716 | */ | ||
717 | if (IS_ERR(bp)) | ||
718 | return PTR_ERR(bp); | ||
719 | |||
720 | t->ptrace_bps[nr] = bp; | ||
721 | } else { | ||
722 | int err; | ||
723 | |||
724 | bp = t->ptrace_bps[nr]; | ||
725 | |||
726 | attr = bp->attr; | ||
727 | attr.bp_addr = addr; | ||
728 | err = modify_user_hw_breakpoint(bp, &attr); | ||
729 | if (err) | ||
730 | return err; | ||
544 | } | 731 | } |
545 | 732 | ||
733 | |||
546 | return 0; | 734 | return 0; |
547 | } | 735 | } |
548 | 736 | ||
549 | /* | 737 | /* |
738 | * Handle PTRACE_POKEUSR calls for the debug register area. | ||
739 | */ | ||
740 | int ptrace_set_debugreg(struct task_struct *tsk, int n, unsigned long val) | ||
741 | { | ||
742 | struct thread_struct *thread = &(tsk->thread); | ||
743 | int rc = 0; | ||
744 | |||
745 | /* There are no DR4 or DR5 registers */ | ||
746 | if (n == 4 || n == 5) | ||
747 | return -EIO; | ||
748 | |||
749 | if (n == 6) { | ||
750 | thread->debugreg6 = val; | ||
751 | goto ret_path; | ||
752 | } | ||
753 | if (n < HBP_NUM) { | ||
754 | rc = ptrace_set_breakpoint_addr(tsk, n, val); | ||
755 | if (rc) | ||
756 | return rc; | ||
757 | } | ||
758 | /* All that's left is DR7 */ | ||
759 | if (n == 7) { | ||
760 | rc = ptrace_write_dr7(tsk, val); | ||
761 | if (!rc) | ||
762 | thread->ptrace_dr7 = val; | ||
763 | } | ||
764 | |||
765 | ret_path: | ||
766 | return rc; | ||
767 | } | ||
768 | |||
769 | /* | ||
550 | * These access the current or another (stopped) task's io permission | 770 | * These access the current or another (stopped) task's io permission |
551 | * bitmap for debugging or core dump. | 771 | * bitmap for debugging or core dump. |
552 | */ | 772 | */ |
@@ -1219,14 +1439,14 @@ static int genregs32_get(struct task_struct *target, | |||
1219 | { | 1439 | { |
1220 | if (kbuf) { | 1440 | if (kbuf) { |
1221 | compat_ulong_t *k = kbuf; | 1441 | compat_ulong_t *k = kbuf; |
1222 | while (count > 0) { | 1442 | while (count >= sizeof(*k)) { |
1223 | getreg32(target, pos, k++); | 1443 | getreg32(target, pos, k++); |
1224 | count -= sizeof(*k); | 1444 | count -= sizeof(*k); |
1225 | pos += sizeof(*k); | 1445 | pos += sizeof(*k); |
1226 | } | 1446 | } |
1227 | } else { | 1447 | } else { |
1228 | compat_ulong_t __user *u = ubuf; | 1448 | compat_ulong_t __user *u = ubuf; |
1229 | while (count > 0) { | 1449 | while (count >= sizeof(*u)) { |
1230 | compat_ulong_t word; | 1450 | compat_ulong_t word; |
1231 | getreg32(target, pos, &word); | 1451 | getreg32(target, pos, &word); |
1232 | if (__put_user(word, u++)) | 1452 | if (__put_user(word, u++)) |
@@ -1247,14 +1467,14 @@ static int genregs32_set(struct task_struct *target, | |||
1247 | int ret = 0; | 1467 | int ret = 0; |
1248 | if (kbuf) { | 1468 | if (kbuf) { |
1249 | const compat_ulong_t *k = kbuf; | 1469 | const compat_ulong_t *k = kbuf; |
1250 | while (count > 0 && !ret) { | 1470 | while (count >= sizeof(*k) && !ret) { |
1251 | ret = putreg32(target, pos, *k++); | 1471 | ret = putreg32(target, pos, *k++); |
1252 | count -= sizeof(*k); | 1472 | count -= sizeof(*k); |
1253 | pos += sizeof(*k); | 1473 | pos += sizeof(*k); |
1254 | } | 1474 | } |
1255 | } else { | 1475 | } else { |
1256 | const compat_ulong_t __user *u = ubuf; | 1476 | const compat_ulong_t __user *u = ubuf; |
1257 | while (count > 0 && !ret) { | 1477 | while (count >= sizeof(*u) && !ret) { |
1258 | compat_ulong_t word; | 1478 | compat_ulong_t word; |
1259 | ret = __get_user(word, u++); | 1479 | ret = __get_user(word, u++); |
1260 | if (ret) | 1480 | if (ret) |
@@ -1345,7 +1565,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
1345 | 1565 | ||
1346 | #ifdef CONFIG_X86_64 | 1566 | #ifdef CONFIG_X86_64 |
1347 | 1567 | ||
1348 | static const struct user_regset x86_64_regsets[] = { | 1568 | static struct user_regset x86_64_regsets[] __read_mostly = { |
1349 | [REGSET_GENERAL] = { | 1569 | [REGSET_GENERAL] = { |
1350 | .core_note_type = NT_PRSTATUS, | 1570 | .core_note_type = NT_PRSTATUS, |
1351 | .n = sizeof(struct user_regs_struct) / sizeof(long), | 1571 | .n = sizeof(struct user_regs_struct) / sizeof(long), |
@@ -1358,6 +1578,12 @@ static const struct user_regset x86_64_regsets[] = { | |||
1358 | .size = sizeof(long), .align = sizeof(long), | 1578 | .size = sizeof(long), .align = sizeof(long), |
1359 | .active = xfpregs_active, .get = xfpregs_get, .set = xfpregs_set | 1579 | .active = xfpregs_active, .get = xfpregs_get, .set = xfpregs_set |
1360 | }, | 1580 | }, |
1581 | [REGSET_XSTATE] = { | ||
1582 | .core_note_type = NT_X86_XSTATE, | ||
1583 | .size = sizeof(u64), .align = sizeof(u64), | ||
1584 | .active = xstateregs_active, .get = xstateregs_get, | ||
1585 | .set = xstateregs_set | ||
1586 | }, | ||
1361 | [REGSET_IOPERM64] = { | 1587 | [REGSET_IOPERM64] = { |
1362 | .core_note_type = NT_386_IOPERM, | 1588 | .core_note_type = NT_386_IOPERM, |
1363 | .n = IO_BITMAP_LONGS, | 1589 | .n = IO_BITMAP_LONGS, |
@@ -1383,7 +1609,7 @@ static const struct user_regset_view user_x86_64_view = { | |||
1383 | #endif /* CONFIG_X86_64 */ | 1609 | #endif /* CONFIG_X86_64 */ |
1384 | 1610 | ||
1385 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION | 1611 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION |
1386 | static const struct user_regset x86_32_regsets[] = { | 1612 | static struct user_regset x86_32_regsets[] __read_mostly = { |
1387 | [REGSET_GENERAL] = { | 1613 | [REGSET_GENERAL] = { |
1388 | .core_note_type = NT_PRSTATUS, | 1614 | .core_note_type = NT_PRSTATUS, |
1389 | .n = sizeof(struct user_regs_struct32) / sizeof(u32), | 1615 | .n = sizeof(struct user_regs_struct32) / sizeof(u32), |
@@ -1402,6 +1628,12 @@ static const struct user_regset x86_32_regsets[] = { | |||
1402 | .size = sizeof(u32), .align = sizeof(u32), | 1628 | .size = sizeof(u32), .align = sizeof(u32), |
1403 | .active = xfpregs_active, .get = xfpregs_get, .set = xfpregs_set | 1629 | .active = xfpregs_active, .get = xfpregs_get, .set = xfpregs_set |
1404 | }, | 1630 | }, |
1631 | [REGSET_XSTATE] = { | ||
1632 | .core_note_type = NT_X86_XSTATE, | ||
1633 | .size = sizeof(u64), .align = sizeof(u64), | ||
1634 | .active = xstateregs_active, .get = xstateregs_get, | ||
1635 | .set = xstateregs_set | ||
1636 | }, | ||
1405 | [REGSET_TLS] = { | 1637 | [REGSET_TLS] = { |
1406 | .core_note_type = NT_386_TLS, | 1638 | .core_note_type = NT_386_TLS, |
1407 | .n = GDT_ENTRY_TLS_ENTRIES, .bias = GDT_ENTRY_TLS_MIN, | 1639 | .n = GDT_ENTRY_TLS_ENTRIES, .bias = GDT_ENTRY_TLS_MIN, |
@@ -1424,6 +1656,23 @@ static const struct user_regset_view user_x86_32_view = { | |||
1424 | }; | 1656 | }; |
1425 | #endif | 1657 | #endif |
1426 | 1658 | ||
1659 | /* | ||
1660 | * This represents bytes 464..511 in the memory layout exported through | ||
1661 | * the REGSET_XSTATE interface. | ||
1662 | */ | ||
1663 | u64 xstate_fx_sw_bytes[USER_XSTATE_FX_SW_WORDS]; | ||
1664 | |||
1665 | void update_regset_xstate_info(unsigned int size, u64 xstate_mask) | ||
1666 | { | ||
1667 | #ifdef CONFIG_X86_64 | ||
1668 | x86_64_regsets[REGSET_XSTATE].n = size / sizeof(u64); | ||
1669 | #endif | ||
1670 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION | ||
1671 | x86_32_regsets[REGSET_XSTATE].n = size / sizeof(u64); | ||
1672 | #endif | ||
1673 | xstate_fx_sw_bytes[USER_XSTATE_XCR0_WORD] = xstate_mask; | ||
1674 | } | ||
1675 | |||
1427 | const struct user_regset_view *task_user_regset_view(struct task_struct *task) | 1676 | const struct user_regset_view *task_user_regset_view(struct task_struct *task) |
1428 | { | 1677 | { |
1429 | #ifdef CONFIG_IA32_EMULATION | 1678 | #ifdef CONFIG_IA32_EMULATION |
@@ -1437,21 +1686,33 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) | |||
1437 | #endif | 1686 | #endif |
1438 | } | 1687 | } |
1439 | 1688 | ||
1440 | void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, | 1689 | static void fill_sigtrap_info(struct task_struct *tsk, |
1441 | int error_code, int si_code) | 1690 | struct pt_regs *regs, |
1691 | int error_code, int si_code, | ||
1692 | struct siginfo *info) | ||
1442 | { | 1693 | { |
1443 | struct siginfo info; | ||
1444 | |||
1445 | tsk->thread.trap_no = 1; | 1694 | tsk->thread.trap_no = 1; |
1446 | tsk->thread.error_code = error_code; | 1695 | tsk->thread.error_code = error_code; |
1447 | 1696 | ||
1448 | memset(&info, 0, sizeof(info)); | 1697 | memset(info, 0, sizeof(*info)); |
1449 | info.si_signo = SIGTRAP; | 1698 | info->si_signo = SIGTRAP; |
1450 | info.si_code = si_code; | 1699 | info->si_code = si_code; |
1700 | info->si_addr = user_mode_vm(regs) ? (void __user *)regs->ip : NULL; | ||
1701 | } | ||
1451 | 1702 | ||
1452 | /* User-mode ip? */ | 1703 | void user_single_step_siginfo(struct task_struct *tsk, |
1453 | info.si_addr = user_mode_vm(regs) ? (void __user *) regs->ip : NULL; | 1704 | struct pt_regs *regs, |
1705 | struct siginfo *info) | ||
1706 | { | ||
1707 | fill_sigtrap_info(tsk, regs, 0, TRAP_BRKPT, info); | ||
1708 | } | ||
1454 | 1709 | ||
1710 | void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, | ||
1711 | int error_code, int si_code) | ||
1712 | { | ||
1713 | struct siginfo info; | ||
1714 | |||
1715 | fill_sigtrap_info(tsk, regs, error_code, si_code, &info); | ||
1455 | /* Send us the fake SIGTRAP */ | 1716 | /* Send us the fake SIGTRAP */ |
1456 | force_sig_info(SIGTRAP, &info, tsk); | 1717 | force_sig_info(SIGTRAP, &info, tsk); |
1457 | } | 1718 | } |
@@ -1516,29 +1777,22 @@ asmregparm long syscall_trace_enter(struct pt_regs *regs) | |||
1516 | 1777 | ||
1517 | asmregparm void syscall_trace_leave(struct pt_regs *regs) | 1778 | asmregparm void syscall_trace_leave(struct pt_regs *regs) |
1518 | { | 1779 | { |
1780 | bool step; | ||
1781 | |||
1519 | if (unlikely(current->audit_context)) | 1782 | if (unlikely(current->audit_context)) |
1520 | audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax); | 1783 | audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax); |
1521 | 1784 | ||
1522 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) | 1785 | if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) |
1523 | trace_sys_exit(regs, regs->ax); | 1786 | trace_sys_exit(regs, regs->ax); |
1524 | 1787 | ||
1525 | if (test_thread_flag(TIF_SYSCALL_TRACE)) | ||
1526 | tracehook_report_syscall_exit(regs, 0); | ||
1527 | |||
1528 | /* | 1788 | /* |
1529 | * If TIF_SYSCALL_EMU is set, we only get here because of | 1789 | * If TIF_SYSCALL_EMU is set, we only get here because of |
1530 | * TIF_SINGLESTEP (i.e. this is PTRACE_SYSEMU_SINGLESTEP). | 1790 | * TIF_SINGLESTEP (i.e. this is PTRACE_SYSEMU_SINGLESTEP). |
1531 | * We already reported this syscall instruction in | 1791 | * We already reported this syscall instruction in |
1532 | * syscall_trace_enter(), so don't do any more now. | 1792 | * syscall_trace_enter(). |
1533 | */ | ||
1534 | if (unlikely(test_thread_flag(TIF_SYSCALL_EMU))) | ||
1535 | return; | ||
1536 | |||
1537 | /* | ||
1538 | * If we are single-stepping, synthesize a trap to follow the | ||
1539 | * system call instruction. | ||
1540 | */ | 1793 | */ |
1541 | if (test_thread_flag(TIF_SINGLESTEP) && | 1794 | step = unlikely(test_thread_flag(TIF_SINGLESTEP)) && |
1542 | tracehook_consider_fatal_signal(current, SIGTRAP)) | 1795 | !test_thread_flag(TIF_SYSCALL_EMU); |
1543 | send_sigtrap(current, regs, 0, TRAP_BRKPT); | 1796 | if (step || test_thread_flag(TIF_SYSCALL_TRACE)) |
1797 | tracehook_report_syscall_exit(regs, step); | ||
1544 | } | 1798 | } |