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 #include "opt_inet.h" #include "opt_inet6.h" -#include #include #include #include +#include #include #include #include @@ -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 #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 */