[glibc] sh: reload r3 after arg evaluation in INTERNAL_SYSCALL [BZ #34167]

Adhemerval Zanella via Glibc-cvs <[email protected]> Mon, 25 May 2026 15:43:46 +0000 (GMT)
Newsgroups gmane.comp.lib.glibc.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=b0f985a21eb55ae9ee3200efabd802aa24744477

commit b0f985a21eb55ae9ee3200efabd802aa24744477
Author: Matt Turner <[email protected]>
Date:   Sat May 23 16:18:27 2026 -0400

    sh: reload r3 after arg evaluation in INTERNAL_SYSCALL [BZ #34167]
    
    r3 is caller-saved. When a function call appears in the args list
    (e.g. INTERNAL_SYSCALL_CALL(tgkill, __getpid(), tid, sig)),
    SUBSTITUTE_ARGS evaluates __getpid() before r3 is reloaded, leaving
    r3=20 (__NR_getpid) instead of __NR_tgkill=270. The trapa then
    dispatches the wrong syscall and the signal is silently dropped.
    
    Fix: declare r3 uninitialised, expand SUBSTITUTE_ARGS (all function
    calls happen here), then assign the syscall number to r3 with no
    intervening calls before the trapa. Applies to both INTERNAL_SYSCALL
    and INTERNAL_SYSCALL_NCS.
    
    signal/tst-raise is a regression test for this bug: raise() calls
    tgkill(__getpid(), tid, sig), which triggers the clobber.
    Reviewed-by: Adhemerval Zanella  <[email protected]>

Diff:
---
 sysdeps/unix/sysv/linux/sh/sysdep.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/sysdeps/unix/sysv/linux/sh/sysdep.h b/sysdeps/unix/sysv/linux/sh/sysdep.h
index d51988e5b0..1562213bf6 100644
--- a/sysdeps/unix/sysv/linux/sh/sysdep.h
+++ b/sysdeps/unix/sysv/linux/sh/sysdep.h
@@ -289,8 +289,9 @@
 #define INTERNAL_SYSCALL(name, nr, args...) \
   ({									      \
     unsigned long int resultvar;					      \
-    register long int r3 asm ("%r3") = SYS_ify (name);			      \
+    register long int r3 asm ("%r3");					      \
     SUBSTITUTE_ARGS_##nr(args);						      \
+    r3 = SYS_ify (name);						      \
 									      \
     asm volatile (SYSCALL_INST_STR##nr SYSCALL_INST_PAD			      \
 		  : "=z" (resultvar)					      \
@@ -303,8 +304,9 @@
 #define INTERNAL_SYSCALL_NCS(name, nr, args...) \
   ({									      \
     unsigned long int resultvar;					      \
-    register long int r3 asm ("%r3") = (name);				      \
+    register long int r3 asm ("%r3");					      \
     SUBSTITUTE_ARGS_##nr(args);						      \
+    r3 = (name);							      \
 									      \
     asm volatile (SYSCALL_INST_STR##nr SYSCALL_INST_PAD			      \
 		  : "=z" (resultvar)					      \