Module Name:    src
Committed By:   martin
Date:           Thu Apr 18 18:22:10 UTC 2024

Modified Files:
        src/sys/kern [netbsd-10]: init_main.c kern_hook.c vfs_mount.c
        src/sys/miscfs/procfs [netbsd-10]: procfs.h procfs_subr.c
            procfs_vfsops.c procfs_vnops.c

Log Message:
Pull up following revision(s) (requested by hannken in ticket #668):

        sys/miscfs/procfs/procfs.h: revision 1.83
        sys/miscfs/procfs/procfs.h: revision 1.84
        sys/kern/vfs_mount.c: revision 1.104
        sys/miscfs/procfs/procfs_vnops.c: revision 1.230
        sys/kern/init_main.c: revision 1.547
        sys/kern/kern_hook.c: revision 1.15
        sys/miscfs/procfs/procfs_vfsops.c: revision 1.112
        sys/miscfs/procfs/procfs_vfsops.c: revision 1.113
        sys/miscfs/procfs/procfs_vfsops.c: revision 1.114
        sys/miscfs/procfs/procfs_subr.c: revision 1.117

Print dangling vnode before panic() to help debug.

PR kern/57775 ""panic: unmount: dangling vnode" while umounting procfs"
Protect kernel hooks exechook, exithook and forkhook with rwlock.

Lock as writer on establish/disestablish and as reader on list traverse.

For exechook ride "exec_lock" as it is already take as reader when
traversing the list.  Add local locks for exithook and forkhook.

Move exec_init before signal_init as signal_init calls exechook_establish()
that needs "exec_lock".

PR kern/39913 "exec, fork, exit hooks need locking"

Add a hashmap to access all procfs nodes by pid.

Using the exechook to revoke procfs nodes is racy and may deadlock:
one thread runs doexechooks() -> procfs_revoke_vnodes() and wants to suspend
the file system for vgone(), while another thread runs a forced unmount,
has the file system suspended, tries to disestablish the exechook and
waits for doexechooks() to complete.

Establish/disestablish the exechook on module load/unload instead
mount/unmount and use the hashmap to access all procfs nodes for this pid.

May fix PR kern/57775 ""panic: unmount: dangling vnode" while umounting procfs"

Remove all procfs nodes for this process on process exit.


To generate a diff of this commit:
cvs rdiff -u -r1.541 -r1.541.2.1 src/sys/kern/init_main.c
cvs rdiff -u -r1.14 -r1.14.2.1 src/sys/kern/kern_hook.c
cvs rdiff -u -r1.101 -r1.101.2.1 src/sys/kern/vfs_mount.c
cvs rdiff -u -r1.82 -r1.82.4.1 src/sys/miscfs/procfs/procfs.h
cvs rdiff -u -r1.116 -r1.116.20.1 src/sys/miscfs/procfs/procfs_subr.c
cvs rdiff -u -r1.111 -r1.111.4.1 src/sys/miscfs/procfs/procfs_vfsops.c
cvs rdiff -u -r1.229 -r1.229.4.1 src/sys/miscfs/procfs/procfs_vnops.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/init_main.c
diff -u src/sys/kern/init_main.c:1.541 src/sys/kern/init_main.c:1.541.2.1
--- src/sys/kern/init_main.c:1.541	Wed Oct 26 23:20:47 2022
+++ src/sys/kern/init_main.c	Thu Apr 18 18:22:10 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: init_main.c,v 1.541 2022/10/26 23:20:47 riastradh Exp $	*/
+/*	$NetBSD: init_main.c,v 1.541.2.1 2024/04/18 18:22:10 martin Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2009, 2019 The NetBSD Foundation, Inc.
@@ -97,7 +97,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.541 2022/10/26 23:20:47 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.541.2.1 2024/04/18 18:22:10 martin Exp $");
 
 #include "opt_cnmagic.h"
 #include "opt_ddb.h"
@@ -409,6 +409,9 @@ main(void)
 	/* Must be called after lwpinit (lwpinit_specificdata) */
 	psref_init();
 
+	/* Initialize exec structures */
+	exec_init(1);		/* signal_init calls exechook_establish() */
+
 	/* Initialize signal-related data structures. */
 	signal_init();
 
@@ -578,9 +581,6 @@ main(void)
 
 	vmem_rehash_start();	/* must be before exec_init */
 
-	/* Initialize exec structures */
-	exec_init(1);		/* seminit calls exithook_establish() */
-
 #if NVERIEXEC > 0
 	/*
 	 * Initialise the Veriexec subsystem.

Index: src/sys/kern/kern_hook.c
diff -u src/sys/kern/kern_hook.c:1.14 src/sys/kern/kern_hook.c:1.14.2.1
--- src/sys/kern/kern_hook.c:1.14	Wed Oct 26 23:21:06 2022
+++ src/sys/kern/kern_hook.c	Thu Apr 18 18:22:10 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_hook.c,v 1.14 2022/10/26 23:21:06 riastradh Exp $	*/
+/*	$NetBSD: kern_hook.c,v 1.14.2.1 2024/04/18 18:22:10 martin Exp $	*/
 
 /*-
  * Copyright (c) 1997, 1998, 1999, 2002, 2007, 2008 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_hook.c,v 1.14 2022/10/26 23:21:06 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_hook.c,v 1.14.2.1 2024/04/18 18:22:10 martin Exp $");
 
 #include <sys/param.h>
 
@@ -42,6 +42,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_hook.c,
 #include <sys/hook.h>
 #include <sys/kmem.h>
 #include <sys/malloc.h>
+#include <sys/once.h>
 #include <sys/rwlock.h>
 #include <sys/systm.h>
 
@@ -74,25 +75,48 @@ struct khook_list {
 
 int	powerhook_debug = 0;
 
+static ONCE_DECL(hook_control);
+static krwlock_t exithook_lock;
+static krwlock_t forkhook_lock;
+
+static int
+hook_init(void)
+{
+
+	rw_init(&exithook_lock);
+	rw_init(&forkhook_lock);
+
+	return 0;
+}
+
 static void *
-hook_establish(hook_list_t *list, void (*fn)(void *), void *arg)
+hook_establish(hook_list_t *list, krwlock_t *lock,
+    void (*fn)(void *), void *arg)
 {
 	struct hook_desc *hd;
 
-	hd = malloc(sizeof(*hd), M_DEVBUF, M_NOWAIT);
-	if (hd == NULL)
-		return (NULL);
+	RUN_ONCE(&hook_control, hook_init);
 
-	hd->hk_fn = fn;
-	hd->hk_arg = arg;
-	LIST_INSERT_HEAD(list, hd, hk_list);
+	hd = malloc(sizeof(*hd), M_DEVBUF, M_NOWAIT);
+	if (hd != NULL) {
+		if (lock)
+			rw_enter(lock, RW_WRITER);
+		hd->hk_fn = fn;
+		hd->hk_arg = arg;
+		LIST_INSERT_HEAD(list, hd, hk_list);
+		if (lock)
+			rw_exit(lock);
+	}
 
 	return (hd);
 }
 
 static void
-hook_disestablish(hook_list_t *list, void *vhook)
+hook_disestablish(hook_list_t *list, krwlock_t *lock, void *vhook)
 {
+
+	if (lock)
+		rw_enter(lock, RW_WRITER);
 #ifdef DIAGNOSTIC
 	struct hook_desc *hd;
 
@@ -106,6 +130,8 @@ hook_disestablish(hook_list_t *list, voi
 #endif
 	LIST_REMOVE((struct hook_desc *)vhook, hk_list);
 	free(vhook, M_DEVBUF);
+	if (lock)
+		rw_exit(lock);
 }
 
 static void
@@ -120,14 +146,20 @@ hook_destroy(hook_list_t *list)
 }
 
 static void
-hook_proc_run(hook_list_t *list, struct proc *p)
+hook_proc_run(hook_list_t *list, krwlock_t *lock, struct proc *p)
 {
 	struct hook_desc *hd;
 
+	RUN_ONCE(&hook_control, hook_init);
+
+	if (lock)
+		rw_enter(lock, RW_READER);
 	LIST_FOREACH(hd, list, hk_list) {
 		__FPTRCAST(void (*)(struct proc *, void *), *hd->hk_fn)(p,
 		    hd->hk_arg);
 	}
+	if (lock)
+		rw_exit(lock);
 }
 
 /*
@@ -146,13 +178,13 @@ static hook_list_t shutdownhook_list = L
 void *
 shutdownhook_establish(void (*fn)(void *), void *arg)
 {
-	return hook_establish(&shutdownhook_list, fn, arg);
+	return hook_establish(&shutdownhook_list, NULL, fn, arg);
 }
 
 void
 shutdownhook_disestablish(void *vhook)
 {
-	hook_disestablish(&shutdownhook_list, vhook);
+	hook_disestablish(&shutdownhook_list, NULL, vhook);
 }
 
 /*
@@ -193,14 +225,14 @@ static hook_list_t mountroothook_list=LI
 void *
 mountroothook_establish(void (*fn)(device_t), device_t dev)
 {
-	return hook_establish(&mountroothook_list, __FPTRCAST(void (*), fn),
-	    dev);
+	return hook_establish(&mountroothook_list, NULL,
+	    __FPTRCAST(void (*), fn), dev);
 }
 
 void
 mountroothook_disestablish(void *vhook)
 {
-	hook_disestablish(&mountroothook_list, vhook);
+	hook_disestablish(&mountroothook_list, NULL, vhook);
 }
 
 void
@@ -227,14 +259,14 @@ static hook_list_t exechook_list = LIST_
 void *
 exechook_establish(void (*fn)(struct proc *, void *), void *arg)
 {
-	return hook_establish(&exechook_list, __FPTRCAST(void (*)(void *), fn),
-	    arg);
+	return hook_establish(&exechook_list, &exec_lock,
+		__FPTRCAST(void (*)(void *), fn), arg);
 }
 
 void
 exechook_disestablish(void *vhook)
 {
-	hook_disestablish(&exechook_list, vhook);
+	hook_disestablish(&exechook_list, &exec_lock, vhook);
 }
 
 /*
@@ -243,7 +275,9 @@ exechook_disestablish(void *vhook)
 void
 doexechooks(struct proc *p)
 {
-	hook_proc_run(&exechook_list, p);
+	KASSERT(rw_lock_held(&exec_lock));
+
+	hook_proc_run(&exechook_list, NULL, p);
 }
 
 static hook_list_t exithook_list = LIST_HEAD_INITIALIZER(exithook_list);
@@ -251,22 +285,16 @@ static hook_list_t exithook_list = LIST_
 void *
 exithook_establish(void (*fn)(struct proc *, void *), void *arg)
 {
-	void *rv;
 
-	rw_enter(&exec_lock, RW_WRITER);
-	rv = hook_establish(&exithook_list, __FPTRCAST(void (*)(void *), fn),
-	    arg);
-	rw_exit(&exec_lock);
-	return rv;
+	return hook_establish(&exithook_list, &exithook_lock,
+	    __FPTRCAST(void (*)(void *), fn), arg);
 }
 
 void
 exithook_disestablish(void *vhook)
 {
 
-	rw_enter(&exec_lock, RW_WRITER);
-	hook_disestablish(&exithook_list, vhook);
-	rw_exit(&exec_lock);
+	hook_disestablish(&exithook_list, &exithook_lock, vhook);
 }
 
 /*
@@ -275,7 +303,7 @@ exithook_disestablish(void *vhook)
 void
 doexithooks(struct proc *p)
 {
-	hook_proc_run(&exithook_list, p);
+	hook_proc_run(&exithook_list, &exithook_lock, p);
 }
 
 static hook_list_t forkhook_list = LIST_HEAD_INITIALIZER(forkhook_list);
@@ -283,14 +311,14 @@ static hook_list_t forkhook_list = LIST_
 void *
 forkhook_establish(void (*fn)(struct proc *, struct proc *))
 {
-	return hook_establish(&forkhook_list, __FPTRCAST(void (*)(void *), fn),
-	    NULL);
+	return hook_establish(&forkhook_list, &forkhook_lock,
+	    __FPTRCAST(void (*)(void *), fn), NULL);
 }
 
 void
 forkhook_disestablish(void *vhook)
 {
-	hook_disestablish(&forkhook_list, vhook);
+	hook_disestablish(&forkhook_list, &forkhook_lock, vhook);
 }
 
 /*
@@ -301,10 +329,14 @@ doforkhooks(struct proc *p2, struct proc
 {
 	struct hook_desc *hd;
 
+	RUN_ONCE(&hook_control, hook_init);
+
+	rw_enter(&forkhook_lock, RW_READER);
 	LIST_FOREACH(hd, &forkhook_list, hk_list) {
 		__FPTRCAST(void (*)(struct proc *, struct proc *), *hd->hk_fn)
 		    (p2, p1);
 	}
+	rw_exit(&forkhook_lock);
 }
 
 static hook_list_t critpollhook_list = LIST_HEAD_INITIALIZER(critpollhook_list);
@@ -312,13 +344,13 @@ static hook_list_t critpollhook_list = L
 void *
 critpollhook_establish(void (*fn)(void *), void *arg)
 {
-	return hook_establish(&critpollhook_list, fn, arg);
+	return hook_establish(&critpollhook_list, NULL, fn, arg);
 }
 
 void
 critpollhook_disestablish(void *vhook)
 {
-	hook_disestablish(&critpollhook_list, vhook);
+	hook_disestablish(&critpollhook_list, NULL, vhook);
 }
 
 /*

Index: src/sys/kern/vfs_mount.c
diff -u src/sys/kern/vfs_mount.c:1.101 src/sys/kern/vfs_mount.c:1.101.2.1
--- src/sys/kern/vfs_mount.c:1.101	Fri Dec  9 10:33:18 2022
+++ src/sys/kern/vfs_mount.c	Thu Apr 18 18:22:10 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_mount.c,v 1.101 2022/12/09 10:33:18 hannken Exp $	*/
+/*	$NetBSD: vfs_mount.c,v 1.101.2.1 2024/04/18 18:22:10 martin Exp $	*/
 
 /*-
  * Copyright (c) 1997-2020 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.101 2022/12/09 10:33:18 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.101.2.1 2024/04/18 18:22:10 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -937,7 +937,7 @@ err_mounted:
 int
 dounmount(struct mount *mp, int flags, struct lwp *l)
 {
-	vnode_t *coveredvp;
+	vnode_t *coveredvp, *vp;
 	int error, async, used_syncer, used_extattr;
 	const bool was_suspended = fstrans_is_owner(mp);
 
@@ -1004,8 +1004,10 @@ dounmount(struct mount *mp, int flags, s
 		vfs_resume(mp);
 
 	mountlist_remove(mp);
-	if (TAILQ_FIRST(&mp->mnt_vnodelist) != NULL)
+	if ((vp = VIMPL_TO_VNODE(TAILQ_FIRST(&mp->mnt_vnodelist))) != NULL) {
+		vprint("dangling", vp);
 		panic("unmount: dangling vnode");
+	}
 	vfs_hooks_unmount(mp);
 
 	vfs_set_lowermount(mp, NULL);

Index: src/sys/miscfs/procfs/procfs.h
diff -u src/sys/miscfs/procfs/procfs.h:1.82 src/sys/miscfs/procfs/procfs.h:1.82.4.1
--- src/sys/miscfs/procfs/procfs.h:1.82	Wed Jan 19 10:23:00 2022
+++ src/sys/miscfs/procfs/procfs.h	Thu Apr 18 18:22:10 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: procfs.h,v 1.82 2022/01/19 10:23:00 martin Exp $	*/
+/*	$NetBSD: procfs.h,v 1.82.4.1 2024/04/18 18:22:10 martin Exp $	*/
 
 /*
  * Copyright (c) 1993
@@ -129,7 +129,9 @@ struct pfskey {
 	int		pk_fd;		/* associated fd if not -1 */
 };
 struct pfsnode {
+	LIST_ENTRY(pfsnode) pfs_hash;	/* per pid hash list */
 	struct vnode	*pfs_vnode;	/* vnode associated with this pfsnode */
+	struct mount	*pfs_mount;	/* mount associated with this pfsnode */
 	struct pfskey	pfs_key;
 #define pfs_type pfs_key.pk_type
 #define pfs_pid pfs_key.pk_pid
@@ -190,7 +192,6 @@ procfs_fileno(pid_t _pid, pfstype _type,
 #define PROCFS_TYPE(type)	((type) % PFSlast)
 
 struct procfsmount {
-	void *pmnt_exechook;
 	int pmnt_flags;
 };
 
@@ -269,7 +270,7 @@ int procfs_doauxv(struct lwp *, struct p
 int procfs_dolimit(struct lwp *, struct proc *, struct pfsnode *,
     struct uio *);
 
-void procfs_revoke_vnodes(struct proc *, void *);
+void procfs_hashrem(struct pfsnode *);
 int procfs_getfp(struct pfsnode *, struct proc *, struct file **);
 
 /* functions to check whether or not files should be displayed */

Index: src/sys/miscfs/procfs/procfs_subr.c
diff -u src/sys/miscfs/procfs/procfs_subr.c:1.116 src/sys/miscfs/procfs/procfs_subr.c:1.116.20.1
--- src/sys/miscfs/procfs/procfs_subr.c:1.116	Sat May 23 23:42:43 2020
+++ src/sys/miscfs/procfs/procfs_subr.c	Thu Apr 18 18:22:10 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: procfs_subr.c,v 1.116 2020/05/23 23:42:43 ad Exp $	*/
+/*	$NetBSD: procfs_subr.c,v 1.116.20.1 2024/04/18 18:22:10 martin Exp $	*/
 
 /*-
  * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -102,7 +102,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.116 2020/05/23 23:42:43 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.116.20.1 2024/04/18 18:22:10 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -358,57 +358,6 @@ vfs_findname(const vfs_namemap_t *nm, co
 	return (0);
 }
 
-static bool
-procfs_revoke_selector(void *arg, struct vnode *vp)
-{
-	struct proc *p = arg;
-	struct pfsnode *pfs;
-
-	KASSERT(mutex_owned(vp->v_interlock));
-
-	pfs = VTOPFS(vp);
-
-	return (pfs != NULL && pfs->pfs_pid == p->p_pid);
-}
-
-void
-procfs_revoke_vnodes(struct proc *p, void *arg)
-{
-	int error;
-	bool suspended;
-	struct vnode *vp;
-	struct vnode_iterator *marker;
-	struct mount *mp = (struct mount *)arg;
-
-	if (!(p->p_flag & PK_SUGID))
-		return;
-
-	suspended = false;
-	vfs_vnode_iterator_init(mp, &marker);
-
-	while ((vp = vfs_vnode_iterator_next(marker,
-	    procfs_revoke_selector, p)) != NULL) {
-		if (vrecycle(vp))
-			continue;
-		/* Vnode is busy, we have to suspend the mount for vgone(). */
-		while (! suspended) {
-			error = vfs_suspend(mp, 0);
-			if (error == 0) {
-				suspended = true;
-			} else if (error != EINTR && error != ERESTART) {
-				KASSERT(error == EOPNOTSUPP);
-				break;
-			}
-		}
-		vgone(vp);
-	}
-
-	if (suspended)
-		vfs_resume(mp);
-
-	vfs_vnode_iterator_destroy(marker);
-}
-
 bool
 procfs_use_linux_compat(struct mount *mp)
 {

Index: src/sys/miscfs/procfs/procfs_vfsops.c
diff -u src/sys/miscfs/procfs/procfs_vfsops.c:1.111 src/sys/miscfs/procfs/procfs_vfsops.c:1.111.4.1
--- src/sys/miscfs/procfs/procfs_vfsops.c:1.111	Mon Jan 17 11:20:00 2022
+++ src/sys/miscfs/procfs/procfs_vfsops.c	Thu Apr 18 18:22:10 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: procfs_vfsops.c,v 1.111 2022/01/17 11:20:00 bouyer Exp $	*/
+/*	$NetBSD: procfs_vfsops.c,v 1.111.4.1 2024/04/18 18:22:10 martin Exp $	*/
 
 /*
  * Copyright (c) 1993
@@ -76,7 +76,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: procfs_vfsops.c,v 1.111 2022/01/17 11:20:00 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: procfs_vfsops.c,v 1.111.4.1 2024/04/18 18:22:10 martin Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_compat_netbsd.h"
@@ -88,6 +88,7 @@ __KERNEL_RCSID(0, "$NetBSD: procfs_vfsop
 #include <sys/dirent.h>
 #include <sys/file.h>
 #include <sys/filedesc.h>
+#include <sys/fstrans.h>
 #include <sys/kauth.h>
 #include <sys/kernel.h>
 #include <sys/module.h>
@@ -110,7 +111,33 @@ MODULE(MODULE_CLASS_VFS, procfs, "ptrace
 
 VFS_PROTOS(procfs);
 
+#define PROCFS_HASHSIZE	256
+#define PROCFS_EXEC_HOOK ((void *)1)
+#define PROCFS_EXIT_HOOK ((void *)2)
+
 static kauth_listener_t procfs_listener;
+static void *procfs_exechook;
+static void *procfs_exithook;
+LIST_HEAD(hashhead, pfsnode);
+static u_long procfs_hashmask;
+static struct hashhead *procfs_hashtab;
+static kmutex_t procfs_hashlock;
+
+static struct hashhead *
+procfs_hashhead(pid_t pid)
+{
+
+	return &procfs_hashtab[pid & procfs_hashmask];
+}
+
+void
+procfs_hashrem(struct pfsnode *pfs)
+{
+
+	mutex_enter(&procfs_hashlock);
+	LIST_REMOVE(pfs, pfs_hash);
+	mutex_exit(&procfs_hashlock);
+}
 
 /*
  * VFS Operations.
@@ -166,7 +193,6 @@ procfs_mount(
 
 	error = set_statvfs_info(path, UIO_USERSPACE, "procfs", UIO_SYSSPACE,
 	    mp->mnt_op->vfs_name, mp, l);
-	pmnt->pmnt_exechook = exechook_establish(procfs_revoke_vnodes, mp);
 	if (*data_len >= sizeof *args)
 		pmnt->pmnt_flags = args->flags;
 	else
@@ -191,8 +217,6 @@ procfs_unmount(struct mount *mp, int mnt
 	if ((error = vflush(mp, 0, flags)) != 0)
 		return (error);
 
-	exechook_disestablish(VFSTOPROC(mp)->pmnt_exechook);
-
 	kmem_free(mp->mnt_data, sizeof(struct procfsmount));
 	mp->mnt_data = NULL;
 
@@ -279,6 +303,7 @@ procfs_loadvnode(struct mount *mp, struc
 	pfs->pfs_type = pfskey.pk_type;
 	pfs->pfs_fd = pfskey.pk_fd;
 	pfs->pfs_vnode = vp;
+	pfs->pfs_mount = mp;
 	pfs->pfs_flags = 0;
 	pfs->pfs_fileno =
 	    PROCFS_FILENO(pfs->pfs_pid, pfs->pfs_type, pfs->pfs_fd);
@@ -421,6 +446,10 @@ procfs_loadvnode(struct mount *mp, struc
 		panic("procfs_allocvp");
 	}
 
+	mutex_enter(&procfs_hashlock);
+	LIST_INSERT_HEAD(procfs_hashhead(pfs->pfs_pid), pfs, pfs_hash);
+	mutex_exit(&procfs_hashlock);
+
 	uvm_vnp_setsize(vp, 0);
 	*new_key = &pfs->pfs_key;
 
@@ -486,6 +515,48 @@ struct vfsops procfs_vfsops = {
 	.vfs_opv_descs = procfs_vnodeopv_descs
 };
 
+static void
+procfs_exechook_cb(struct proc *p, void *arg)
+{
+	struct hashhead *head;
+	struct pfsnode *pfs;
+	struct mount *mp;
+	struct pfskey key;
+	struct vnode *vp;
+	int error;
+
+	if (arg == PROCFS_EXEC_HOOK && !(p->p_flag & PK_SUGID))
+		return;
+
+	head = procfs_hashhead(p->p_pid);
+
+again:
+	mutex_enter(&procfs_hashlock);
+	LIST_FOREACH(pfs, head, pfs_hash) {
+		if (pfs->pfs_pid != p->p_pid)
+			continue;
+		mp = pfs->pfs_mount;
+		key = pfs->pfs_key;
+		vfs_ref(mp);
+		mutex_exit(&procfs_hashlock);
+
+		error = vcache_get(mp, &key, sizeof(key), &vp);
+		vfs_rele(mp);
+		if (error != 0)
+			goto again;
+		if (vrecycle(vp))
+			goto again;
+		do {
+			error = vfs_suspend(mp, 0);
+		} while (error == EINTR || error == ERESTART);
+		vgone(vp);
+		if (error == 0)
+			vfs_resume(mp);
+		goto again;
+	}
+	mutex_exit(&procfs_hashlock);
+}
+
 static int
 procfs_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
     void *arg0, void *arg1, void *arg2, void *arg3)
@@ -548,12 +619,25 @@ procfs_modcmd(modcmd_t cmd, void *arg)
 		procfs_listener = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
 		    procfs_listener_cb, NULL);
 
+		procfs_exechook = exechook_establish(procfs_exechook_cb,
+		    PROCFS_EXEC_HOOK);
+		procfs_exithook = exithook_establish(procfs_exechook_cb,
+		    PROCFS_EXIT_HOOK);
+
+		mutex_init(&procfs_hashlock, MUTEX_DEFAULT, IPL_NONE);
+		procfs_hashtab = hashinit(PROCFS_HASHSIZE, HASH_LIST, true,
+		    &procfs_hashmask);
+
 		break;
 	case MODULE_CMD_FINI:
 		error = vfs_detach(&procfs_vfsops);
 		if (error != 0)
 			break;
 		kauth_unlisten_scope(procfs_listener);
+		exechook_disestablish(procfs_exechook);
+		exithook_disestablish(procfs_exithook);
+		mutex_destroy(&procfs_hashlock);
+		hashdone(procfs_hashtab, HASH_LIST, procfs_hashmask);
 		break;
 	default:
 		error = ENOTTY;

Index: src/sys/miscfs/procfs/procfs_vnops.c
diff -u src/sys/miscfs/procfs/procfs_vnops.c:1.229 src/sys/miscfs/procfs/procfs_vnops.c:1.229.4.1
--- src/sys/miscfs/procfs/procfs_vnops.c:1.229	Fri Jun 17 14:30:37 2022
+++ src/sys/miscfs/procfs/procfs_vnops.c	Thu Apr 18 18:22:10 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: procfs_vnops.c,v 1.229 2022/06/17 14:30:37 shm Exp $	*/
+/*	$NetBSD: procfs_vnops.c,v 1.229.4.1 2024/04/18 18:22:10 martin Exp $	*/
 
 /*-
  * Copyright (c) 2006, 2007, 2008, 2020 The NetBSD Foundation, Inc.
@@ -105,7 +105,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.229 2022/06/17 14:30:37 shm Exp $");
+__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.229.4.1 2024/04/18 18:22:10 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -437,6 +437,7 @@ procfs_reclaim(void *v)
 	mutex_enter(vp->v_interlock);
 	vp->v_data = NULL;
 	mutex_exit(vp->v_interlock);
+	procfs_hashrem(pfs);
 	kmem_free(pfs, sizeof(*pfs));
 	return 0;
 }

Reply via email to