git: 68d4b311270e - main - kern: add p_canopen()

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

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

commit 68d4b311270ecca80bbb887a5e502e2caacebc98
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-07-14 16:59:17 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-08-28 11:55:10 +0000

    kern: add p_canopen()
    
    The function defines the policy for allowing to open a pid.
    
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D58989
---
 sys/kern/kern_prot.c   | 28 ++++++++++++++++++++++++++--
 sys/kern/sys_process.c |  5 +++++
 sys/sys/proc.h         |  1 +
 sys/sys/ptrace.h       |  1 +
 4 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index 5aa7fcf7c653..5370028f4490 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -46,14 +46,13 @@
  * System calls related to processes and protection
  */
 
-#include <sys/cdefs.h>
 #include "opt_inet.h"
 #include "opt_inet6.h"
 
-#include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/abi_compat.h>
 #include <sys/acct.h>
+#include <sys/capsicum.h>
 #include <sys/imgact.h>
 #include <sys/kdb.h>
 #include <sys/kernel.h>
@@ -2313,6 +2312,31 @@ cr_xids_subset(struct ucred *active_cred, struct ucred *obj_cred)
 	return (uidsubset && grpsubset);
 }
 
+/*
+ * Determine whether the td thread allowed to do pdopenpid(2) on the
+ * process p.  The permissions are scoped to the PIDs namespace and
+ * processes hierarchy, and do not imply permissions to perform
+ * operations on the resulting process descriptor, e.g. pdkill(2) and
+ * other.
+ */
+int
+p_canopen(struct thread *td, struct proc *p)
+{
+#ifdef INVARIANTS
+	if (IN_CAPABILITY_MODE(td))
+		sx_assert(&proctree_lock, SX_LOCKED);
+#endif
+
+	/*
+	 * Allow implicit parent in cap mode: either real parent or
+	 * debugger can open pid.
+	 */
+	if (!IN_CAPABILITY_MODE(td) || (allow_ptrace_in_cap_mode &&
+	    (td->td_proc == p->p_pptr || p->p_oppid == td->td_proc->p_pid)))
+		return (0);
+	return (ECAPMODE);
+}
+
 /*-
  * Determine whether td may debug p.
  * Returns: 0 for permitted, an errno value otherwise
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index 2cf9ffaa68dd..35aa376fb6f5 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -70,6 +70,11 @@
 #include <sys/procfs.h>
 #endif
 
+bool allow_ptrace_in_cap_mode = true;
+SYSCTL_BOOL(_security_bsd, OID_AUTO, allow_ptrace_in_cap_mode, CTLFLAG_RWTUN,
+    &allow_ptrace_in_cap_mode, 0,
+    "Allow ptrace(2) in capability mode");
+
 /* Assert it's safe to unlock a process, e.g. to allocate working memory */
 #define	PROC_ASSERT_TRACEREQ(p)	MPASS(((p)->p_flag2 & P2_PTRACEREQ) != 0)
 
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index c052540cece5..a10bcfb9d910 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -1195,6 +1195,7 @@ int	leavepgrp(struct proc *p);
 void	maybe_yield(void);
 void	mi_switch(int flags);
 int	p_candebug(struct thread *td, struct proc *p);
+int	p_canopen(struct thread *td, struct proc *p);
 int	p_cansee(struct thread *td, struct proc *p);
 int	p_cansched(struct thread *td, struct proc *p);
 int	p_cansignal(struct thread *td, struct proc *p, int signum);
diff --git a/sys/sys/ptrace.h b/sys/sys/ptrace.h
index 1e219b606dbd..d6e071285eac 100644
--- a/sys/sys/ptrace.h
+++ b/sys/sys/ptrace.h
@@ -296,6 +296,7 @@ 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;
+extern bool allow_ptrace_in_cap_mode;
 
 #else /* !_KERNEL */