]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
kprobes/x86: Do not disable preempt on int3 path
authorMasami Hiramatsu <mhiramat@kernel.org>
Tue, 19 Jun 2018 16:16:17 +0000 (01:16 +0900)
committerIngo Molnar <mingo@kernel.org>
Thu, 21 Jun 2018 10:33:20 +0000 (12:33 +0200)
Since int3 and debug exception(for singlestep) are run with
IRQ disabled and while running single stepping we drop IF
from regs->flags, that path must not be preemptible. So we
can remove the preempt disable/enable calls from that path.

Suggested-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: linux-arch@vger.kernel.org
Cc: linux-doc@vger.kernel.org
Link: https://lore.kernel.org/lkml/152942497779.15209.2879580696589868291.stgit@devbox
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Documentation/kprobes.txt
arch/x86/kernel/kprobes/core.c
arch/x86/kernel/kprobes/opt.c

index ab2c7307f123bd2cfe13647a14a6a89ae77089b2..cbb545910634366d1554d86e0c8702e323342193 100644 (file)
@@ -566,12 +566,11 @@ the same handler) may run concurrently on different CPUs.
 Kprobes does not use mutexes or allocate memory except during
 registration and unregistration.
 
-Probe handlers are run with preemption disabled.  Depending on the
-architecture and optimization state, handlers may also run with
-interrupts disabled (e.g., kretprobe handlers and optimized kprobe
-handlers run without interrupt disabled on x86/x86-64).  In any case,
-your handler should not yield the CPU (e.g., by attempting to acquire
-a semaphore).
+Probe handlers are run with preemption disabled or interrupt disabled,
+which depends on the architecture and optimization state.  (e.g.,
+kretprobe handlers and optimized kprobe handlers run without interrupt
+disabled on x86/x86-64).  In any case, your handler should not yield
+the CPU (e.g., by attempting to acquire a semaphore, or waiting I/O).
 
 Since a return probe is implemented by replacing the return
 address with the trampoline's address, stack backtraces and calls
index 814e26b7c8a2fcf23ef7eb07930c219b0f9faa44..f7104b256de72bdcec5abba3c671df354d18a94f 100644 (file)
@@ -594,7 +594,6 @@ static void setup_singlestep(struct kprobe *p, struct pt_regs *regs,
                 * stepping.
                 */
                regs->ip = (unsigned long)p->ainsn.insn;
-               preempt_enable_no_resched();
                return;
        }
 #endif
@@ -667,12 +666,10 @@ int kprobe_int3_handler(struct pt_regs *regs)
 
        addr = (kprobe_opcode_t *)(regs->ip - sizeof(kprobe_opcode_t));
        /*
-        * We don't want to be preempted for the entire
-        * duration of kprobe processing. We conditionally
-        * re-enable preemption at the end of this function,
-        * and also in reenter_kprobe() and setup_singlestep().
+        * We don't want to be preempted for the entire duration of kprobe
+        * processing. Since int3 and debug trap disables irqs and we clear
+        * IF while singlestepping, it must be no preemptible.
         */
-       preempt_disable();
 
        kcb = get_kprobe_ctlblk();
        p = get_kprobe(addr);
@@ -694,10 +691,8 @@ int kprobe_int3_handler(struct pt_regs *regs)
                         */
                        if (!p->pre_handler || !p->pre_handler(p, regs))
                                setup_singlestep(p, regs, kcb, 0);
-                       else {
+                       else
                                reset_current_kprobe();
-                               preempt_enable_no_resched();
-                       }
                        return 1;
                }
        } else if (*addr != BREAKPOINT_INSTRUCTION) {
@@ -711,11 +706,9 @@ int kprobe_int3_handler(struct pt_regs *regs)
                 * the original instruction.
                 */
                regs->ip = (unsigned long)addr;
-               preempt_enable_no_resched();
                return 1;
        } /* else: not a kprobe fault; let the kernel handle it */
 
-       preempt_enable_no_resched();
        return 0;
 }
 NOKPROBE_SYMBOL(kprobe_int3_handler);
@@ -966,8 +959,6 @@ int kprobe_debug_handler(struct pt_regs *regs)
        }
        reset_current_kprobe();
 out:
-       preempt_enable_no_resched();
-
        /*
         * if somebody else is singlestepping across a probe point, flags
         * will have TF set, in which case, continue the remaining processing
@@ -1014,7 +1005,6 @@ int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
                        restore_previous_kprobe(kcb);
                else
                        reset_current_kprobe();
-               preempt_enable_no_resched();
        } else if (kcb->kprobe_status == KPROBE_HIT_ACTIVE ||
                   kcb->kprobe_status == KPROBE_HIT_SSDONE) {
                /*
index 203d398802a3cb4d5d8a0c9183c5f5de60b7f5d6..eaf02f2e73005731e28dc22bd5d91d10fd26d2aa 100644 (file)
@@ -491,7 +491,6 @@ int setup_detour_execution(struct kprobe *p, struct pt_regs *regs, int reenter)
                regs->ip = (unsigned long)op->optinsn.insn + TMPL_END_IDX;
                if (!reenter)
                        reset_current_kprobe();
-               preempt_enable_no_resched();
                return 1;
        }
        return 0;