Add pdptrace(2)

Reviewed by:	markj
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D58586
This commit is contained in:
Konstantin Belousov committed 2026-08-28 14:52:32 +03:00
1 parent 9cea869940
commit f8c0616052
4 files changed
+91 -29

No files matched your search

+19 -5
View File
@@ -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);
}
+61 -22
View File
@@ -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);
}
+9
View File
@@ -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
+2 -2
View File
@@ -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;