glibc/sysdeps/unix/sysv/linux/sparc
Adhemerval Zanella 2c1903cbba sparc: Fix restartable syscalls (BZ 32173)
The commit 'sparc: Use Linux kABI for syscall return'
(86c5d2cf0c) did not take into account
a subtle sparc syscall kABI constraint.  For syscalls that might block
indefinitely, on an interrupt (like SIGCONT) the kernel will set the
instruction pointer to just before the syscall:

arch/sparc/kernel/signal_64.c
476 static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
477 {
[...]
525                 if (restart_syscall) {
526                         switch (regs->u_regs[UREG_I0]) {
527                         case ERESTARTNOHAND:
528                         case ERESTARTSYS:
529                         case ERESTARTNOINTR:
530                                 /* replay the system call when we are done */
531                                 regs->u_regs[UREG_I0] = orig_i0;
532                                 regs->tpc -= 4;
533                                 regs->tnpc -= 4;
534                                 pt_regs_clear_syscall(regs);
535                                 fallthrough;
536                         case ERESTART_RESTARTBLOCK:
537                                 regs->u_regs[UREG_G1] = __NR_restart_syscall;
538                                 regs->tpc -= 4;
539                                 regs->tnpc -= 4;
540                                 pt_regs_clear_syscall(regs);
541                         }

However, on a SIGCONT it seems that 'g1' register is being clobbered after the
syscall returns.  Before 86c5d2cf0c, the 'g1' was always placed jus
before the 'ta' instruction which then reloads the syscall number and restarts
the syscall.

On master, where 'g1' might be placed before 'ta':

  $ cat test.c
  #include <unistd.h>

  int main ()
  {
    pause ();
  }
  $ gcc test.c -o test
  $ strace -f ./t
  [...]
  ppoll(NULL, 0, NULL, NULL, 0

On another terminal

  $ kill -STOP 2262828

  $ strace -f ./t
  [...]
  --- SIGSTOP {si_signo=SIGSTOP, si_code=SI_USER, si_pid=2521813, si_uid=8289} ---
  --- stopped by SIGSTOP ---

And then

  $ kill -CONT 2262828

Results in:

  --- SIGCONT {si_signo=SIGCONT, si_code=SI_USER, si_pid=2521813, si_uid=8289} ---
  restart_syscall(<... resuming interrupted ppoll ...>) = -1 EINTR (Interrupted system call)

Where the expected behaviour would be:

  $ strace -f ./t
  [...]
  ppoll(NULL, 0, NULL, NULL, 0)           = ? ERESTARTNOHAND (To be restarted if no handler)
  --- SIGSTOP {si_signo=SIGSTOP, si_code=SI_USER, si_pid=2521813, si_uid=8289} ---
  --- stopped by SIGSTOP ---
  --- SIGCONT {si_signo=SIGCONT, si_code=SI_USER, si_pid=2521813, si_uid=8289} ---
  ppoll(NULL, 0, NULL, NULL, 0

Just moving the 'g1' setting near the syscall asm is not suffice,
the compiler might optimize it away (as I saw on cancellation.c by
trying this fix).  Instead, I have change the inline asm to put the
'g1' setup in ithe asm block.  This would require to change the asm
constraint for INTERNAL_SYSCALL_NCS, since the syscall number is not
constant.

Checked on sparc64-linux-gnu.

Reported-by: René Rebe <rene@exactcode.de>
Tested-by: Sam James <sam@gentoo.org>
Reviewed-by: Sam James <sam@gentoo.org>
2024-10-16 14:54:24 -03:00
..
bits login: structs utmp, utmpx, lastlog _TIME_BITS independence (bug 30701) 2024-04-19 14:38:17 +02:00
sparc32 sparc: Fix restartable syscalls (BZ 32173) 2024-10-16 14:54:24 -03:00
sparc64 sparc: Fix restartable syscalls (BZ 32173) 2024-10-16 14:54:24 -03:00
sys Update copyright dates with scripts/update-copyrights 2024-01-01 10:53:40 -08:00
a.out.h Remove trailing whitespace. 2013-06-05 20:44:03 +00:00
aio_cancel.c Linux: Move aio_cancel, aio_cancel64 into libc 2021-06-25 11:48:46 +02:00
brk_call.h Update copyright dates with scripts/update-copyrights 2024-01-01 10:53:40 -08:00
configure configure: Use autoconf 2.71 2023-07-17 10:08:10 -04:00
configure.ac Move architecture cases out of sysdeps/unix/sysv/linux/configure.ac. 2014-06-24 20:53:03 +00:00
dl-cache.h Update copyright dates with scripts/update-copyrights 2024-01-01 10:53:40 -08:00
errlist-compat-data.h Update copyright dates with scripts/update-copyrights 2024-01-01 10:53:40 -08:00
getrlimit64.c Update copyright dates with scripts/update-copyrights 2024-01-01 10:53:40 -08:00
getshmlba.c Update copyright dates with scripts/update-copyrights 2024-01-01 10:53:40 -08:00
Implies NPTL is no longer an add-on! 2014-07-07 09:29:06 -07:00
kernel-features.h Update copyright dates with scripts/update-copyrights 2024-01-01 10:53:40 -08:00
kernel_sigaction.h m68k: Fix sigaction kernel definition (BZ #23960) 2018-12-18 16:45:10 -02:00
kernel_termios.h Update copyright dates with scripts/update-copyrights 2024-01-01 10:53:40 -08:00
ldd-rewrite.sed Remove left over LD_LIBRARY_VERSION usages 2022-08-04 09:09:48 -03:00
librt-compat.c Update copyright dates with scripts/update-copyrights 2024-01-01 10:53:40 -08:00
Makefile nptl: Remove remaining code from libpthread 2021-05-21 22:35:01 +02:00
profil-counter.h Update copyright dates with scripts/update-copyrights 2024-01-01 10:53:40 -08:00
readelflib.c Update copyright dates with scripts/update-copyrights 2024-01-01 10:53:40 -08:00
rt-sysdep.c * shlib-versions: Use sparc64.*- for CPU patterns. 2006-03-06 01:34:09 +00:00
socket-constants-time64.h Update copyright dates with scripts/update-copyrights 2024-01-01 10:53:40 -08:00
struct_kernel_shmid64_ds.h sysv: linux: Add 64-bit time_t variant for shmctl 2020-07-09 12:05:47 -03:00
sysdep.c * shlib-versions: Use sparc64.*- for CPU patterns. 2006-03-06 01:34:09 +00:00
sysdep.h sparc: Fix restartable syscalls (BZ 32173) 2024-10-16 14:54:24 -03:00
Versions Linux: Move aio_cancel, aio_cancel64 into libc 2021-06-25 11:48:46 +02:00
xstatver.h Remove mknod wrapper functions, move them to symbols 2020-10-09 17:02:06 -03:00