git: a4993bac4135 - main - pseudofs: ensure that the target process vmspace is stable for VOP_READ/WRITE

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Sun, 21 Jun 2026 11:48:14 UTC
The branch main has been updated by kib:

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

commit a4993bac41350e85bc9affb862d2974a1a09bb5e
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-06-07 19:39:42 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-06-21 11:46:53 +0000

    pseudofs: ensure that the target process vmspace is stable for VOP_READ/WRITE
    
    Reviewed by:    markj
    Tested by:      pho
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D57497
---
 sys/fs/pseudofs/pseudofs_vnops.c | 59 ++++++++++++++++++++++++++++------------
 1 file changed, 41 insertions(+), 18 deletions(-)

diff --git a/sys/fs/pseudofs/pseudofs_vnops.c b/sys/fs/pseudofs/pseudofs_vnops.c
index d14ed15f3329..229f762914bc 100644
--- a/sys/fs/pseudofs/pseudofs_vnops.c
+++ b/sys/fs/pseudofs/pseudofs_vnops.c
@@ -676,6 +676,7 @@ pfs_read(struct vop_read_args *va)
 	struct pfs_node *pn = pvd->pvd_pn;
 	struct uio *uio = va->a_uio;
 	struct proc *proc;
+	struct thread *td;
 	struct sbuf *sb = NULL;
 	int error, locked;
 	off_t buflen, buflim;
@@ -694,21 +695,30 @@ pfs_read(struct vop_read_args *va)
 	if (pn->pn_fill == NULL)
 		PFS_RETURN (EIO);
 
+	td = curthread;
+
 	/*
 	 * This is necessary because either process' privileges may
 	 * have changed since the open() call.
 	 */
-	if (!pfs_visible(curthread, pn, pvd->pvd_pid, &proc))
+	if (!pfs_visible(td, pn, pvd->pvd_pid, &proc))
 		PFS_RETURN (EIO);
-	if (proc != NULL) {
-		_PHOLD(proc);
-		PROC_UNLOCK(proc);
-	}
 
 	vhold(vn);
 	locked = VOP_ISLOCKED(vn);
 	VOP_UNLOCK(vn);
 
+	if (proc != NULL) {
+		_PHOLD(proc);
+		execve_block_wait(td, proc);
+		if (!pfs_visible_proc(td, pn, proc)) {
+			PROC_UNLOCK(proc);
+			error = EIO;
+			goto ret;
+		}
+		PROC_UNLOCK(proc);
+	}
+
 	if (pn->pn_flags & PFS_RAWRD) {
 		PFS_TRACE(("%zd resid", uio->uio_resid));
 		error = pn_fill(curthread, proc, pn, NULL, uio);
@@ -778,8 +788,12 @@ pfs_read(struct vop_read_args *va)
 ret:
 	vn_lock(vn, locked | LK_RETRY);
 	vdrop(vn);
-	if (proc != NULL)
-		PRELE(proc);
+	if (proc != NULL) {
+		PROC_LOCK(proc);
+		execve_unblock(td, proc);
+		_PRELE(proc);
+		PROC_UNLOCK(proc);
+	}
 	PFS_RETURN (error);
 }
 
@@ -1087,6 +1101,7 @@ pfs_write(struct vop_write_args *va)
 	struct pfs_node *pn = pvd->pvd_pn;
 	struct uio *uio = va->a_uio;
 	struct proc *proc;
+	struct thread *td;
 	struct sbuf sb;
 	int error;
 
@@ -1106,36 +1121,44 @@ pfs_write(struct vop_write_args *va)
 	if (uio->uio_resid > PFS_MAXBUFSIZ)
 		PFS_RETURN (EIO);
 
+	td = curthread;
+
 	/*
 	 * This is necessary because either process' privileges may
 	 * have changed since the open() call.
 	 */
-	if (!pfs_visible(curthread, pn, pvd->pvd_pid, &proc))
+	if (!pfs_visible(td, pn, pvd->pvd_pid, &proc))
 		PFS_RETURN (EIO);
 	if (proc != NULL) {
 		_PHOLD(proc);
+		execve_block_wait(td, proc);
+		if (!pfs_visible_proc(td, pn, proc)) {
+			PROC_UNLOCK(proc);
+			error = EIO;
+			goto out;
+		}
 		PROC_UNLOCK(proc);
 	}
 
 	if (pn->pn_flags & PFS_RAWWR) {
 		error = pn_fill(curthread, proc, pn, NULL, uio);
-		if (proc != NULL)
-			PRELE(proc);
-		PFS_RETURN (error);
+		goto out;
 	}
 
 	sbuf_uionew(&sb, uio, &error);
-	if (error) {
-		if (proc != NULL)
-			PRELE(proc);
-		PFS_RETURN (error);
-	}
+	if (error != 0)
+		goto out;
 
 	error = pn_fill(curthread, proc, pn, &sb, uio);
 
 	sbuf_delete(&sb);
-	if (proc != NULL)
-		PRELE(proc);
+out:
+	if (proc != NULL) {
+		PROC_LOCK(proc);
+		execve_unblock(td, proc);
+		_PRELE(proc);
+		PROC_UNLOCK(proc);
+	}
 	PFS_RETURN (error);
 }