pdptrace(2): allow debugging in capability mode

The pdopenpid(2) syscall is allowed in capability mode. Add the chicken
switch security.bsd.ptrace_in_cap_mode, which disables it without
reboot, if needed.

The descriptor passed to pdptrace(2) must have the CAP_PTRACE
capability enabled. This capability is not enabled by default by
pdfork()/pdopenpid(), and the calls do not return a procdesc suitable
for debugging. The opening code must prepare for debugging in advance by
passing the PD_PTRACE_CAP flag to pdfork()/pdopenpid().

For ptrace(2), allow PT_CLEARSTEP and PT_GET_CHILDREN for the current
thread and process in cap mode as well.

Reviewed by:	markj
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D58989
This commit is contained in:
Konstantin Belousov committed 2026-08-28 14:55:11 +03:00
1 parent 68d4b31127
commit 7006cb7bd2
3 files changed
+24 -9

No files matched your search

-3
View File
@@ -1050,9 +1050,6 @@ freebsd32_ptrace_useraction(struct thread *td, int req, bool pd_mode, pid_t pid,
void *addr;
int data, error, i;
if (!allow_ptrace)
return (ENOSYS);
error = 0;
addr = &r;
data = udata;
+22 -4
View File
@@ -51,6 +51,7 @@
#include <sys/sleepqueue.h>
#include <sys/sx.h>
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
#include <sys/sysent.h>
#include <sys/sysproto.h>
#include <sys/vnode.h>
@@ -708,6 +709,24 @@ ptrace_vm_entry(struct thread *td, struct proc *p, struct ptrace_vm_entry *pve)
return (error);
}
static int
ptrace_check_allowed(struct thread *td, int req, bool pd_mode, pid_t pid)
{
if (!allow_ptrace)
return (ENOSYS);
if (!IN_CAPABILITY_MODE(td))
return (0);
if (!allow_ptrace_in_cap_mode)
return (ECAPMODE);
if (pd_mode)
return (0);
if (req == PT_GET_CHILDREN && pid == td->td_proc->p_pid)
return (0);
if (req == PT_CLEARSTEP && pid == td->td_tid)
return (0);
return (ECAPMODE);
}
/*
* Process debugging system call.
*/
@@ -748,12 +767,11 @@ ptrace_useraction(struct thread *td, int req, bool pd_mode, pid_t pid, int pfd,
void *addr;
int error, data;
if (!allow_ptrace)
return (ENOSYS);
error = ptrace_check_allowed(td, req, pd_mode, pid);
if (error != 0)
return (error);
error = 0;
addr = &r;
switch (req) {
case PT_GET_EVENT_MASK:
case PT_LWPINFO:
+2 -2
View File
@@ -264,7 +264,7 @@
25 AUE_GETEUID STD|CAPENABLED {
uid_t geteuid(void);
}
26 AUE_PTRACE STD {
26 AUE_PTRACE STD|CAPENABLED {
int ptrace(
int req,
pid_t pid,
@@ -3442,7 +3442,7 @@
int flags
);
}
605 AUE_PDPTRACE STD {
605 AUE_PDPTRACE STD|CAPENABLED {
int pdptrace(
int req,
int pfd,