|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v3 4/4] x86: prefer shadow stack for producing call traces
Shadow stacks contain little more than return addresses, and they in
particular allow precise call traces also with FRAME_POINTER=n:
(XEN) Xen call trace:
(XEN) [<ffff82d04032d730>] R extable.c#search_one_extable+0x70/0x73
(XEN) [<ffff82d04032d802>] C search_exception_table+0xc2/0x177
(XEN) [<ffff82d040358378>] C traps.c#extable_fixup.isra.0+0x18/0x6c
(XEN) [<ffff82d040358e3b>] C do_invalid_op+0xab/0x106
(XEN) [<ffff82d040201d98>] C x86_64/entry.S#handle_exception_saved+0x88/0xf4
(XEN) [<ffff82d07fffe044>] E ffff82d07fffe044
(XEN) [<ffff82d040412db0>] C stub_selftest+0xd0/0x168
(XEN) [<ffff82d0403508d6>] C setup.c#init_done+0x116/0x15a
as opposed to this counterpart (earlier during the same boot, before CET
is enabled):
(XEN) Xen call trace:
(XEN) [<ffff82d04032d730>] R extable.c#search_one_extable+0x70/0x73
(XEN) [<ffff82d04032d802>] S search_exception_table+0xc2/0x177
(XEN) [<ffff82d040358378>] S traps.c#extable_fixup.isra.0+0x18/0x6c
(XEN) [<ffff82d040358e3b>] S do_invalid_op+0xab/0x106
(XEN) [<ffff82d040201d98>] S x86_64/entry.S#handle_exception_saved+0x88/0xf4
(XEN) [<ffff82d040412db0>] S stub_selftest+0xd0/0x168
(XEN) [<ffff82d0403d0cc9>] S do_initcalls+0x29/0x38
(XEN) [<ffff82d04041adf2>] S __start_xen+0x1c72/0x2235
(XEN) [<ffff82d040288a57>] S __high_start+0xb7/0xc0
(note the entirely missing entry for the stub itself [1]; sadly there are
no stray entries there).
[1] Arguably we could teach FRAME_POINTER=n traces to recognize stubs as
well. But not FRAME_POINTER=y ones. In fact, what's missing there
isn't the stub itself, but (of course) its immediate caller.
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
---
While the 'E' for exception frames is probably okay, I'm not overly
happy with the 'C' (for CET). I would have preferred 'S' (for shadow),
but we use that character already.
As an alternative to suppressing output for the top level exception
frame, adding the new code ahead of the 'R' output line (and then also
ahead of the stack top read) could be considered.
Quite likely a number of other uses of is_active_kernel_text() also want
amending with in_stub().
---
v3: Correct "link to other shadow stack" check. Don't log a line for the
(impossible) PV case. Add example stack trace to description.
v2: IS_ENABLED() -> #ifdef. Re-base.
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -48,6 +48,7 @@
#include <asm/shared.h>
#include <asm/shstk.h>
#include <asm/smp.h>
+#include <asm/stubs.h>
#include <asm/system.h>
#include <asm/traps.h>
#include <asm/uaccess.h>
@@ -705,6 +706,13 @@ unsigned long get_stack_dump_bottom(unsi
}
}
+#ifdef CONFIG_XEN_SHSTK
+static bool in_stub(unsigned long addr)
+{
+ return !((this_cpu(stubs.addr) ^ addr) >> STUB_BUF_SHIFT);
+}
+#endif
+
#if !defined(CONFIG_FRAME_POINTER)
/*
@@ -797,6 +805,49 @@ static void show_trace(const struct cpu_
!is_active_kernel_text(tos) )
printk(" [<%p>] R %pS\n", _p(regs->rip), _p(regs->rip));
+#ifdef CONFIG_XEN_SHSTK
+ if ( rdssp() != SSP_NO_SHSTK )
+ {
+ const unsigned long *ptr = _p(regs->entry_ssp);
+ unsigned int n;
+
+ for ( n = 0; (unsigned long)ptr & (PAGE_SIZE - sizeof(*ptr)); ++n )
+ {
+ unsigned long val = *ptr;
+
+ if ( is_active_kernel_text(val) || in_stub(val) )
+ {
+ /* Normal return address entry. */
+ printk(" [<%p>] C %pS\n", _p(val), _p(val));
+ ++ptr;
+ }
+ else if ( !((val ^ (unsigned long)ptr) >>
+ (PAGE_SHIFT + STACK_ORDER)) )
+ {
+ if ( val & (sizeof(val) - 1) )
+ {
+ /* Most likely a supervisor token. */
+ break;
+ }
+
+ /*
+ * Ought to be a hypervisor interruption frame. But don't
+ * (re)log the current frame's %rip.
+ */
+ if ( n || ptr[1] != regs->rip )
+ printk(" [<%p>] E %pS\n", _p(ptr[1]), _p(ptr[1]));
+ ptr = _p(val);
+ }
+ else /* Bogus. */
+ break;
+ }
+
+ /* Fall back to legacy stack trace if nothing was logged at all. */
+ if ( n )
+ return;
+ }
+#endif /* CONFIG_XEN_SHSTK */
+
if ( fault )
{
printk(" [Fault on access]\n");
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |