Calls to x86_64_exception_frame() with combined items set in the flags argument that include EFRAME_VERIFY do not have the EFRAME_VERIFY operation performed. I have some cores where multiple cases of attempting to read a not-present pt_regs end a single PID backtrace with a failure. One instance has the pt_regs read overrunning stacktop because the pt_regs is not present and the level's stack position is closer to stacktop than the size of a pt_regs. That results in a backtrace failing before complete with a "seek error" at the start of page after stacktop: crash> bt 7456 PID: 7456 TASK: ffff933fdb960000 CPU: 0 COMMAND: "sh" #0 [fffffe0000009e58] crash_nmi_callback at ffffffff93260e93 ... #9 [ffffaea5c0003f80] hrtimer_interrupt at ffffffff933313d5 bt: seek error: kernel virtual address: ffffaea5c0004000 type: "pt_regs" crash> The correct backtrace would reach level #12 with no seek error. The condition to perform the EFRAME_VERIFY operation tests if the flags value equals EFRAME_VERIFY, not if the value includes EFRAME_VERIFY. The call to x86_64_exception_frame() in x86_64_print_stack_entry() performed when eframe_check >= 0 supplies a flags value of EFRAME_PRINT | EFRAME_VERIFY. In the bt example above backtrace reaches level #9, 128 bytes from the top of the current stack's pages in an IRQ stack and with a function name ending in "_interrupt". This leads to x86_64_print_stack_entry() setting eframe_check to zero and x86_64_exception_frame() being called with flags EFRAME_PRINT | EFRAME_VERIFY. x86_64_exception_frame() doesn't perform the verify because flags is not just EFRAME_VERIFY. An attempt is made to read 168 bytes (SIZE(pt_regs) - 8 bytes) from a position 128 bytes from the top of the stack. The stack in question is followed by a not-present page and the read fails attempting to read from the page following stacktop. Signed-off-by: David Mair <dmair@xxxxxxxx> --- diff --git a/x86_64.c b/x86_64.c index fc05e8a..cc870e0 100644 --- a/x86_64.c +++ b/x86_64.c @@ -4418,7 +4418,7 @@ x86_64_exception_frame(ulong flags, ulong kvaddr, char *local, long err; char buf[BUFSIZE]; - if (flags == EFRAME_VERIFY) { + if (flags & EFRAME_VERIFY) { if (!accessible(kvaddr) || !accessible(kvaddr + SIZE(pt_regs) - sizeof(long))) return FALSE; -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility