sigaction: put sa_restorer behind sa_mask where the kernel has no such field
The rt_sigaction path in libc/signal/sigaction.c hands the userspace
struct sigaction to the kernel unchanged, so both layouts have to agree.
The common bits/sigaction.h carried sa_restorer unconditionally, but the
kernel only has that field where __ARCH_HAS_SA_RESTORER is set -- either
directly in arch/*/include/asm/signal.h (arm, m68k, powerpc, s390, sparc,
x86, xtensa) or via uapi/asm-generic/signal.h when the arch defines
SA_RESTORER (arc, arm64, ia64, nios2, sh).
On the arches that have neither -- riscv, csky, microblaze, or1k, nds32
and kvx -- sa_mask sat one pointer too far into the struct and the kernel
installed whatever was in sa_restorer as the handler's signal mask.
Measured on riscv32: with sa_restorer = 0x12345678, sigprocmask() inside
the handler reports 0x12305679, the value plus SIGHUP, minus the SIGSTOP
bit the kernel strips.
It usually goes unnoticed because a zeroed struct sigaction yields an
empty mask; the handler then blocks nothing, not even its own signal. It
becomes visible when the junk hits a bit that matters: tst-cancel20,
tst-cancel21, tst-cancelx20 and tst-cancelx21 failed on riscv32 at -O2
because bit 31 was set, which blocked SIGCANCEL while a handler ran and
delayed the cancellation past the read() it was meant to interrupt.
Only the prefix up to sa_mask has to match: rt_sigaction copies sizeof of
its own struct in both directions (kernel/signal.c), so everything behind
the mask is ours. Move the field there instead of dropping it, which is
what docs/sigaction.txt asked for when the layout was unified in
885f507317: "If sa_restorer field is present in libc but is missing in
kernel_sigaction, add it at the bottom in order to not mess up
kernel_sigaction layout". That document was removed in dc7ad9738. mips
does it this way already, and so do glibc and musl.
This changes the userspace ABI on those six arches -- sa_mask moves one
word forward, the struct keeps its size -- so libc and applications have
to be rebuilt together.
Tested with the full uclibc-ng-test suite under qemu, libc and tests
rebuilt together: riscv32 770 passed / 0 failed (was 4 failures), or1k
769/0, microblaze 759/0, csky 477/0. nds32 and kvx are analysis only,
there is no qemu target for either.
Signed-off-by: Ramin Moussavi <lordrasmus@gmail.com>