[rfc] new generic ptrace api for setting syscall info

Renzo Davoli renzo at cs.unibo.it
Tue Nov 2 13:50:58 UTC 2021


I am sorry for the delay. Life synch problems.
> at a high level, i like where this is going.  i think we should break them up as
> (1) that's how you get things reviewed & accepted faster,
> (2) certain pieces need more help from arches than others,
> (3) they look easy to break up & make logically independent,
> (4) i selfishly care more for some aspects than others :),
> (5) i want to avoid an "all or nothing" type of functionality merge.
Agree, entirely, including (4) for my interests.
> 
> the functionality that matters to me with PTRACE_SET_SYSCALL_INFO:
> * set syscall nr (e.g. skip it) 
> * change syscall arguments
> * set syscall return value
> * set syscall error value
> imo, without these, PTRACE_SET_SYSCALL_INFO is not super useful, and seems like
> it'd be hard to partially implement any of these.  especially as syscall_set_nr
> is the worst performer, and is a bit of the foundation here.  a survey of the
> current asm/syscall.h tree:
> * syscall_set_nr
>   (1/22) only csky has this atm
> * syscall_set_arguments
>   (14/22) missing alpha arc h8300 hexagon m68k mips parisc sh
> * syscall_set_return_value
>   (17/22) missing alpha h8300 hexagon m68k sh
PTRACE_GET_SYSCALL_INFO is provided under the flag: CONFIG_HAVE_ARCH_TRACEHOOK i.e.:
arc arm arm64 csky hexagon ia64 mips nds32 nios2 openrisc parisc powerpc riscv s390 sh sparc x86 xtensa

It is reasonable to design PTRACE_SET_SYSCALL_INFO for the same set of archs.
so:
* syscall_set_nr
  (1/18) only csky has this atm
* syscall_set_arguments
  (12/18) missing arc hexagon mips parisc sh
* syscall_set_return_value
  (16/18) missing hexagon sh
> 
> you've also thrown in these:
> * change IP
> * change SP
> i'm guessing you've done that simply to mirror the API?  i would argue that
> these are significantly less interesting (i won't say never as i could think
> of a few).  
Not entirely. In vuos we set the IP to repeat the system call.
For what concerns the change of SP, I am with you: it is just to preserve the simmetry.
In similar situations, it has happened to me many times that I discover a suitable usage later.
> so what if we start off with a PTRACE_SET_SYSCALL_INFO that does
> not support changing these values.  i'm not sure we could get away with using
> a sentinel value here (e.g. require they be set to -1 else we EINVAL), so
> maybe requiring them to be the same as would be OK ?  it's reasonable imo to
> assume the tracer first called PTRACE_GET_SYSCALL_INFO before modifying, so
> they'll have easy access to the current values.  if they don't match, we will
> return EINVAL.  this will allow merging of the API without also implementing
> the corresponding APIs in asm/ptrace.h.
> * instruction_pointer_set
>   (11/22) missing alpha arc h8300 hexagon ia64 m68k microblaze nds32 nios2 openrisc xtensa
(12/18) missing arc hexagon ia64 nds32 nios2 xtensa
> * stack_pointer_set
>   (4/22) only mips riscv sh x86
(4/18) only mips riscv sh x86
> 
> i guess we're just ignoring arch entirely.  not unreasonable considering
> changing execution architecture state is ... not useful, if even possible
> for many architectures.  
Absolutely
> so should we enforce it be 0 and return an EINVAL
> if it isn't ?  otherwise it turns into a field we can never use for anything
> else in the set path.  afaict, there is no AUDIT_xxx value that is zero atm,
> and never will be since it encodes the ELF machine (EM_*), and EM_NONE==0.
I envision the default usage of PTRACE_SET_SYSCALL_INFO to be:
  ptrace(PTRACE_GET_SYSCALL_INFO, tracee_pid, sizeof(info), &info)
	/* modify something in info */
  ptrace(PTRACE_SET_SYSCALL_INFO, tracee_pid, sizeof(info), &info)
so I propose to ignore the value of arch, otherwise programmers need to remember to 
set the field to zero prior to call PTRACE_SET_SYSCALL_INFO.

Looking at the future and aiming at the goal to have the entire PTRACE_SET_SYSCALL_INFO
implementend although through some steps, we need to provide a way to inform
the programmers about which features have been implemented (change IP/change SP), so that
those features can be used if present or a workaround applied.

I propose to check if IP/SP have been modified on archs where change IP/SP
have not implemented yet and return an EINVAL in case.
The same approach could be applied to an attempt to modify arch.
> 
> next you have seccomp improvements.  these are interesting, but i think
> important to not block PTRACE_SET_SYSCALL_INFO on since seccomp support is
> a bit spotty already across arches.  and it seems like it calls for a bit
> of API bikeshedding.  while your reuse of the existing INFO ops doesn't
> feel too terrible since there are direct parallels between them, adding a
> new op that only shows up on set feels a little awkward.  it'd be nice if
> we could stick to PTRACE_SYSCALL_INFO_SECCOMP somehow.  with the fields we
> have now, we have the syscall number, args, and return value.  so can't we
> do what you want ?  there's no access to setting an error distinct from a
> return value ... but oes seccomp allow that either ?  if not, extending
> that limitation from seccomp to ptrace-seccomp doesn't feel bad.

One of the features we agree to support in the first patch to propose is:
> * set syscall nr (e.g. skip it)
Skip the system call also means to provide a suitable return value/errno
to be returned to the caller.
So in this case we need to encode for PTRACE_SET_SYSCALL_INFO in some way:
 * the info that the syscall must be skipped 
 * rval/is_error.
Either
we provide a specific tag (as I propose) PTRACE_SYSCALL_INFO_SECCOMP_SKIP
and we use the "exit" branch of the union in  struct ptrace_syscall_info
to provide rval/errno,
or
we set seccomp.nr to -1 and then we need to "recycle" the fields in the seccomp
branch (nr, args[6], and ret_data).
seccomp.ret_data is not suitable for the syscall return value as it is _u32, on 64 bits archs
one may need to return 64 bit values. Modify the struct ptrace_syscall_info is
out of scope, it would break the compatibility with the PTRACE_GET_SYSCALL current usage.
So we should use two of the args for rval/errno.

I am quite supportive for my proposal, When a user wants to skip the system call,
they use a specific tag and set the "exit" fields, as it is an exit, not an entry.
There is no syscall to enter if it has to be skipped.

> 
> in terms of contributing, i think you can see where my interests align,
> and so i'd be happy to chip in for those parts.  but for others, i'll
> just wish you the best of luck :).

I think we have a quite good alignemnt. Luck is always needed anyway.

ciao
	renzo


More information about the Strace-devel mailing list