• Will Deacon's avatar
    arm64: vdso: Disable dwarf unwinding through the sigreturn trampoline · 87676cfc
    Will Deacon authored
    Commit 7e9f5e66 ("arm64: vdso: Add --eh-frame-hdr to ldflags") results
    in a .eh_frame_hdr section for the vDSO, which in turn causes the libgcc
    unwinder to unwind out of signal handlers using the .eh_frame information
    populated by our .cfi directives. In conjunction with a4eb355a
    ("arm64: vdso: Fix CFI directives in sigreturn trampoline"), this has
    been shown to cause segmentation faults originating from within the
    unwinder during thread cancellation:
    
     | Thread 14 "virtio-net-rx" received signal SIGSEGV, Segmentation fault.
     | 0x0000000000435e24 in uw_frame_state_for ()
     | (gdb) bt
     | #0  0x0000000000435e24 in uw_frame_state_for ()
     | #1  0x0000000000436e88 in _Unwind_ForcedUnwind_Phase2 ()
     | #2  0x00000000004374d8 in _Unwind_ForcedUnwind ()
     | #3  0x0000000000428400 in __pthread_unwind (buf=<optimized out>) at unwind.c:121
     | #4  0x0000000000429808 in __do_cancel () at ./pthreadP.h:304
     | #5  sigcancel_handler (sig=32, si=0xffff33c743f0, ctx=<optimized out>) at nptl-init.c:200
     | #6  sigcancel_handler (sig=<optimized out>, si=0xffff33c743f0, ctx=<optimized out>) at nptl-init.c:165
     | #7  <signal handler called>
     | #8  futex_wait_cancelable (private=0, expected=0, futex_word=0x3890b708) at ../sysdeps/unix/sysv/linux/futex-internal.h:88
    
    After considerable bashing of heads, it appears that our CFI directives
    for unwinding out of the sigreturn trampoline are only processed by libgcc
    when both a .eh_frame_hdr section is present *and* the mysterious NOP is
    covered by an entry in .eh_frame. With both of these now in place, it has
    highlighted that our CFI directives are not comprehensive enough to
    restore the stack pointer of the interrupted context. This results in libgcc
    falling back to an arm64-specific unwinder after computing a bogus PC value
    from the unwind tables. The unwinder promptly dereferences this bogus address
    in an attempt to see if the pointed-to instruction sequence looks like
    the sigreturn trampoline.
    
    Restore the old unwind behaviour, which relied solely on heuristics in
    the unwinder, by removing the .eh_frame_hdr section from the vDSO and
    commenting out the insufficient CFI directives for now. Add comments to
    explain the current, miserable state of affairs.
    
    Cc: Tamas Zsoldos <tamas.zsoldos@arm.com>
    Cc: Szabolcs Nagy <szabolcs.nagy@arm.com>
    Cc: Catalin Marinas <catalin.marinas@arm.com>
    Cc: Daniel Kiss <daniel.kiss@arm.com>
    Acked-by: default avatarDave Martin <Dave.Martin@arm.com>
    Reviewed-by: default avatarVincenzo Frascino <vincenzo.frascino@arm.com>
    Reviewed-by: default avatarArd Biesheuvel <ardb@kernel.org>
    Reported-by: default avatarArd Biesheuvel <ardb@kernel.org>
    Signed-off-by: default avatarWill Deacon <will@kernel.org>
    87676cfc
sigreturn.S 2.97 KB