git: f8c0616052e2 - main - Add pdptrace(2)
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 28 Aug 2026 12:05:08 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=f8c0616052e2befaf7271fa82b212ff34a7913af
commit f8c0616052e2befaf7271fa82b212ff34a7913af
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-07-19 21:33:54 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
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;