git: 5c32aa785184 - main - kern: add pdopenpid(2)
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 07 Jul 2026 01:57:17 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=5c32aa785184bb1e646b0b4c73d3c5fd9a6b8951
commit 5c32aa785184bb1e646b0b4c73d3c5fd9a6b8951
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-05-20 02:04:02 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
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.