git: 68d4b311270e - main - kern: add p_canopen()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
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 */