git: 336fec57a6cc - stable/14 - linux: Fix usage of ptrace(PT_GET_SC_ARGS)
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 30 Jun 2025 14:21:30 UTC
The branch stable/14 has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=336fec57a6cc0a4ee58ed9a094905ad4ad7030fe
commit 336fec57a6cc0a4ee58ed9a094905ad4ad7030fe
Author: Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2025-06-13 19:03:03 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
CommitDate: 2025-06-30 14:19:30 +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
(cherry picked from commit 48a656c588f9fb995b9c524b57dd5febd9f69168)
---
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 a8331897316d..951d9c28b7f1 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 4d1d0ef21a15..f81013ffb842 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -696,6 +696,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;
@@ -1172,7 +1175,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
@@ -1182,11 +1187,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 3cce2c088f0b..85c6b2d5366a 100644
--- a/sys/sys/ptrace.h
+++ b/sys/sys/ptrace.h
@@ -89,8 +89,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
+#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