git: 91e11c8f2b38 - main - procdesc: Disallow pddupfd() of non-passable files
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 24 Jul 2026 21:07:23 UTC
The branch main has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=91e11c8f2b38eb1d1f3a1d57b27378fb2c6ab3c1
commit 91e11c8f2b38eb1d1f3a1d57b27378fb2c6ab3c1
Author: Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-07-24 20:05:26 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-07-24 20:05:26 +0000
procdesc: Disallow pddupfd() of non-passable files
Reported by: Maik Muench of Secfault Security
Reviewed by: kib
Fixes: 1ad21a652182 ("kern: add pddupfd(2)")
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D58403
---
lib/libsys/pdfork.2 | 6 ++++++
sys/kern/sys_procdesc.c | 10 +++++++---
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/lib/libsys/pdfork.2 b/lib/libsys/pdfork.2
index 584c87e17e38..1b99157203c1 100644
--- a/lib/libsys/pdfork.2
+++ b/lib/libsys/pdfork.2
@@ -195,6 +195,8 @@ flag set.
The
.Fa flags
argument is reserved and must be zero.
+Certain file descriptor types cannot be copied this way, namely
+kqueues.
.Pp
The following system calls also have effects specific to process descriptors:
.Pp
@@ -350,6 +352,10 @@ The file descriptor
is not a valid file descriptor in the specified process.
.It Bq Er ENOENT
The specified process does not have a file descriptor table.
+.It Bq Er EOPNOTSUPP
+.Fa remotefd
+refers to a file that cannot be duplicated across a process boundary,
+such as a kqueue.
.El
.Sh SEE ALSO
.Xr close 2 ,
diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c
index 7fc63256bc05..b913c9109f18 100644
--- a/sys/kern/sys_procdesc.c
+++ b/sys/kern/sys_procdesc.c
@@ -796,9 +796,13 @@ kern_pddupfd(struct thread *td, int pdfd, int fd, int flags)
PROC_UNLOCK(p);
error = fget_remote(td, p, fd, &fcaps, &fd_flags, &fp);
if (error == 0) {
- error = finstall_refed(td, fp, &fdr, O_CLOEXEC |
- ((fd_flags & FD_RESOLVE_BENEATH) != 0 ?
- O_RESOLVE_BENEATH : 0), &fcaps);
+ if ((fp->f_ops->fo_flags & DFLAG_PASSABLE) == 0) {
+ error = EOPNOTSUPP;
+ } else {
+ error = finstall_refed(td, fp, &fdr, O_CLOEXEC |
+ ((fd_flags & FD_RESOLVE_BENEATH) != 0 ?
+ O_RESOLVE_BENEATH : 0), &fcaps);
+ }
if (error != 0) {
fdrop(fp, td);
filecaps_free(&fcaps);