The branch main has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=48a656c588f9fb995b9c524b57dd5febd9f69168

commit 48a656c588f9fb995b9c524b57dd5febd9f69168
Author:     Mark Johnston <ma...@freebsd.org>
AuthorDate: 2025-06-13 19:03:03 +0000
Commit:     Mark Johnston <ma...@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
+#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

Reply via email to