Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2bbda764 authored by Masami Hiramatsu's avatar Masami Hiramatsu Committed by Ingo Molnar
Browse files

kprobes/x86: Do not disable preempt on int3 path



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: default avatarIngo Molnar <mingo@kernel.org>
Signed-off-by: default avatarMasami Hiramatsu <mhiramat@kernel.org>
Acked-by: default avatarThomas 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: default avatarIngo Molnar <mingo@kernel.org>
parent cce188bd
Loading
Loading
Loading
Loading
+5 −6
Original line number Original line Diff line number Diff line
@@ -566,12 +566,11 @@ the same handler) may run concurrently on different CPUs.
Kprobes does not use mutexes or allocate memory except during
Kprobes does not use mutexes or allocate memory except during
registration and unregistration.
registration and unregistration.


Probe handlers are run with preemption disabled.  Depending on the
Probe handlers are run with preemption disabled or interrupt disabled,
architecture and optimization state, handlers may also run with
which depends on the architecture and optimization state.  (e.g.,
interrupts disabled (e.g., kretprobe handlers and optimized kprobe
kretprobe handlers and optimized kprobe handlers run without interrupt
handlers run without interrupt disabled on x86/x86-64).  In any case,
disabled on x86/x86-64).  In any case, your handler should not yield
your handler should not yield the CPU (e.g., by attempting to acquire
the CPU (e.g., by attempting to acquire a semaphore, or waiting I/O).
a semaphore).


Since a return probe is implemented by replacing the return
Since a return probe is implemented by replacing the return
address with the trampoline's address, stack backtraces and calls
address with the trampoline's address, stack backtraces and calls
+4 −14
Original line number Original line Diff line number Diff line
@@ -594,7 +594,6 @@ static void setup_singlestep(struct kprobe *p, struct pt_regs *regs,
		 * stepping.
		 * stepping.
		 */
		 */
		regs->ip = (unsigned long)p->ainsn.insn;
		regs->ip = (unsigned long)p->ainsn.insn;
		preempt_enable_no_resched();
		return;
		return;
	}
	}
#endif
#endif
@@ -667,12 +666,10 @@ int kprobe_int3_handler(struct pt_regs *regs)


	addr = (kprobe_opcode_t *)(regs->ip - sizeof(kprobe_opcode_t));
	addr = (kprobe_opcode_t *)(regs->ip - sizeof(kprobe_opcode_t));
	/*
	/*
	 * We don't want to be preempted for the entire
	 * We don't want to be preempted for the entire duration of kprobe
	 * duration of kprobe processing. We conditionally
	 * processing. Since int3 and debug trap disables irqs and we clear
	 * re-enable preemption at the end of this function,
	 * IF while singlestepping, it must be no preemptible.
	 * and also in reenter_kprobe() and setup_singlestep().
	 */
	 */
	preempt_disable();


	kcb = get_kprobe_ctlblk();
	kcb = get_kprobe_ctlblk();
	p = get_kprobe(addr);
	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))
			if (!p->pre_handler || !p->pre_handler(p, regs))
				setup_singlestep(p, regs, kcb, 0);
				setup_singlestep(p, regs, kcb, 0);
			else {
			else
				reset_current_kprobe();
				reset_current_kprobe();
				preempt_enable_no_resched();
			}
			return 1;
			return 1;
		}
		}
	} else if (*addr != BREAKPOINT_INSTRUCTION) {
	} else if (*addr != BREAKPOINT_INSTRUCTION) {
@@ -711,11 +706,9 @@ int kprobe_int3_handler(struct pt_regs *regs)
		 * the original instruction.
		 * the original instruction.
		 */
		 */
		regs->ip = (unsigned long)addr;
		regs->ip = (unsigned long)addr;
		preempt_enable_no_resched();
		return 1;
		return 1;
	} /* else: not a kprobe fault; let the kernel handle it */
	} /* else: not a kprobe fault; let the kernel handle it */


	preempt_enable_no_resched();
	return 0;
	return 0;
}
}
NOKPROBE_SYMBOL(kprobe_int3_handler);
NOKPROBE_SYMBOL(kprobe_int3_handler);
@@ -966,8 +959,6 @@ int kprobe_debug_handler(struct pt_regs *regs)
	}
	}
	reset_current_kprobe();
	reset_current_kprobe();
out:
out:
	preempt_enable_no_resched();

	/*
	/*
	 * if somebody else is singlestepping across a probe point, flags
	 * if somebody else is singlestepping across a probe point, flags
	 * will have TF set, in which case, continue the remaining processing
	 * 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);
			restore_previous_kprobe(kcb);
		else
		else
			reset_current_kprobe();
			reset_current_kprobe();
		preempt_enable_no_resched();
	} else if (kcb->kprobe_status == KPROBE_HIT_ACTIVE ||
	} else if (kcb->kprobe_status == KPROBE_HIT_ACTIVE ||
		   kcb->kprobe_status == KPROBE_HIT_SSDONE) {
		   kcb->kprobe_status == KPROBE_HIT_SSDONE) {
		/*
		/*
+0 −1
Original line number Original line Diff line number Diff line
@@ -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;
		regs->ip = (unsigned long)op->optinsn.insn + TMPL_END_IDX;
		if (!reenter)
		if (!reenter)
			reset_current_kprobe();
			reset_current_kprobe();
		preempt_enable_no_resched();
		return 1;
		return 1;
	}
	}
	return 0;
	return 0;