The branch main has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=5c32aa785184bb1e646b0b4c73d3c5fd9a6b8951

commit 5c32aa785184bb1e646b0b4c73d3c5fd9a6b8951
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2026-05-20 02:04:02 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2026-07-07 01:24:51 +0000

    kern: add pdopenpid(2)
    
    Reviewed by:    markj
    Tested by:      pho
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D57124
---
 sys/kern/sys_procdesc.c  | 114 ++++++++++++++++++++++++++++++++++++++++++-----
 sys/kern/syscalls.master |   7 +++
 sys/sys/procdesc.h       |   2 +
 3 files changed, 111 insertions(+), 12 deletions(-)

diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c
index 0d57a8cc7b2c..3fca3ea29b18 100644
--- a/sys/kern/sys_procdesc.c
+++ b/sys/kern/sys_procdesc.c
@@ -435,18 +435,22 @@ procdesc_close(struct file *fp, struct thread *td)
                        pd->pd_pid = -1;
                        procdesc_free(pd);
 
-                       /*
-                        * Next, reparent it to its reaper (usually init(8)) so
-                        * that there's someone to pick up the pieces; finally,
-                        * terminate with prejudice.
-                        */
-                       p->p_sigparent = SIGCHLD;
-                       if ((p->p_flag & P_TRACED) == 0) {
-                               proc_reparent(p, p->p_reaper, true);
-                       } else {
-                               proc_clear_orphan(p);
-                               p->p_oppid = p->p_reaper->p_pid;
-                               proc_add_orphan(p, p->p_reaper);
+                       /* Failed finstall() should not cause reaping. */
+                       if ((fp->f_pdflags & F_PD_NOFINSTALL) == 0) {
+                               /*
+                                * Next, reparent it to its reaper
+                                * (usually init(8)) so that there's
+                                * someone to pick up the pieces;
+                                * finally, terminate with prejudice.
+                                */
+                               p->p_sigparent = SIGCHLD;
+                               if ((p->p_flag & P_TRACED) == 0) {
+                                       proc_reparent(p, p->p_reaper, true);
+                               } else {
+                                       proc_clear_orphan(p);
+                                       p->p_oppid = p->p_reaper->p_pid;
+                                       proc_add_orphan(p, p->p_reaper);
+                               }
                        }
                        procdesc_close_tail(fp, p);
                } else {
@@ -609,3 +613,89 @@ procdesc_cmp(struct file *fp1, struct file *fp2, struct 
thread *td)
        pdp2 = fp2->f_data;
        return (kcmp_cmp((uintptr_t)pdp1->pd_pid, (uintptr_t)pdp2->pd_pid));
 }
+
+static int
+pdopenpid1(struct thread *td, pid_t pid, struct procdesc **pdf, struct file 
*fp)
+{
+       struct proc *p;
+       struct procdesc *pd;
+       int error;
+
+       sx_assert(&proctree_lock, SX_XLOCKED);
+
+       error = pget(pid, PGET_NOTID | PGET_CANDEBUG, &p);
+       if (error != 0)
+               return (error);
+       if ((p->p_flag & (P_SYSTEM | P_WEXIT)) != 0) {
+               PROC_UNLOCK(p);
+               return (EBUSY);
+       }
+       pd = p->p_procdesc;
+       if (pd != NULL) {
+               refcount_acquire(&pd->pd_refcount);
+               PROCDESC_LOCK(pd);
+               MPASS(pd->pd_fpcount > 0);
+               pd->pd_fpcount++;
+               PROCDESC_UNLOCK(pd);
+       } else {
+               pd = *pdf;
+               *pdf = NULL;
+               pd->pd_proc = p;
+               pd->pd_pid = p->p_pid;
+               p->p_procdesc = pd;
+       }
+       procdesc_finit(pd, fp);
+       PROC_UNLOCK(p);
+       return (0);
+}
+
+static int
+kern_pdopenpid(struct thread *td, pid_t pid, int flags)
+{
+       struct file *fp;
+       struct procdesc *pdf;
+       int error, fd, fflags;
+
+       error = falloc_noinstall(td, &fp);
+       if (error != 0)
+               return (error);
+       fflags = pdtofdflags(flags);
+       pdf = procdesc_alloc(flags);
+       if ((flags & PD_DAEMON) != 0)
+               fp->f_pdflags |= F_PD_NOKILL;
+
+       sx_xlock(&proctree_lock);
+       error = pdopenpid1(td, pid, &pdf, fp);
+       sx_xunlock(&proctree_lock);
+
+       if (error == 0) {
+               error = finstall(td, fp, &fd, fflags, NULL);
+               if (error == 0) {
+                       td->td_retval[0] = fd;
+               } else {
+                       /*
+                        * Not killing the target process if cannot
+                        * return file descriptor to userspace.
+                        */
+                       fp->f_pdflags |= F_PD_NOKILL | F_PD_NOFINSTALL;
+               }
+       }
+       fdrop(fp, td);
+
+       if (pdf != NULL) {
+               MPASS(pdf->pd_refcount == 2);
+               MPASS(pdf->pd_fpcount == 1);
+               MPASS(pdf->pd_proc == NULL);
+               MPASS(pdf->pd_pid == -1);
+               procdesc_destroy(pdf);
+       }
+       return (error);
+}
+
+int
+sys_pdopenpid(struct thread *td, struct pdopenpid_args *args)
+{
+       if ((args->flags & ~(PD_ALLOWED_AT_FORK)) != 0)
+               return (EINVAL);
+       return (kern_pdopenpid(td, args->pid, args->flags));
+}
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 1032f6cd1bf0..41580d0c4595 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -3429,4 +3429,11 @@
                    int flags
                );
        }
+603    AUE_NULL        STD {
+               int pdopenpid(
+                   pid_t pid,
+                   int flags
+               );
+       }
+
 ; vim: syntax=off
diff --git a/sys/sys/procdesc.h b/sys/sys/procdesc.h
index 5fbd43f1ac84..9eb64525e430 100644
--- a/sys/sys/procdesc.h
+++ b/sys/sys/procdesc.h
@@ -95,6 +95,8 @@ struct procdesc {
  */
 #define        F_PD_NOKILL     0x00000001      /* Opened with PD_DAEMON. Don't 
send
                                           SIGKILL when file closes. */
+#define        F_PD_NOFINSTALL 0x00000002      /* Procdesc file is closing 
because
+                                          finstall() failed */
 
 /*
  * In-kernel interfaces to process descriptors.

Reply via email to