A not so recent kernel change[1] changed how the trampoline
`__kernel_sigtramp_rt64` is used to call signal handlers.
This was exposed on the test misc/tst-sigcontext-get_pc
Before kernel 5.9, the kernel set LR to the trampoline address and
jumped directly to the signal handler, and at the end the signal
handler, as any other function, would `blr` to the address set. In
other words, the trampoline was executed just at the end of the signal
handler and the only thing it did was call sigreturn. But since
kernel 5.9 the kernel set CTRL to the signal handler and calls to the
trampoline code, the trampoline then `bctrl` to the address in CTRL,
setting the LR to the next instruction in the middle of the
trampoline, when the signal handler returns, the rest of the
trampoline code executes the same code as before.
Here is the full trampoline code as of kernel 5.11.0-rc5 for
reference:
V_FUNCTION_BEGIN(__kernel_sigtramp_rt64)
.Lsigrt_start:
bctrl /* call the handler */
addi r1, r1, __SIGNAL_FRAMESIZE
li r0,__NR_rt_sigreturn
sc
.Lsigrt_end:
V_FUNCTION_END(__kernel_sigtramp_rt64)
This new behavior breaks how `backtrace()` uses to detect the
trampoline frame to correctly reconstruct the stack frame when it is
called from inside a signal handling.
This workaround rely on the fact that the trampoline code is at very
least two (maybe 3?) instructions in size (as it is in the 32 bits
version, only on `li` and `sc`), so it is safe to check the return
address be in the range __kernel_sigtramp_rt64 .. + 4.
[1] subject: powerpc/64/signal: Balance return predictor stack in signal trampoline
commit: 0138ba5783ae0dcc799ad401a1e8ac8333790df9
url: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0138ba5783ae0dcc799ad401a1e8ac8333790df9
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
I used these shell commands:
../glibc/scripts/update-copyrights $PWD/../gnulib/build-aux/update-copyright
(cd ../glibc && git commit -am"[this commit message]")
and then ignored the output, which consisted lines saying "FOO: warning:
copyright statement not found" for each of 6694 files FOO.
I then removed trailing white space from benchtests/bench-pthread-locks.c
and iconvdata/tst-iconv-big5-hkscs-to-2ucs4.c, to work around this
diagnostic from Savannah:
remote: *** pre-commit check failed ...
remote: *** error: lines with trailing whitespace found
remote: error: hook declined to update refs/heads/master
When unwinding through a signal frame the backtrace function on PowerPC
didn't check array bounds when storing the frame address. Fixes commit
d400dcac5e ("PowerPC: fix backtrace to handle signal trampolines").
This patch moves the vDSO setup from libc to loader code, just after
the vDSO link_map setup. For static case the initialization
is moved to _dl_non_dynamic_init instead.
Instead of using the mangled pointer, the vDSO data is set as
attribute_relro (on _rtld_global_ro for shared or _dl_vdso_* for
static). It is read-only even with partial relro.
It fixes BZ#24967 now that the vDSO pointer is setup earlier than
malloc interposition is called.
Also, vDSO calls should not be a problem for static dlopen as
indicated by BZ#20802. The vDSO pointer would be zero-initialized
and the syscall will be issued instead.
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu,
arm-linux-gnueabihf, powerpc64le-linux-gnu, powerpc64-linux-gnu,
powerpc-linux-gnu, s390x-linux-gnu, sparc64-linux-gnu, and
sparcv9-linux-gnu. I also run some tests on mips.
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Linux vDSO initialization code the internal function pointers require a
lot of duplicated boilerplate over different architectures. This patch
aims to simplify not only the code but the required definition to enable
a vDSO symbol.
The changes are:
1. Consolidate all init-first.c on only one implementation and enable
the symbol based on HAVE_*_VSYSCALL existence.
2. Set the HAVE_*_VSYSCALL to the architecture expected names string.
3. Add a new internal implementation, get_vdso_mangle_symbol, which
returns a mangled function pointer.
Currently the clock_gettime, clock_getres, gettimeofday, getcpu, and time
are handled in an arch-independent way, powerpc still uses some
arch-specific vDSO symbol handled in a specific init-first implementation.
Checked on aarch64-linux-gnu, arm-linux-gnueabihf, i386-linux-gnu,
mips64-linux-gnu, powerpc64le-linux-gnu, s390x-linux-gnu,
sparc64-linux-gnu, and x86_64-linux-gnu.
* sysdeps/powerpc/powerpc32/backtrace.c (is_sigtramp_address,
is_sigtramp_address_rt): Use HAVE_SIGTRAMP_{RT}32 instead of SHARED.
* sysdeps/powerpc/powerpc64/backtrace.c (is_sigtramp_address):
Likewise.
* sysdeps/unix/sysv/linux/aarch64/init-first.c: Remove file.
* sysdeps/unix/sysv/linux/aarch64/libc-vdso.h: Likewise.
* sysdeps/unix/sysv/linux/arm/init-first.c: Likewise.
* sysdeps/unix/sysv/linux/arm/libc-vdso.h: Likewise.
* sysdeps/unix/sysv/linux/mips/init-first.c: Likewise.
* sysdeps/unix/sysv/linux/mips/libc-vdso.h: Likewise.
* sysdeps/unix/sysv/linux/i386/init-first.c: Likewise.
* sysdeps/unix/sysv/linux/riscv/init-first.c: Likewise.
* sysdeps/unix/sysv/linux/riscv/libc-vdso.h: Likewise.
* sysdeps/unix/sysv/linux/s390/init-first.c: Likewise.
* sysdeps/unix/sysv/linux/s390/libc-vdso.h: Likewise.
* sysdeps/unix/sysv/linux/sparc/init-first.c: Likewise.
* sysdeps/unix/sysv/linux/sparc/libc-vdso.h: Likewise.
* sysdeps/unix/sysv/linux/x86/libc-vdso.h: Likewise.
* sysdeps/unix/sysv/linux/x86_64/init-first.c: Likewise.
* sysdeps/unix/sysv/linux/aarch64/sysdep.h
(HAVE_CLOCK_GETRES_VSYSCALL, HAVE_CLOCK_GETTIME_VSYSCALL,
HAVE_GETTIMEOFDAY_VSYSCALL): Define value based on kernel exported
name.
* sysdeps/unix/sysv/linux/arm/sysdep.h (HAVE_CLOCK_GETTIME_VSYSCALL,
HAVE_GETTIMEOFDAY_VSYSCALL): Likewise.
* sysdeps/unix/sysv/linux/i386/sysdep.h (HAVE_CLOCK_GETTIME_VSYSCALL,
HAVE_GETTIMEOFDAY_VSYSCALL): Likewise.
* sysdeps/unix/sysv/linux/mips/sysdep.h (HAVE_CLOCK_GETTIME_VSYSCALL,
HAVE_GETTIMEOFDAY_VSYSCALL): Likewise.
* sysdeps/unix/sysv/linux/powerpc/sysdep.h
(HAVE_CLOCK_GETRES_VSYSCALL, HAVE_CLOCK_GETTIME_VSYSCALL,
HAVE_GETCPU_VSYSCALL, HAVE_TIME_VSYSCALL, HAVE_GET_TBFREQ,
HAVE_SIGTRAMP_RT64, HAVE_SIGTRAMP_32, HAVE_SIGTRAMP_RT32i,
HAVE_GETTIMEOFDAY_VSYSCALL): Likewise.
* sysdeps/unix/sysv/linux/riscv/sysdep.h (HAVE_CLOCK_GETRES_VSYSCALL,
HAVE_CLOCK_GETTIME_VSYSCALL, HAVE_GETTIMEOFDAY_VSYSCALL,
HAVE_GETCPU_VSYSCALL): Likewise.
* sysdeps/unix/sysv/linux/s390/sysdep.h (HAVE_CLOCK_GETRES_VSYSCALL,
HAVE_CLOCK_GETTIME_VSYSCALL, HAVE_GETTIMEOFDAY_VSYSCALL,
HAVE_GETCPU_VSYSCALL): Likewise.
* sysdeps/unix/sysv/linux/sparc/sysdep.h (HAVE_CLOCK_GETTIME_VSYSCALL,
HAVE_GETTIMEOFDAY_VSYSCALL): Likewise.
* sysdeps/unix/sysv/linux/x86_64/sysdep.h
(HAVE_CLOCK_GETTIME_VSYSCALL, HAVE_GETTIMEOFDAY_VSYSCALL,
HAVE_GETCPU_VSYSCALL): Likewise.
* sysdeps/unix/sysv/linux/dl-vdso.h (VDSO_NAME, VDSO_HASH): Define to
invalid names if architecture does not define them.
(get_vdso_mangle_symbol): New symbol.
* sysdeps/unix/sysv/linux/init-first.c: New file.
* sysdeps/unix/sysv/linux/libc-vdso.h: Likewise.
* sysdeps/unix/sysv/linux/powerpc/init-first.c (gettimeofday,
clock_gettime, clock_getres, getcpu, time): Remove declaration.
(__libc_vdso_platform_setup_arch): Likewise and use
get_vdso_mangle_symbol to setup vDSO symbols.
(sigtramp_rt64, sigtramp32, sigtramp_rt32, get_tbfreq): Add
attribute_hidden.
* sysdeps/unix/sysv/linux/powerpc/libc-vdso.h: Likewise.
* sysdeps/unix/sysv/linux/sysdep-vdso.h (VDSO_SYMBOL): Remove
definition.
The ucontext_t type has a tag struct ucontext. As with previous such
issues for siginfo_t and stack_t, this tag is not permitted by POSIX
(is not in a reserved namespace), and so namespace conformance means
breaking C++ name mangling for this type.
In this case, the type does need to have some tag rather than just a
typedef name, because it includes a pointer to itself. This patch
uses struct ucontext_t as the new tag, so the type is mangled as
ucontext_t (the POSIX *_t reservation applies in all namespaces, not
just the namespace of ordinary identifiers). Another reserved name
such as struct __ucontext could of course be used.
Because of other namespace issues, this patch does not by itself fix
bug 21457 or allow any XFAILs to be removed.
Tested for x86_64, and with build-many-glibcs.py.
[BZ #21457]
* sysdeps/arm/sys/ucontext.h (struct ucontext): Rename to struct
ucontext_t.
* sysdeps/generic/sys/ucontext.h (struct ucontext): Likewise.
* sysdeps/i386/sys/ucontext.h (struct ucontext): Likewise.
* sysdeps/m68k/sys/ucontext.h (struct ucontext): Likewise.
* sysdeps/mips/sys/ucontext.h (struct ucontext): Likewise.
* sysdeps/unix/sysv/linux/aarch64/sys/ucontext.h (struct
ucontext): Likewise.
* sysdeps/unix/sysv/linux/alpha/sys/ucontext.h (struct ucontext):
Likewise.
* sysdeps/unix/sysv/linux/arm/sys/ucontext.h (struct ucontext):
Likewise.
* sysdeps/unix/sysv/linux/hppa/sys/ucontext.h (struct ucontext):
Likewise.
* sysdeps/unix/sysv/linux/ia64/sys/ucontext.h (struct ucontext):
Likewise.
* sysdeps/unix/sysv/linux/m68k/sys/ucontext.h (struct ucontext):
Likewise.
* sysdeps/unix/sysv/linux/mips/sys/ucontext.h (struct ucontext):
Likewise.
* sysdeps/unix/sysv/linux/nios2/sys/ucontext.h (struct ucontext):
Likewise.
* sysdeps/unix/sysv/linux/powerpc/sys/ucontext.h (struct
ucontext): Likewise.
* sysdeps/unix/sysv/linux/s390/sys/ucontext.h (struct ucontext):
Likewise.
* sysdeps/unix/sysv/linux/sh/sys/ucontext.h (struct ucontext):
Likewise.
* sysdeps/unix/sysv/linux/sparc/sys/ucontext.h (struct ucontext):
Likewise.
* sysdeps/unix/sysv/linux/tile/sys/ucontext.h (struct ucontext):
Likewise.
* sysdeps/unix/sysv/linux/x86/sys/ucontext.h (struct ucontext):
Likewise.
* sysdeps/powerpc/powerpc32/backtrace.c (struct
rt_signal_frame_32): Likewise.
* sysdeps/powerpc/powerpc64/backtrace.c (struct signal_frame_64):
Likewise.
* sysdeps/unix/sysv/linux/aarch64/kernel_rt_sigframe.h (struct
kernel_rt_sigframe): Likewise.
* sysdeps/unix/sysv/linux/aarch64/sigcontextinfo.h (SIGCONTEXT):
Likewise.
* sysdeps/unix/sysv/linux/arm/register-dump.h (register_dump):
Likewise.
* sysdeps/unix/sysv/linux/arm/sigcontextinfo.h (SIGCONTEXT):
Likewise.
* sysdeps/unix/sysv/linux/hppa/profil-counter.h
(__profil_counter): Likewise.
* sysdeps/unix/sysv/linux/microblaze/sigcontextinfo.h
(SIGCONTEXT): Likewise.
* sysdeps/unix/sysv/linux/mips/kernel_rt_sigframe.h (struct
kernel_rt_sigframe): Likewise.
* sysdeps/unix/sysv/linux/nios2/kernel_rt_sigframe.h (struct
kernel_rt_sigframe): Likewise.
* sysdeps/unix/sysv/linux/nios2/sigcontextinfo.h (SIGCONTEXT):
Likewise.
* sysdeps/unix/sysv/linux/sh/makecontext.S (__makecontext):
Likewise.
* sysdeps/unix/sysv/linux/sparc/sparc64/makecontext.c
(__start_context): Likewise.
* sysdeps/unix/sysv/linux/tile/sigcontextinfo.h (SIGCONTEXT):
Likewise.
* sysdeps/unix/sysv/linux/x86_64/register-dump.h (register_dump):
Likewise.
* sysdeps/unix/sysv/linux/x86_64/sigcontextinfo.h (SIGCONTEXT):
Likewise.
Now with read consolidation which uses SYSCALL_CANCEL macro, a frame
pointer is created in the syscall code and this makes the powerpc
backtrace obtain a bogus entry for the signal handling patch.
It is because it does not setup the correct frame pointer register
(r1) based on the saved value from the kernel sigreturn. It was not
failing because the syscall frame pointer register was the same one
for the next frame (the function that actually called the syscall).
This patch fixes it by setup the next stack frame using the saved
one by the kernel sigreturn. It fixes tst-backtrace{5,6} from
the read consolidation patch.
Checked on powerpc-linux-gnu and powerpc64le-linux-gnu.
* sysdeps/powerpc/powerpc32/backtrace.c (is_sigtramp_address): Use
void* for argument type and use VDSO_SYMBOL macro.
(is_sigtramp_address_rt): Likewise.
(__backtrace): Setup expected frame pointer address for signal
handling.
* sysdeps/powerpc/powerpc64/backtrace.c (is_sigtramp_address): Use
void* for argumetn type and use VSDO_SYMBOL macro.
(__backtrace): Setup expected frame pointer address for signal
handling.
This patch fixes backtrace for PPC32 and PPC64 to correctly handle
signal trampolines. The 'debug/tst-backtrace6.c' also check for
SA_SIGINFO handling, where is triggers another vDSO symbols for PPC32.
Ported to PowerPC64 running Linux.
* sysdeps/powerpc/powerpc64/Dist: New file.
* sysdeps/powerpc/powerpc64/Implies: New file.
* sysdeps/powerpc/powerpc64/Makefile: New file.
* sysdeps/powerpc/powerpc64/__longjmp.S: New file.
* sysdeps/powerpc/powerpc64/atomicity.h: New file.
* sysdeps/powerpc/powerpc64/backtrace.c: New file.
* sysdeps/powerpc/powerpc64/bp-asm.h: New file.
* sysdeps/powerpc/powerpc64/bsd-_setjmp.S: New file.
* sysdeps/powerpc/powerpc64/bsd-setjmp.S: New file.
* sysdeps/powerpc/powerpc64/dl-dtprocnum.h: New file.
* sysdeps/powerpc/powerpc64/dl-lookupcfg.h: New file.
* sysdeps/powerpc/powerpc64/dl-machine.c: New file.
* sysdeps/powerpc/powerpc64/dl-machine.h: New file.
* sysdeps/powerpc/powerpc64/memset.S: New file.
* sysdeps/powerpc/powerpc64/ppc-mcount.S: New file.
* sysdeps/powerpc/powerpc64/register-dump.h: New file.
* sysdeps/powerpc/powerpc64/setjmp.S: New file.
* sysdeps/powerpc/powerpc64/stpcpy.S: New file.
* sysdeps/powerpc/powerpc64/strchr.S: New file.
* sysdeps/powerpc/powerpc64/strcmp.S: New file.
* sysdeps/powerpc/powerpc64/strcpy.S: New file.
* sysdeps/powerpc/powerpc64/strlen.S: New file.
* sysdeps/powerpc/powerpc64/elf/bzero.S: New file.
* sysdeps/powerpc/powerpc64/elf/start.S: New file.
* sysdeps/powerpc/powerpc64/fpu/s_copysign.S: New file.
* sysdeps/powerpc/powerpc64/fpu/s_copysignf.S: New file.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/Versions: New File.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/brk.S: New file.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S: New file.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/glob64.c: New file.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S: New file.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list: New file.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h: New file.