The branch main has been updated by kib:

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

commit f8c0616052e2befaf7271fa82b212ff34a7913af
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2026-07-19 21:33:54 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2026-08-28 11:52:32 +0000

    Add pdptrace(2)
    
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D58586
---
 sys/compat/freebsd32/freebsd32_misc.c | 24 +++++++---
 sys/kern/sys_process.c                | 83 +++++++++++++++++++++++++----------
 sys/kern/syscalls.master              |  9 ++++
 sys/sys/ptrace.h                      |  4 +-
 4 files changed, 91 insertions(+), 29 deletions(-)

diff --git a/sys/compat/freebsd32/freebsd32_misc.c 
b/sys/compat/freebsd32/freebsd32_misc.c
index 5b5a13a16de1..103a40f221ac 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -1016,8 +1016,8 @@ ptrace_sc_ret32_to_ret(const struct ptrace_sc_ret32 
*psr32,
 }
 
 static int
-freebsd32_ptrace_useraction(struct thread *td, int req, pid_t pid,
-    void *uaddr, int udata)
+freebsd32_ptrace_useraction(struct thread *td, int req, bool pd_mode, pid_t 
pid,
+    int pfd, lwpid_t lwpid, void *uaddr, int udata)
 {
        union {
                struct ptrace_io_desc piod;
@@ -1181,7 +1181,7 @@ freebsd32_ptrace_useraction(struct thread *td, int req, 
pid_t pid,
        if (error != 0)
                return (error);
 
-       error = ptrace_action(td, req, pid, addr, data);
+       error = ptrace_action(td, req, pd_mode, pid, pfd, lwpid, addr, data);
        if (error != 0)
                return (error);
 
@@ -1259,8 +1259,22 @@ freebsd32_ptrace(struct thread *td, struct 
freebsd32_ptrace_args *uap)
        AUDIT_ARG_CMD(uap->req);
        AUDIT_ARG_VALUE(uap->data);
 
-       error = freebsd32_ptrace_useraction(td, uap->req, uap->pid,
-           uap->addr, uap->data);
+       error = freebsd32_ptrace_useraction(td, uap->req, false, uap->pid,
+           -1, -1, uap->addr, uap->data);
+       return (error);
+}
+
+int
+freebsd32_pdptrace(struct thread *td, struct freebsd32_pdptrace_args *uap)
+{
+       int error;
+
+       AUDIT_ARG_FD(uap->pfd);
+       AUDIT_ARG_CMD(uap->req);
+       AUDIT_ARG_VALUE(uap->data);
+
+       error = freebsd32_ptrace_useraction(td, uap->req, true, -1,
+           uap->pfd, uap->lwpid, uap->addr, uap->data);
        return (error);
 }
 
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index 39196561928c..94dbb8215a1e 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -32,7 +32,7 @@
  */
 
 #include <sys/systm.h>
-#include <sys/caprights.h>
+#include <sys/capsicum.h>
 #include <sys/filedesc.h>
 #include <sys/imgact.h>
 #include <sys/ktr.h>
@@ -43,6 +43,7 @@
 #include <sys/mutex.h>
 #include <sys/priv.h>
 #include <sys/proc.h>
+#include <sys/procdesc.h>
 #include <sys/ptrace.h>
 #include <sys/reg.h>
 #include <sys/rwlock.h>
@@ -715,8 +716,8 @@ struct ptrace_args {
 #endif
 
 static int
-ptrace_useraction(struct thread *td, int req, pid_t pid, void *uaddr,
-    int udata)
+ptrace_useraction(struct thread *td, int req, bool pd_mode, pid_t pid, int pfd,
+    lwpid_t lwpid, void *uaddr, int udata)
 {
        /*
         * XXX this obfuscation is to reduce stack usage, but the register
@@ -826,7 +827,7 @@ ptrace_useraction(struct thread *td, int req, pid_t pid, 
void *uaddr,
        if (error != 0)
                return (error);
 
-       error = ptrace_action(td, req, pid, addr, udata);
+       error = ptrace_action(td, req, pd_mode, pid, pfd, lwpid, addr, udata);
        if (error != 0)
                return (error);
 
@@ -1044,7 +1045,8 @@ ptrace_sel_coredump_thread(struct proc *p)
 }
 
 int
-ptrace_action(struct thread *td, int req, pid_t pid, void *addr, int data)
+ptrace_action(struct thread *td, int req, bool pd_mode, pid_t pid, int pfd,
+    lwpid_t lwpid, void *addr, int data)
 {
        struct iovec iov;
        struct uio uio;
@@ -1058,6 +1060,7 @@ ptrace_action(struct thread *td, int req, pid_t pid, void 
*addr, int data)
        struct ptrace_coredump *pc;
        struct thr_coredump_req *tcq;
        struct thr_syscall_req *tsr;
+       struct file *pfp;
        struct ptrace_child *children, *ptc;
        int error, num, num1, tmp;
        lwpid_t tid = 0, *buf;
@@ -1069,6 +1072,7 @@ ptrace_action(struct thread *td, int req, pid_t pid, void 
*addr, int data)
        curp = td->td_proc;
        proctree_locked = false;
        p2_req_set = false;
+       pfp = NULL;
 
        /* Lock proctree before locking the process. */
        switch (req) {
@@ -1096,24 +1100,42 @@ ptrace_action(struct thread *td, int req, pid_t pid, 
void *addr, int data)
        if (req == PT_TRACE_ME) {
                p = td->td_proc;
                PROC_LOCK(p);
-       } else {
-               if (pid <= PID_MAX) {
-                       if ((p = pfind(pid)) == NULL) {
-                               if (proctree_locked)
-                                       sx_xunlock(&proctree_lock);
-                               return (ESRCH);
+       } else if (pd_mode) {
+               if (!proctree_locked)
+                       sx_slock(&proctree_lock);
+               error = fget_procdesc(td, pfd, &cap_ptrace_rights, EINVAL,
+                   &pfp, NULL, &p);
+               if (!proctree_locked)
+                       sx_sunlock(&proctree_lock);
+               if (error != 0)
+                       goto fail_proctree;
+               pid = p->p_pid;
+               if (lwpid != -1) {
+                       FOREACH_THREAD_IN_PROC(p, td2) {
+                               if (td2->td_tid == lwpid)
+                                       break;
                        }
-               } else {
-                       td2 = tdfind(pid, -1);
                        if (td2 == NULL) {
-                               if (proctree_locked)
-                                       sx_xunlock(&proctree_lock);
-                               return (ESRCH);
+                               PROC_UNLOCK(p);
+                               error = ESRCH;
+                               goto fail_proctree;
                        }
-                       p = td2->td_proc;
-                       tid = pid;
-                       pid = p->p_pid;
+                       tid = td2->td_tid;
+               }
+       } else if (pid <= PID_MAX) {
+               if ((p = pfind(pid)) == NULL) {
+                       error = ESRCH;
+                       goto fail_proctree;
+               }
+       } else {
+               td2 = tdfind(pid, -1);
+               if (td2 == NULL) {
+                       error = ESRCH;
+                       goto fail_proctree;
                }
+               p = td2->td_proc;
+               tid = pid;
+               pid = p->p_pid;
        }
        AUDIT_ARG_PROCESS(p);
 
@@ -2009,8 +2031,11 @@ fail:
                p->p_flag2 &= ~P2_PTRACEREQ;
        }
        PROC_UNLOCK(p);
+fail_proctree:
        if (proctree_locked)
                sx_xunlock(&proctree_lock);
+       if (pfp != NULL)
+               fdrop(pfp, td);
        return (error);
 }
 #undef PROC_READ
@@ -2019,7 +2044,7 @@ fail:
 int
 kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
 {
-       return (ptrace_action(td, req, pid, addr, data));
+       return (ptrace_action(td, req, false, pid, -1, -1, addr, data));
 }
 
 int
@@ -2031,7 +2056,21 @@ sys_ptrace(struct thread *td, struct ptrace_args *uap)
        AUDIT_ARG_CMD(uap->req);
        AUDIT_ARG_VALUE(uap->data);
 
-       error = ptrace_useraction(td, uap->req, uap->pid, uap->addr,
-           uap->data);
+       error = ptrace_useraction(td, uap->req, false, uap->pid, -1, -1,
+           uap->addr, uap->data);
+       return (error);
+}
+
+int
+sys_pdptrace(struct thread *td, struct pdptrace_args *uap)
+{
+       int error;
+
+       AUDIT_ARG_FD(uap->pfd);
+       AUDIT_ARG_CMD(uap->req);
+       AUDIT_ARG_VALUE(uap->data);
+
+       error = ptrace_useraction(td, uap->req, true, -1, uap->pfd, uap->lwpid,
+           uap->addr, uap->data);
        return (error);
 }
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 64145f2c3e57..7050e564903e 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -3442,5 +3442,14 @@
                        int flags
                );
        }
+605    AUE_PDPTRACE    STD {
+               int pdptrace(
+                       int req,
+                       int pfd,
+                       int lwpid,
+                       _Inout_opt_ _Contains_long_ptr_ void *addr,
+                       int data
+               );
+       }
 
 ; vim: syntax=off
diff --git a/sys/sys/ptrace.h b/sys/sys/ptrace.h
index 50e7dba5c946..52f13d4d6790 100644
--- a/sys/sys/ptrace.h
+++ b/sys/sys/ptrace.h
@@ -291,8 +291,8 @@ int proc_write_dbregs32(struct thread *_td, struct dbreg32 
*_dbreg32);
 #endif
 
 void   ptrace_unsuspend(struct proc *p);
-int    ptrace_action(struct thread *td, int req, pid_t pid, void *addr,
-           int data);
+int    ptrace_action(struct thread *td, int req, bool pd_mode, pid_t pid,
+           int pfd, lwpid_t lwpid, void *addr, int data);
 
 extern bool allow_ptrace;
 

Reply via email to