Date: Sun, 15 Jun 2025 11:18:05 +0300 From: Konstantin Belousov <kostikbel@gmail.com> To: Mark Johnston <markj@freebsd.org> Cc: src-committers@freebsd.org, dev-commits-src-all@freebsd.org, dev-commits-src-main@freebsd.org Subject: Re: git: 48a656c588f9 - main - linux: Fix usage of ptrace(PT_GET_SC_ARGS) Message-ID: <aE6BvayWrz9dtLc7@kib.kiev.ua> In-Reply-To: <202506131920.55DJKEGT006179@gitrepo.freebsd.org> References: <202506131920.55DJKEGT006179@gitrepo.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, Jun 13, 2025 at 07:20:14PM +0000, Mark Johnston wrote: > The branch main has been updated by markj: > > URL: https://cgit.FreeBSD.org/src/commit/?id=48a656c588f9fb995b9c524b57dd5febd9f69168 > > commit 48a656c588f9fb995b9c524b57dd5febd9f69168 > Author: Mark Johnston <markj@FreeBSD.org> > AuthorDate: 2025-06-13 19:03:03 +0000 > Commit: Mark Johnston <markj@FreeBSD.org> > CommitDate: 2025-06-13 19:19:59 +0000 > > linux: Fix usage of ptrace(PT_GET_SC_ARGS) > > The native handler expects the argument to be a pointer to an array of 8 > syscall arguments, whereas the emulation provided an array that holds up > to 6. > > Handle this by adding a new range of Linuxulator-specific ptrace > commands. In particular, introduce PTLINUX_GET_SC_ARGS, which always > copies exactly six arguments. This fixes the problem and removes the > hack of checking the target thread ABI to decide whether to apply a > Linux-specific quirk to PT_GET_SC_ARGS. > > Reviewed by: kib > MFC after: 2 weeks > Sponsored by: Klara, Inc. > Differential Revision: https://reviews.freebsd.org/D50758 > --- > sys/compat/freebsd32/freebsd32_misc.c | 3 +++ > sys/compat/linux/linux_ptrace.c | 18 ++++-------------- > sys/kern/sys_process.c | 27 +++++++++++++++++++++------ > sys/sys/ptrace.h | 8 ++++++++ > 4 files changed, 36 insertions(+), 20 deletions(-) > > diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c > index cc777f2bf830..75fdb1f544ca 100644 > --- a/sys/compat/freebsd32/freebsd32_misc.c > +++ b/sys/compat/freebsd32/freebsd32_misc.c > @@ -1177,6 +1177,9 @@ freebsd32_ptrace(struct thread *td, struct freebsd32_ptrace_args *uap) > pscr_args[i] = pscr_args32[i]; > r.sr.pscr_args = pscr_args; > break; > + case PTLINUX_FIRST ... PTLINUX_LAST: > + error = EINVAL; > + break; > default: > addr = uap->addr; > break; > diff --git a/sys/compat/linux/linux_ptrace.c b/sys/compat/linux/linux_ptrace.c > index 421760eab2a9..0dbfd2177122 100644 > --- a/sys/compat/linux/linux_ptrace.c > +++ b/sys/compat/linux/linux_ptrace.c > @@ -386,21 +386,11 @@ linux_ptrace_get_syscall_info(struct thread *td, pid_t pid, > if (lwpinfo.pl_flags & PL_FLAG_SCE) { > si.op = LINUX_PTRACE_SYSCALL_INFO_ENTRY; > si.entry.nr = lwpinfo.pl_syscall_code; > - /* > - * The use of PT_GET_SC_ARGS there is special, > - * implementation of PT_GET_SC_ARGS for Linux-ABI > - * callers emulates Linux bug which strace(1) depends > - * on: at initialization it tests whether ptrace works > - * by calling close(2), or some other single-argument > - * syscall, _with six arguments_, and then verifies > - * whether it can fetch them all using this API; > - * otherwise it bails out. > - */ > - error = kern_ptrace(td, PT_GET_SC_ARGS, pid, > - &si.entry.args, sizeof(si.entry.args)); > + error = kern_ptrace(td, PTLINUX_GET_SC_ARGS, pid, > + si.entry.args, sizeof(si.entry.args)); > if (error != 0) { > - linux_msg(td, "PT_GET_SC_ARGS failed with error %d", > - error); > + linux_msg(td, > + "PT_LINUX_GET_SC_ARGS failed with error %d", error); > return (error); > } > } else if (lwpinfo.pl_flags & PL_FLAG_SCX) { > diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c > index 8b382cb3048e..821c537065b3 100644 > --- a/sys/kern/sys_process.c > +++ b/sys/kern/sys_process.c > @@ -690,6 +690,9 @@ sys_ptrace(struct thread *td, struct ptrace_args *uap) > break; > r.sr.pscr_args = pscr_args; > break; > + case PTLINUX_FIRST ... PTLINUX_LAST: > + error = EINVAL; > + break; > default: > addr = uap->addr; > break; > @@ -1166,7 +1169,9 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) > break; > > case PT_GET_SC_ARGS: > - CTR1(KTR_PTRACE, "PT_GET_SC_ARGS: pid %d", p->p_pid); > + case PTLINUX_GET_SC_ARGS: > + CTR2(KTR_PTRACE, "%s: pid %d", req == PT_GET_SC_ARGS ? > + "PT_GET_SC_ARGS" : "PT_LINUX_GET_SC_ARGS", p->p_pid); > if (((td2->td_dbgflags & (TDB_SCE | TDB_SCX)) == 0 && > td2->td_sa.code == 0) > #ifdef COMPAT_FREEBSD32 > @@ -1176,11 +1181,21 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) > error = EINVAL; > break; > } > - bzero(addr, sizeof(td2->td_sa.args)); > - /* See the explanation in linux_ptrace_get_syscall_info(). */ > - bcopy(td2->td_sa.args, addr, SV_PROC_ABI(td->td_proc) == > - SV_ABI_LINUX ? sizeof(td2->td_sa.args) : > - td2->td_sa.callp->sy_narg * sizeof(syscallarg_t)); > + if (req == PT_GET_SC_ARGS) { > + bzero(addr, sizeof(td2->td_sa.args)); > + bcopy(td2->td_sa.args, addr, td2->td_sa.callp->sy_narg * > + sizeof(syscallarg_t)); > + } else { > + /* > + * Emulate a Linux bug which which strace(1) depends on: > + * at initialization it tests whether ptrace works by > + * calling close(2), or some other single-argument > + * syscall, _with six arguments_, and then verifies > + * whether it can fetch them all using this API; > + * otherwise it bails out. > + */ > + bcopy(td2->td_sa.args, addr, 6 * sizeof(syscallarg_t)); > + } > break; > > case PT_GET_SC_RET: > diff --git a/sys/sys/ptrace.h b/sys/sys/ptrace.h > index 3a7b87bfc85f..13291cd31cf5 100644 > --- a/sys/sys/ptrace.h > +++ b/sys/sys/ptrace.h > @@ -87,8 +87,16 @@ > #define PT_SC_REMOTE 44 /* Execute a syscall */ > > #define PT_FIRSTMACH 64 /* for machine-specific requests */ > +#define PT_LASTMACH 127 > #include <machine/ptrace.h> /* machine-specific requests, if any */ > > +#ifdef _KERNEL > +/* Space for Linux ptrace emulation. */ > +#define PTLINUX_FIRST 128 As an after-thought, I think it is better to name them like PTINTERNAL_FIRST/LAST. > +#define PTLINUX_LAST 191 > +#define PTLINUX_GET_SC_ARGS (PTLINUX_FIRST + 0) > +#endif > + > /* Events used with PT_GET_EVENT_MASK and PT_SET_EVENT_MASK */ > #define PTRACE_EXEC 0x0001 > #define PTRACE_SCE 0x0002
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?aE6BvayWrz9dtLc7>