git: 61f4a89823b7 - stable/15 - kern: add pddupfd(2)

Konstantin Belousov <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.src
Message-ID <6a812498.45380.8d097ef__39739.19268917$1786848619$gmane$org@gitrepo.freebsd.org>
The branch stable/15 has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=61f4a89823b7db38c0e997a135522f1838bfdb86

commit 61f4a89823b7db38c0e997a135522f1838bfdb86
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2026-05-21 19:12:45 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2026-08-16 02:41:26 +0000

    kern: add pddupfd(2)
    
    (cherry picked from commit 1ad21a6521827473dc6692646e9c760a5b0521cd)
---
 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 b10b7f4f90bb..4fecd55fb5f1 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -3134,6 +3134,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,
@@ -3158,8 +3159,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 cc3cfa355133..71e8f6797d47 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>
@@ -705,3 +706,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 41abbdb88075..b4f02e04d9d4 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -3428,5 +3428,12 @@
 		    int flags
 		);
 	}
+604	AUE_NULL	STD {
+		int pddupfd(
+			int pd,
+			int fd,
+			int flags
+		);
+	}
 
 ; vim: syntax=off
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.