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

Will Deacon will at kernel.org
Tue Jun 23 06:10:29 EDT 2020


On Tue, Jun 23, 2020 at 10:47:14AM +0100, Mark Rutland wrote:
> 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.

Yeah, I'll do that for consistency, although having the .eh_frame_hdr
section won't cause problems without the CFI directives. There are also many
other horrible options like -fexceptions and -funwind-tables that we happily
ignore...

Will



More information about the linux-arm-kernel mailing list