microblaze: reserve the ABI argument-home area in the signal frame

The MicroBlaze procedure call standard reserves [r1+0] for the return
address and lets a callee store its incoming register arguments r5..r10
into the caller-provided home slots at [r1+4]..[r1+24].  When the kernel
enters a signal handler it sets r1 to point at struct rt_sigframe, whose
leading member is the siginfo prepared for the handler.  A handler that
homes its arguments - which an unoptimised (-O0) build always does -
therefore overwrites the first 24 bytes of that siginfo, so an
SA_SIGINFO handler reads corrupted values.  The stores stay within
siginfo (128 bytes) and do not reach the ucontext behind it.

Reserve the home area by making a seven-word gap -- the return-address
slot plus the six argument slots, 28 bytes -- the first member of struct
rt_sigframe, so the handler's argument stores land in scratch space
instead of clobbering siginfo.

Tested on qemu-system-microblazeel (petalogix-s3adsp1800) with the
uClibc-ng NPTL test suite: tst-timer4, tst-timer5, tst-mqueue5 and
tst-signal6 pass; before this change they failed because the handler
clobbered the signal frame.

Fixes: 2148daa9c4 ("microblaze_v8: Signal support")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-5
Signed-off-by: Ramin Moussavi <ramin.moussavi@yacoub.de>
Tested-by: Waldemar Brodkorb <wbx@openadk.org>
Link: https://patch.msgid.link/20260821151809.1233057-3-ramin.moussavi@yacoub.de
Signed-off-by: Michal Simek <michal.simek@amd.com>
This commit is contained in:
Ramin Moussavi 2026-08-21 17:18:06 +02:00 committed by Michal Simek
parent 730e01d932
commit c5947d28c2

View File

@ -49,6 +49,14 @@ struct sigframe {
};
struct rt_sigframe {
/*
* Home area for the handler's register arguments: the MicroBlaze
* ABI reserves [r1+0] for the return address and lets the callee
* store r5..r10 at [r1+4]..[r1+24], and r1 points at this frame
* when the handler is entered. Without the gap those stores
* corrupt frame->info.
*/
unsigned long abi_gap[7];
struct siginfo info;
struct ucontext uc;
unsigned long tramp[2]; /* signal trampoline */