git: 7006cb7bd22d - main - pdptrace(2): allow debugging in capability mode

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Fri, 28 Aug 2026 12:05:16 UTC
The branch main has been updated by kib:

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

commit 7006cb7bd22d07d2ce30b0fb7ebfe58771b2a32f
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-07-07 23:46:56 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-08-28 11:55:11 +0000

    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
---
 sys/compat/freebsd32/freebsd32_misc.c |  3 ---
 sys/kern/sys_process.c                | 26 ++++++++++++++++++++++----
 sys/kern/syscalls.master              |  4 ++--
 3 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index 4da3b4ee97c1..bb4548660278 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -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;
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index 35aa376fb6f5..5c8f32773412 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -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:
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 7050e564903e..656c73da348f 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -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,