Re: [PATCH v5 0/2] PTRACE_SET_SYSCALL_INFO: add support for seccomp syscall skipping
From: Michal Suchánek
Date: Tue Jul 21 2026 - 06:25:14 EST
On Fri, Jul 10, 2026 at 06:49:11PM +0200, Renzo Davoli wrote:
> Hi Michal,
> I am not an expert of the powerpc architecture.
>
> On Fri, Jul 10, 2026 at 05:38:32PM +0200, Michal Suchánek wrote:
> > On these architectures the syscall number and the syscall return value
> > share the same register.
>
> Reading the file arch/powerpc/include/asm/syscall.h
> the functions
> syscall_get_nr()
> syscall_set_nr()
> read and write regs->gpr[0]
>
> while
> syscall_get_return_value()
> syscall_set_return_value()
> read and write regs->gpr[3] (and one bit in regs->ccr as an error flag).
>
> Am I missing another part of the entry/exit path where the two overlap?
Ok, so it has the other varian of the problem. The syscall return value
overlaps a parameter.
In any case it has this problem:
On and other architectures the syscall number, the syscall arguments,
and the syscall return value are disjunct. These architectures use this
platform-specific to preset teh syscall return value at the very start
of syscall processing, before entry ptrace and seccomp.
On architectures where there is an overlap between the syscall number or
arguments and the return value the return value cannot be preset before
entry ptrace and seccomp because these need the syscall number abd
arguments. On these platforms the tracer may change the registers in one
way or another but there is no guarantee that when the syscall number is
invalid, or -1 as is the value traditionally used to skip a syscall that
there is a meaningful return value set.
The -ENOSYS when handling an invalid syscal is set only after the entry
ptrace and seccomp, overwriting any value that ptrace may have set.
The SECCOMP_SET_MODE_FILTER SECCOMP_RET_ERRNO can accomplish setting
areturn value and skipping the syscall because it changes the return
value of __secure_computing() indicating that the return value has been
set, and the syscall number or parameters in the registers must not be
used anymore, and the syscall skipped.
As ptrace does not have any way to return something it does not have
this option.
There are some workarounds possible. One is setting another flag in
pt_regs to indicate the same as SECCOMP_RET_ERRNO:
https://lore.kernel.org/all/20260714075935.1830145-1-mkchauras@xxxxxxxxx/
another is storing the return value otside of the registers allowing it
to be set in advance:
https://lore.kernel.org/all/20260715133830.2619853-1-svens@xxxxxxxxxxxxx/
but as of now the architectures that have this overlap are not required
to apply one of these workarounds, and not all do AFAIK.
Note there is a piece of bogus code in seccomp that incorrectly skips
syscalls when returning from ptrace:
/* Allow the BPF to provide the event message */
ptrace_event(PTRACE_EVENT_SECCOMP, data);
/*
* The delivery of a fatal signal during event
* notification may silently skip tracer notification,
* which could leave us with a potentially unmodified
* syscall that the tracer would have liked to have
* changed. Since the process is about to die, we just
* force the syscall to be skipped and let the signal
* kill the process and correctly handle any tracer exit
* notifications.
*/
if (fatal_signal_pending(current))
goto skip;
/* Check if the tracer forced the syscall to be skipped. */
this_syscall = syscall_get_nr(current, current_pt_regs());
if (this_syscall < 0)
goto skip;
This does not work correctly when the return value of the syscal is not
preset before calling __secure_computing()
Thanks
Michal