When ptrace or seccomp skip a system call on powerpc, the return value
they set is lost or the tracer is affected:

 - syscall_set_return_value() sets TIF_SYSCALL_RET on current, which is
   the tracer when called through PTRACE_SET_SYSCALL_INFO, so the next
   system call of the tracer is silently skipped (1/2);

 - system_call_exception() returns syscall_get_error() for a skipped
   system call, which is 0 for any non-error value, so a success value
   set by a tracer or by a SECCOMP_RET_USER_NOTIF listener is replaced
   with 0 (2/2).

Both problems are in v7.3.  1/2 does not apply as is to v7.3, which
still has the two separate TIF_SYSCALL_RET checks from before commit
66236558dfac ("powerpc/syscall: Avoid atomic test_and_clear_thread_flag
on fast path"); the code it leaves behind is the same, and 2/2 then
applies on top.

Tested on QEMU pseries (TCG, -cpu power9), ppc64le guest config, on
mainline 734bef548a96, with ppc_skip_repro.c [1] (a tracer sets the
return value with PTRACE_SET_SYSCALL_INFO and then makes a system call;
a tracer skips a system call at a PTRACE_EVENT_SECCOMP stop with
PTRACE_POKEUSER, with both "sc" and "scv 0") and with the ptrace and
seccomp selftests:

                                           mainline    + 1/2       + 2/2
  tracer syscall after SET_SYSCALL_INFO    not run     correct     correct
  skipped syscall, success value, sc/scv   returns 0   returns 0   correct
  skipped syscall, error value, sc/scv     correct     correct     correct
  selftests/ptrace set_syscall_info        FAIL        pass        pass
  selftests/seccomp/seccomp_bpf (*)        14 FAIL     14 FAIL     all pass

  failing in mainline and with 1/2 only:
  user_notification_{basic,child_pid_ns,sibling_pid_ns,fault_recv,addfd,
  addfd_opath,addfd_rlimit,addfd_send_interrupted,sync,fifo,
  wait_killable}, TRACE_syscall.seccomp.syscall_faked,
  notification_restart.{killable,both}.after_receive

(*) not counting user_notification_wait_killable_after_reply (100000
    notifications with a 1 ms itimer), which hits the 30 s harness
    timeout under emulation on all three kernels.

Build-tested with W=1: ppc64le guest config, ppc64_defconfig (BE),
pmac32_defconfig.

Changes in v3:
- Split in two patches, one per Fixes: tag: 1/2 removes TIF_SYSCALL_RET
  (suggested by Michal), 2/2 fixes the return value.
- 2/2 returns syscall_get_error() ?: regs->gpr[3] instead of
  regs->gpr[3], so the error path is unchanged (suggested by Mukesh).
- Applies unchanged to current mainline (d89e1d186ec9).
- Link to v2:
  https://lore.kernel.org/lkml/[email protected]/

Changes in v2:
- Rebased on mainline 734bef548a96, after commit 66236558dfac.
- Link to v1:
  https://lore.kernel.org/lkml/[email protected]/

[1] https://lore.kernel.org/lkml/[email protected]/

Renzo Davoli (2):
  powerpc/syscall: Remove TIF_SYSCALL_RET
  powerpc/syscall: Return the preset value of skipped syscalls

 arch/powerpc/include/asm/syscall.h     |  6 ------
 arch/powerpc/include/asm/thread_info.h |  1 -
 arch/powerpc/kernel/syscall.c          | 13 +++++++++----
 3 files changed, 9 insertions(+), 11 deletions(-)


base-commit: d89e1d186ec9271bf78e62771779e9fc03bf0fc3
-- 
2.55.0


Reply via email to