diff options
author | Oleg Nesterov <oleg@redhat.com> | 2014-04-21 14:39:56 -0400 |
---|---|---|
committer | Oleg Nesterov <oleg@redhat.com> | 2014-04-30 13:10:37 -0400 |
commit | 220ef8dc9a7a63fe202aacd3fc61e5104f6dd98c (patch) | |
tree | 1176022547d4fd10b216612e0b73440570520015 /arch/x86 | |
parent | 6ded5f3848bfd3227ee208aa38f8bf8d7209d4e3 (diff) |
uprobes/x86: Move UPROBE_FIX_SETF logic from arch_uprobe_post_xol() to default_post_xol_op()
UPROBE_FIX_SETF is only needed to handle "popf" correctly but it is
processed by the generic arch_uprobe_post_xol() code. This doesn't
allows us to make ->fixups private for default_xol_ops.
1 Change default_post_xol_op(UPROBE_FIX_SETF) to set ->saved_tf = T.
"popf" always reads the flags from stack, it doesn't matter if TF
was set or not before single-step. Ignoring the naming, this is
even more logical, "saved_tf" means "owned by application" and we
do not own this flag after "popf".
2. Change arch_uprobe_post_xol() to save ->saved_tf into the local
"bool send_sigtrap" before ->post_xol().
3. Change arch_uprobe_post_xol() to ignore UPROBE_FIX_SETF and just
check ->saved_tf after ->post_xol().
With this patch ->fixups and ->rip_rela_target_address are only used
by default_xol_ops hooks, we are ready to remove them from the common
part of arch_uprobe.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Reviewed-by: Jim Keniston <jkenisto@us.ibm.com>
Diffstat (limited to 'arch/x86')
-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. */ |