Page MenuHomeFreeBSD

kinst: Add per-CPU interrupt trampolines
ClosedPublic

Authored by markj on Dec 7 2022, 12:04 AM.
Tags
None
Referenced Files
Unknown Object (File)
Dec 26 2023, 10:11 AM
Unknown Object (File)
Dec 23 2023, 1:31 AM
Unknown Object (File)
Dec 10 2023, 12:34 PM
Unknown Object (File)
Oct 12 2023, 12:59 AM
Unknown Object (File)
Sep 30 2023, 7:15 PM
Unknown Object (File)
Sep 6 2023, 1:15 AM
Unknown Object (File)
Aug 14 2023, 5:09 PM
Unknown Object (File)
Aug 14 2023, 6:12 AM

Details

Summary

In the common case, kinst emulates a traced instruction by copying it to
a trampoline, where it is followed by a jump back to the original code,
and pointing the interrupted thread's %rip at the trampoline. In
particular, the trampoline is executed with the same CPU context as the
original instruction, so if interrupts are enabled immediately before
the probe fires, they are enabled when the trampoline is executed.

It can happen that an interrupt is raised while a thread is executing a
kinst trampoline. In that case, it is possible that the interrupt
handler will trigger a kinst probe, so we must ensure that the thread
does not recurse and overwrite its trampoline before it is finished
executing the original contents, otherwise an attempt to trace code
called from interrupt handlers can crash the kernel.

To that end, add a per-CPU trampoline, used iff the probe fired with
interrupts disabled. Note that this is not quite complete since it does
not handle the possibility of kinst probes firing while executing an NMI
handler.

Also ensure that we do not trace instructions which set IF, since in
that case it is not clear which trampoline (the per-thread trampoline or
the per-CPU trampoline) we should use, and since such instructions are
rare.

Reported by: Domagoj Stolfa

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

markj requested review of this revision.Dec 7 2022, 12:04 AM

Tested it on my end and it works. Code also looks good to me. Thanks!

@markj: Would it make sense to add a new test which covers this scenario? Given that the issue manifests in a bit of an annoying way, perhaps this test case would catch it early in the future?

This revision is now accepted and ready to land.Dec 7 2022, 9:36 PM

Tested it on my end and it works. Code also looks good to me. Thanks!

Thank you.

@markj: Would it make sense to add a new test which covers this scenario? Given that the issue manifests in a bit of an annoying way, perhaps this test case would catch it early in the future?

I think the existing test can be extended. It's sufficient to trace a function that disables interrupts somewhere; tracing kinst::_thread_lock: or kinst::spinlock_enter: will crash the kernel without this patch.

I'll update the test when I commit this patch.

This revision was automatically updated to reflect the committed changes.