diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/uprobes.c | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index 2efb93f96030..b2bca293fc57 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c | |||
@@ -441,6 +441,9 @@ static int default_post_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs | |||
441 | return -ERESTART; | 441 | return -ERESTART; |
442 | } | 442 | } |
443 | } | 443 | } |
444 | /* popf; tell the caller to not touch TF */ | ||
445 | if (auprobe->fixups & UPROBE_FIX_SETF) | ||
446 | utask->autask.saved_tf = true; | ||
444 | 447 | ||
445 | return 0; | 448 | return 0; |
446 | } | 449 | } |
@@ -757,15 +760,15 @@ bool arch_uprobe_xol_was_trapped(struct task_struct *t) | |||
757 | int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) | 760 | int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) |
758 | { | 761 | { |
759 | struct uprobe_task *utask = current->utask; | 762 | struct uprobe_task *utask = current->utask; |
763 | bool send_sigtrap = utask->autask.saved_tf; | ||
764 | int err = 0; | ||
760 | 765 | ||
761 | WARN_ON_ONCE(current->thread.trap_nr != UPROBE_TRAP_NR); | 766 | WARN_ON_ONCE(current->thread.trap_nr != UPROBE_TRAP_NR); |
762 | current->thread.trap_nr = utask->autask.saved_trap_nr; | 767 | current->thread.trap_nr = utask->autask.saved_trap_nr; |
763 | 768 | ||
764 | if (auprobe->ops->post_xol) { | 769 | if (auprobe->ops->post_xol) { |
765 | int err = auprobe->ops->post_xol(auprobe, regs); | 770 | err = auprobe->ops->post_xol(auprobe, regs); |
766 | if (err) { | 771 | if (err) { |
767 | if (!utask->autask.saved_tf) | ||
768 | regs->flags &= ~X86_EFLAGS_TF; | ||
769 | /* | 772 | /* |
770 | * Restore ->ip for restart or post mortem analysis. | 773 | * Restore ->ip for restart or post mortem analysis. |
771 | * ->post_xol() must not return -ERESTART unless this | 774 | * ->post_xol() must not return -ERESTART unless this |
@@ -773,8 +776,8 @@ int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) | |||
773 | */ | 776 | */ |
774 | regs->ip = utask->vaddr; | 777 | regs->ip = utask->vaddr; |
775 | if (err == -ERESTART) | 778 | if (err == -ERESTART) |
776 | return 0; | 779 | err = 0; |
777 | return err; | 780 | send_sigtrap = false; |
778 | } | 781 | } |
779 | } | 782 | } |
780 | /* | 783 | /* |
@@ -782,12 +785,13 @@ int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) | |||
782 | * so we can get an extra SIGTRAP if we do not clear TF. We need | 785 | * so we can get an extra SIGTRAP if we do not clear TF. We need |
783 | * to examine the opcode to make it right. | 786 | * to examine the opcode to make it right. |
784 | */ | 787 | */ |
785 | if (utask->autask.saved_tf) | 788 | if (send_sigtrap) |
786 | send_sig(SIGTRAP, current, 0); | 789 | send_sig(SIGTRAP, current, 0); |
787 | else if (!(auprobe->fixups & UPROBE_FIX_SETF)) | 790 | |
791 | if (!utask->autask.saved_tf) | ||
788 | regs->flags &= ~X86_EFLAGS_TF; | 792 | regs->flags &= ~X86_EFLAGS_TF; |
789 | 793 | ||
790 | return 0; | 794 | return err; |
791 | } | 795 | } |
792 | 796 | ||
793 | /* callback routine for handling exceptions. */ | 797 | /* callback routine for handling exceptions. */ |