diff options
| -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. */ |
