The branch main has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=1ad21a6521827473dc6692646e9c760a5b0521cd

commit 1ad21a6521827473dc6692646e9c760a5b0521cd
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2026-05-21 19:12:45 +0000
Commit:     Konstantin Belousov <[email protected]>
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

Reply via email to