git: e8c313204887 - main - pdfork(2): add PD_PTRACE_CAP flag
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 28 Aug 2026 12:05:04 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=e8c313204887e7ba47b5c349acbe37d64a3162a1
commit e8c313204887e7ba47b5c349acbe37d64a3162a1
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:52:31 +0000
pdfork(2): add PD_PTRACE_CAP flag
If the flag is not specified, the process descriptor returned by either
pdfork(2) or pdopenpid(2) has the CAP_PTRACE capability disabled.
Reviewed by: markj
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D58586
---
sys/kern/kern_fork.c | 14 ++++++++++++++
sys/kern/sys_procdesc.c | 7 ++++++-
sys/sys/procdesc.h | 6 ++++--
3 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 7d2535de987f..182d5ec68b20 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -41,6 +41,7 @@
#include <sys/systm.h>
#include <sys/acct.h>
#include <sys/bitstring.h>
+#include <sys/capsicum.h>
#include <sys/eventhandler.h>
#include <sys/exterrvar.h>
#include <sys/fcntl.h>
@@ -119,6 +120,7 @@ int
sys_pdfork(struct thread *td, struct pdfork_args *uap)
{
struct fork_req fr;
+ struct filecaps fcaps;
int error, fd, pid;
bzero(&fr, sizeof(fr));
@@ -126,6 +128,10 @@ sys_pdfork(struct thread *td, struct pdfork_args *uap)
fr.fr_pidp = &pid;
fr.fr_pd_fd = &fd;
fr.fr_pd_flags = uap->flags;
+ filecaps_fill(&fcaps);
+ if ((uap->flags & PD_PTRACE_CAP) == 0)
+ cap_rights_clear(&fcaps.fc_rights, CAP_PTRACE);
+ fr.fr_pd_fcaps = &fcaps;
AUDIT_ARG_FFLAGS(uap->flags);
/*
* It is necessary to return fd by reference because 0 is a valid file
@@ -194,6 +200,7 @@ int
sys_pdrfork(struct thread *td, struct pdrfork_args *uap)
{
struct fork_req fr;
+ struct filecaps fcaps;
int error, fd, pid;
bzero(&fr, sizeof(fr));
@@ -226,6 +233,10 @@ sys_pdrfork(struct thread *td, struct pdrfork_args *uap)
fr.fr_pidp = &pid;
fr.fr_pd_fd = &fd;
fr.fr_pd_flags = uap->pdflags;
+ filecaps_fill(&fcaps);
+ if ((uap->pdflags & PD_PTRACE_CAP) == 0)
+ cap_rights_clear(&fcaps.fc_rights, CAP_PTRACE);
+ fr.fr_pd_fcaps = &fcaps;
error = fork1(td, &fr);
if (error == 0) {
td->td_retval[0] = pid;
@@ -1068,6 +1079,7 @@ fork1(struct thread *td, struct fork_req *fr)
fr->fr_pd_flags, fr->fr_pd_fcaps);
if (error != 0)
goto fail2;
+ fr->fr_pd_fcaps = NULL;
AUDIT_ARG_FD(*fr->fr_pd_fd);
}
@@ -1163,6 +1175,8 @@ fail2:
fdclose(td, fp_procdesc, *fr->fr_pd_fd);
fdrop(fp_procdesc, td);
}
+ if (fr->fr_pd_fcaps != NULL)
+ filecaps_free(fr->fr_pd_fcaps);
atomic_add_int(&nprocs, -1);
cleanup:
if (killsx_locked)
diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c
index 0d0ca7b6871c..5ee8a4734248 100644
--- a/sys/kern/sys_procdesc.c
+++ b/sys/kern/sys_procdesc.c
@@ -692,6 +692,7 @@ kern_pdopenpid(struct thread *td, pid_t pid, int flags)
{
struct file *fp;
struct procdesc *pdf;
+ struct filecaps fcaps;
int error, fd, fflags;
error = falloc_noinstall(td, &fp);
@@ -701,13 +702,16 @@ kern_pdopenpid(struct thread *td, pid_t pid, int flags)
pdf = procdesc_alloc(flags);
if ((flags & PD_DAEMON) != 0)
fp->f_pdflags |= F_PD_NOKILL;
+ filecaps_fill(&fcaps);
+ if ((flags & PD_PTRACE_CAP) == 0)
+ cap_rights_clear(&fcaps.fc_rights, CAP_PTRACE);
sx_xlock(&proctree_lock);
error = pdopenpid1(td, pid, &pdf, fp);
sx_xunlock(&proctree_lock);
if (error == 0) {
- error = finstall(td, fp, &fd, fflags, NULL);
+ error = finstall(td, fp, &fd, fflags, &fcaps);
if (error == 0) {
td->td_retval[0] = fd;
} else {
@@ -716,6 +720,7 @@ kern_pdopenpid(struct thread *td, pid_t pid, int flags)
* return file descriptor to userspace.
*/
fp->f_pdflags |= F_PD_NOKILL | F_PD_NOFINSTALL;
+ filecaps_free(&fcaps);
}
}
fdrop(fp, td);
diff --git a/sys/sys/procdesc.h b/sys/sys/procdesc.h
index 6cb837af2d3b..f4cba787db01 100644
--- a/sys/sys/procdesc.h
+++ b/sys/sys/procdesc.h
@@ -161,8 +161,10 @@ __END_DECLS
#define PD_DAEMON 0x00000001 /* Don't exit when procdesc closes. */
#define PD_CLOEXEC 0x00000002 /* Close file descriptor on exec. */
#define PD_NOWAITPID 0x00000004 /* Reap without waitpid(). */
+#define PD_PTRACE_CAP 0x00000008 /* Allow PT_PROCDESC in cap mode. */
-#define PD_ALLOWED_AT_FORK (PD_DAEMON | PD_CLOEXEC | PD_NOWAITPID)
-#define PD_ALLOWED_AT_OPENPID (PD_DAEMON | PD_CLOEXEC)
+#define PD_ALLOWED_AT_FORK \
+ (PD_DAEMON | PD_CLOEXEC | PD_NOWAITPID | PD_PTRACE_CAP)
+#define PD_ALLOWED_AT_OPENPID (PD_DAEMON | PD_CLOEXEC | PD_PTRACE_CAP)
#endif /* !_SYS_PROCDESC_H_ */