[PATCH 1/6] arm64: vdso: Disable dwarf unwinding through the sigreturn trampoline

Mark Rutland mark.rutland at arm.com
Tue Jun 23 05:47:14 EDT 2020


On Tue, Jun 23, 2020 at 09:54:31AM +0100, Will Deacon wrote:
> Commit 7e9f5e6629f6 ("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 a4eb355a3fda
> ("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.

> diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
> index 556d424c6f52..4a2e06181d80 100644
> --- a/arch/arm64/kernel/vdso/Makefile
> +++ b/arch/arm64/kernel/vdso/Makefile
> @@ -24,7 +24,7 @@ btildflags-$(CONFIG_ARM64_BTI_KERNEL) += -z force-bti
>  # routines, as x86 does (see 6f121e548f83 ("x86, vdso: Reimplement vdso.so
>  # preparation in build-time C")).
>  ldflags-y := -shared -nostdlib -soname=linux-vdso.so.1 --hash-style=sysv \
> -		-Bsymbolic --eh-frame-hdr --build-id -n $(btildflags-y) -T
> +		-Bsymbolic --build-id -n $(btildflags-y) -T

I reckon we should be explicit with --no-eh-frame-hdr, so that we're not
at the mercy of toolchain defaults.

Mark.



More information about the linux-arm-kernel mailing list