Skip to content

Commit

Permalink
x86: Fixup from the removed INT3 if it is unhandled
Browse files Browse the repository at this point in the history
INT3 is used not only for software breakpoint, but also self modifying
code on x86 in the kernel. For example, jump_label, function tracer etc.
Those may not handle INT3 after removing it but not waiting for
synchronizing CPUs enough. Since such 'ghost' INT3 is not handled by
anyone because they think it has been removed already.
Recheck there is INT3 on the exception address and if not, ignore it.

Note that previously kprobes does the same thing by itself, but that is
not a good location to do that because INT3 is commonly used. Do it at
the common place so that it can handle all 'ghost' INT3.

Reported-by: Matthieu Baerts <matttbe@kernel.org>
Closes: https://lore.kernel.org/all/06cb540e-34ff-4dcd-b936-19d4d14378c9@kernel.org/
Closes: #471
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Fixes: 8e791f7 ("x86/kprobes: Drop removed INT3 handling code")
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
  • Loading branch information
mhiramat authored and matttbe committed Jan 23, 2024
1 parent de0a468 commit af2c212
Showing 1 changed file with 20 additions and 1 deletion.
21 changes: 20 additions & 1 deletion arch/x86/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,25 @@ static bool do_int3(struct pt_regs *regs)
}
NOKPROBE_SYMBOL(do_int3);

static bool fixup_int3(struct pt_regs *regs)
{
unsigned long addr = instruction_pointer(regs) - INT3_INSN_SIZE;

if (*(u8 *)addr != INT3_INSN_OPCODE) {
/*
* The breakpoint instruction was removed right
* after we hit it. Another cpu has removed it
* from this address. In this case, no further
* handling of this interrupt is appropriate.
* Back up over the (now missing) int3 and run
* the original instruction.
*/
instruction_pointer_set(regs, (unsigned long)addr);
return true;
}
return false;
}

static void do_int3_user(struct pt_regs *regs)
{
if (do_int3(regs))
Expand Down Expand Up @@ -758,7 +777,7 @@ DEFINE_IDTENTRY_RAW(exc_int3)
irqentry_state_t irq_state = irqentry_nmi_enter(regs);

instrumentation_begin();
if (!do_int3(regs))
if (!do_int3(regs) && !fixup_int3(regs))
die("int3", regs, 0);
instrumentation_end();
irqentry_nmi_exit(regs, irq_state);
Expand Down

0 comments on commit af2c212

Please sign in to comment.