git: 1ad21a652182 - main - kern: add pddupfd(2)
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 07 Jul 2026 23:28:23 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=1ad21a6521827473dc6692646e9c760a5b0521cd
commit 1ad21a6521827473dc6692646e9c760a5b0521cd
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-05-21 19:12:45 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-07-07 22:03:53 +0000
kern: add pddupfd(2)
Reviewed by: markj
Tested by: pho
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D57163
---
sys/kern/kern_descrip.c | 8 +++--
sys/kern/sys_procdesc.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++
sys/kern/syscalls.master | 7 +++++
3 files changed, 95 insertions(+), 2 deletions(-)
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 351cc1917b04..8272d6da9b0a 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -3162,6 +3162,7 @@ fget_remote(struct thread *td, struct proc *p, int fd, struct filecaps *fcaps,
struct filedesc *fdp;
struct file *fp;
int error;
+ bool copied __diagused;
/*
* Both fcaps and fd_flags must be either requested together,
@@ -3186,8 +3187,11 @@ fget_remote(struct thread *td, struct proc *p, int fd, struct filecaps *fcaps,
*fd_flags = fde_to_fd_flags(fdp->fd_ofiles[fd].
fde_flags);
}
- if (fcaps != NULL)
- *fcaps = fdp->fd_ofiles[fd].fde_caps;
+ if (fcaps != NULL) {
+ copied = filecaps_copy(
+ &fdp->fd_ofiles[fd].fde_caps, fcaps, true);
+ MPASS(copied);
+ }
error = 0;
} else {
error = EBADF;
diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c
index 4749a9b8bf7e..7351df11c631 100644
--- a/sys/kern/sys_procdesc.c
+++ b/sys/kern/sys_procdesc.c
@@ -67,6 +67,7 @@
#include <sys/fcntl.h>
#include <sys/file.h>
#include <sys/filedesc.h>
+#include <sys/imgact.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
@@ -702,3 +703,84 @@ sys_pdopenpid(struct thread *td, struct pdopenpid_args *args)
return (EINVAL);
return (kern_pdopenpid(td, args->pid, args->flags));
}
+
+static int
+kern_pddupfd(struct thread *td, int pdfd, int fd, int flags)
+{
+ struct proc *p;
+ struct file *fp, *pfp;
+ struct procdesc *pd;
+ struct filecaps fcaps;
+ uint8_t fd_flags;
+ int error, fdr;
+
+ error = fget(td, pdfd, &cap_pddupfd_rights, &pfp);
+ if (error != 0)
+ return (error);
+ if (pfp->f_type != DTYPE_PROCDESC) {
+ error = EBADF;
+ goto out;
+ }
+ pd = pfp->f_data;
+again:
+ sx_slock(&proctree_lock);
+ p = pd->pd_proc;
+ if (p != NULL) {
+ AUDIT_ARG_PROCESS(p);
+ PROC_LOCK(p);
+ sx_sunlock(&proctree_lock);
+ if ((p->p_flag & P_WEXIT) != 0) {
+ error = ESRCH;
+ } else {
+ /*
+ * Block the target process from entering
+ * execve(). We need to ensure that the
+ * p_candebug() predicate is stable until the
+ * fget_remote() call ends even after the
+ * process lock is dropped. For that, the
+ * process must not change uid/suid.
+ */
+ if (!execve_block(td, p))
+ goto again;
+ error = p_candebug(td, p);
+ if (error == 0)
+ _PHOLD(p);
+ else
+ execve_unblock(td, p);
+ }
+ PROC_UNLOCK(p);
+ if (error != 0)
+ goto out;
+
+ error = fget_remote(td, p, fd, &fcaps, &fd_flags, &fp);
+ PROC_LOCK(p);
+ execve_unblock(td, p);
+ _PRELE(p);
+ PROC_UNLOCK(p);
+ if (error == 0) {
+ 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);
+ } else {
+ td->td_retval[0] = fdr;
+ }
+ }
+ } else {
+ sx_sunlock(&proctree_lock);
+ error = ESRCH;
+ }
+out:
+ fdrop(pfp, td);
+ return (error);
+}
+
+int
+sys_pddupfd(struct thread *td, struct pddupfd_args *args)
+{
+ if (args->flags != 0)
+ return (EINVAL);
+ return (kern_pddupfd(td, args->pd, args->fd, args->flags));
+}
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 8ea32a7b0058..4bc5385f76e7 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -3435,5 +3435,12 @@
int flags
);
}
+604 AUE_NULL STD {
+ int pddupfd(
+ int pd,
+ int fd,
+ int flags
+ );
+ }
; vim: syntax=off