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.diff -r1.541 -r1.541.2.1 src/sys/kern/init_main.c
(martin)
--- src/sys/kern/init_main.c 2022/10/26 23:20:47 1.541
+++ src/sys/kern/init_main.c 2024/04/18 18:22:10 1.541.2.1
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: init_main.c,v 1.541 2022/10/26 23:20:47 riastradh Exp $ */ | 1 | /* $NetBSD: init_main.c,v 1.541.2.1 2024/04/18 18:22:10 martin Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2008, 2009, 2019 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2008, 2009, 2019 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
@@ -87,27 +87,27 @@ | @@ -87,27 +87,27 @@ | |||
87 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 87 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
88 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 88 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
89 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 89 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
90 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 90 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
91 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 91 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
92 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 92 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
93 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 93 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
94 | * SUCH DAMAGE. | 94 | * SUCH DAMAGE. | |
95 | * | 95 | * | |
96 | * @(#)init_main.c 8.16 (Berkeley) 5/14/95 | 96 | * @(#)init_main.c 8.16 (Berkeley) 5/14/95 | |
97 | */ | 97 | */ | |
98 | 98 | |||
99 | #include <sys/cdefs.h> | 99 | #include <sys/cdefs.h> | |
100 | __KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.541 2022/10/26 23:20:47 riastradh Exp $"); | 100 | __KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.541.2.1 2024/04/18 18:22:10 martin Exp $"); | |
101 | 101 | |||
102 | #include "opt_cnmagic.h" | 102 | #include "opt_cnmagic.h" | |
103 | #include "opt_ddb.h" | 103 | #include "opt_ddb.h" | |
104 | #include "opt_inet.h" | 104 | #include "opt_inet.h" | |
105 | #include "opt_ipsec.h" | 105 | #include "opt_ipsec.h" | |
106 | #include "opt_modular.h" | 106 | #include "opt_modular.h" | |
107 | #include "opt_ntp.h" | 107 | #include "opt_ntp.h" | |
108 | #include "opt_pipe.h" | 108 | #include "opt_pipe.h" | |
109 | #include "opt_syscall_debug.h" | 109 | #include "opt_syscall_debug.h" | |
110 | #include "opt_sysv.h" | 110 | #include "opt_sysv.h" | |
111 | #include "opt_fileassoc.h" | 111 | #include "opt_fileassoc.h" | |
112 | #include "opt_ktrace.h" | 112 | #include "opt_ktrace.h" | |
113 | #include "opt_pax.h" | 113 | #include "opt_pax.h" | |
@@ -399,26 +399,29 @@ main(void) | @@ -399,26 +399,29 @@ main(void) | |||
399 | * The following things must be done before autoconfiguration. | 399 | * The following things must be done before autoconfiguration. | |
400 | */ | 400 | */ | |
401 | rnd_init(); /* initialize entropy pool */ | 401 | rnd_init(); /* initialize entropy pool */ | |
402 | 402 | |||
403 | cprng_init(); /* initialize cryptographic PRNG */ | 403 | cprng_init(); /* initialize cryptographic PRNG */ | |
404 | 404 | |||
405 | /* Initialize process and pgrp structures. */ | 405 | /* Initialize process and pgrp structures. */ | |
406 | procinit(); | 406 | procinit(); | |
407 | lwpinit(); | 407 | lwpinit(); | |
408 | 408 | |||
409 | /* Must be called after lwpinit (lwpinit_specificdata) */ | 409 | /* Must be called after lwpinit (lwpinit_specificdata) */ | |
410 | psref_init(); | 410 | psref_init(); | |
411 | 411 | |||
412 | /* Initialize exec structures */ | |||
413 | exec_init(1); /* signal_init calls exechook_establish() */ | |||
414 | ||||
412 | /* Initialize signal-related data structures. */ | 415 | /* Initialize signal-related data structures. */ | |
413 | signal_init(); | 416 | signal_init(); | |
414 | 417 | |||
415 | /* Initialize resource management. */ | 418 | /* Initialize resource management. */ | |
416 | resource_init(); | 419 | resource_init(); | |
417 | 420 | |||
418 | /* Create process 0. */ | 421 | /* Create process 0. */ | |
419 | proc0_init(); | 422 | proc0_init(); | |
420 | lwp0_init(); | 423 | lwp0_init(); | |
421 | 424 | |||
422 | /* Disable preemption during boot. */ | 425 | /* Disable preemption during boot. */ | |
423 | kpreempt_disable(); | 426 | kpreempt_disable(); | |
424 | 427 | |||
@@ -568,29 +571,26 @@ main(void) | @@ -568,29 +571,26 @@ main(void) | |||
568 | /* Initialize the rest of ipi(9) after CPUs have been detected. */ | 571 | /* Initialize the rest of ipi(9) after CPUs have been detected. */ | |
569 | ipi_percpu_init(); | 572 | ipi_percpu_init(); | |
570 | 573 | |||
571 | futex_sys_init(); | 574 | futex_sys_init(); | |
572 | 575 | |||
573 | /* Now timer is working. Enable preemption. */ | 576 | /* Now timer is working. Enable preemption. */ | |
574 | kpreempt_enable(); | 577 | kpreempt_enable(); | |
575 | 578 | |||
576 | /* Get the threads going and into any sleeps before continuing. */ | 579 | /* Get the threads going and into any sleeps before continuing. */ | |
577 | yield(); | 580 | yield(); | |
578 | 581 | |||
579 | vmem_rehash_start(); /* must be before exec_init */ | 582 | vmem_rehash_start(); /* must be before exec_init */ | |
580 | 583 | |||
581 | /* Initialize exec structures */ | |||
582 | exec_init(1); /* seminit calls exithook_establish() */ | |||
583 | ||||
584 | #if NVERIEXEC > 0 | 584 | #if NVERIEXEC > 0 | |
585 | /* | 585 | /* | |
586 | * Initialise the Veriexec subsystem. | 586 | * Initialise the Veriexec subsystem. | |
587 | */ | 587 | */ | |
588 | veriexec_init(); | 588 | veriexec_init(); | |
589 | #endif /* NVERIEXEC > 0 */ | 589 | #endif /* NVERIEXEC > 0 */ | |
590 | 590 | |||
591 | pax_init(); | 591 | pax_init(); | |
592 | 592 | |||
593 | #ifdef IPSEC | 593 | #ifdef IPSEC | |
594 | /* Attach network crypto subsystem */ | 594 | /* Attach network crypto subsystem */ | |
595 | ipsec_attach(); | 595 | ipsec_attach(); | |
596 | #endif | 596 | #endif |
--- src/sys/kern/kern_hook.c 2022/10/26 23:21:06 1.14
+++ src/sys/kern/kern_hook.c 2024/04/18 18:22:10 1.14.2.1
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: kern_hook.c,v 1.14 2022/10/26 23:21:06 riastradh Exp $ */ | 1 | /* $NetBSD: kern_hook.c,v 1.14.2.1 2024/04/18 18:22:10 martin Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1997, 1998, 1999, 2002, 2007, 2008 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1997, 1998, 1999, 2002, 2007, 2008 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | 8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | |
9 | * NASA Ames Research Center, and by Luke Mewburn. | 9 | * NASA Ames Research Center, and by Luke Mewburn. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
@@ -21,37 +21,38 @@ | @@ -21,37 +21,38 @@ | |||
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
30 | * POSSIBILITY OF SUCH DAMAGE. | 30 | * POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | #include <sys/cdefs.h> | 33 | #include <sys/cdefs.h> | |
34 | __KERNEL_RCSID(0, "$NetBSD: kern_hook.c,v 1.14 2022/10/26 23:21:06 riastradh Exp $"); | 34 | __KERNEL_RCSID(0, "$NetBSD: kern_hook.c,v 1.14.2.1 2024/04/18 18:22:10 martin Exp $"); | |
35 | 35 | |||
36 | #include <sys/param.h> | 36 | #include <sys/param.h> | |
37 | 37 | |||
38 | #include <sys/condvar.h> | 38 | #include <sys/condvar.h> | |
39 | #include <sys/cpu.h> | 39 | #include <sys/cpu.h> | |
40 | #include <sys/device.h> | 40 | #include <sys/device.h> | |
41 | #include <sys/exec.h> | 41 | #include <sys/exec.h> | |
42 | #include <sys/hook.h> | 42 | #include <sys/hook.h> | |
43 | #include <sys/kmem.h> | 43 | #include <sys/kmem.h> | |
44 | #include <sys/malloc.h> | 44 | #include <sys/malloc.h> | |
45 | #include <sys/once.h> | |||
45 | #include <sys/rwlock.h> | 46 | #include <sys/rwlock.h> | |
46 | #include <sys/systm.h> | 47 | #include <sys/systm.h> | |
47 | 48 | |||
48 | /* | 49 | /* | |
49 | * A generic linear hook. | 50 | * A generic linear hook. | |
50 | */ | 51 | */ | |
51 | struct hook_desc { | 52 | struct hook_desc { | |
52 | LIST_ENTRY(hook_desc) hk_list; | 53 | LIST_ENTRY(hook_desc) hk_list; | |
53 | void (*hk_fn)(void *); | 54 | void (*hk_fn)(void *); | |
54 | void *hk_arg; | 55 | void *hk_arg; | |
55 | }; | 56 | }; | |
56 | typedef LIST_HEAD(, hook_desc) hook_list_t; | 57 | typedef LIST_HEAD(, hook_desc) hook_list_t; | |
57 | 58 | |||
@@ -64,105 +65,136 @@ struct khook_list { | @@ -64,105 +65,136 @@ struct khook_list { | |||
64 | hook_list_t hl_list; | 65 | hook_list_t hl_list; | |
65 | kmutex_t hl_lock; | 66 | kmutex_t hl_lock; | |
66 | kmutex_t *hl_cvlock; | 67 | kmutex_t *hl_cvlock; | |
67 | struct lwp *hl_lwp; | 68 | struct lwp *hl_lwp; | |
68 | kcondvar_t hl_cv; | 69 | kcondvar_t hl_cv; | |
69 | enum hook_list_st | 70 | enum hook_list_st | |
70 | hl_state; | 71 | hl_state; | |
71 | khook_t *hl_active_hk; | 72 | khook_t *hl_active_hk; | |
72 | char hl_namebuf[HOOKNAMSIZ]; | 73 | char hl_namebuf[HOOKNAMSIZ]; | |
73 | }; | 74 | }; | |
74 | 75 | |||
75 | int powerhook_debug = 0; | 76 | int powerhook_debug = 0; | |
76 | 77 | |||
78 | static ONCE_DECL(hook_control); | |||
79 | static krwlock_t exithook_lock; | |||
80 | static krwlock_t forkhook_lock; | |||
81 | ||||
82 | static int | |||
83 | hook_init(void) | |||
84 | { | |||
85 | ||||
86 | rw_init(&exithook_lock); | |||
87 | rw_init(&forkhook_lock); | |||
88 | ||||
89 | return 0; | |||
90 | } | |||
91 | ||||
77 | static void * | 92 | static void * | |
78 | hook_establish(hook_list_t *list, void (*fn)(void *), void *arg) | 93 | hook_establish(hook_list_t *list, krwlock_t *lock, | |
94 | void (*fn)(void *), void *arg) | |||
79 | { | 95 | { | |
80 | struct hook_desc *hd; | 96 | struct hook_desc *hd; | |
81 | 97 | |||
82 | hd = malloc(sizeof(*hd), M_DEVBUF, M_NOWAIT); | 98 | RUN_ONCE(&hook_control, hook_init); | |
83 | if (hd == NULL) | |||
84 | return (NULL); | |||
85 | 99 | |||
86 | hd->hk_fn = fn; | 100 | hd = malloc(sizeof(*hd), M_DEVBUF, M_NOWAIT); | |
87 | hd->hk_arg = arg; | 101 | if (hd != NULL) { | |
88 | LIST_INSERT_HEAD(list, hd, hk_list); | 102 | if (lock) | |
103 | rw_enter(lock, RW_WRITER); | |||
104 | hd->hk_fn = fn; | |||
105 | hd->hk_arg = arg; | |||
106 | LIST_INSERT_HEAD(list, hd, hk_list); | |||
107 | if (lock) | |||
108 | rw_exit(lock); | |||
109 | } | |||
89 | 110 | |||
90 | return (hd); | 111 | return (hd); | |
91 | } | 112 | } | |
92 | 113 | |||
93 | static void | 114 | static void | |
94 | hook_disestablish(hook_list_t *list, void *vhook) | 115 | hook_disestablish(hook_list_t *list, krwlock_t *lock, void *vhook) | |
95 | { | 116 | { | |
117 | ||||
118 | if (lock) | |||
119 | rw_enter(lock, RW_WRITER); | |||
96 | #ifdef DIAGNOSTIC | 120 | #ifdef DIAGNOSTIC | |
97 | struct hook_desc *hd; | 121 | struct hook_desc *hd; | |
98 | 122 | |||
99 | LIST_FOREACH(hd, list, hk_list) { | 123 | LIST_FOREACH(hd, list, hk_list) { | |
100 | if (hd == vhook) | 124 | if (hd == vhook) | |
101 | break; | 125 | break; | |
102 | } | 126 | } | |
103 | 127 | |||
104 | if (hd == NULL) | 128 | if (hd == NULL) | |
105 | panic("hook_disestablish: hook %p not established", vhook); | 129 | panic("hook_disestablish: hook %p not established", vhook); | |
106 | #endif | 130 | #endif | |
107 | LIST_REMOVE((struct hook_desc *)vhook, hk_list); | 131 | LIST_REMOVE((struct hook_desc *)vhook, hk_list); | |
108 | free(vhook, M_DEVBUF); | 132 | free(vhook, M_DEVBUF); | |
133 | if (lock) | |||
134 | rw_exit(lock); | |||
109 | } | 135 | } | |
110 | 136 | |||
111 | static void | 137 | static void | |
112 | hook_destroy(hook_list_t *list) | 138 | hook_destroy(hook_list_t *list) | |
113 | { | 139 | { | |
114 | struct hook_desc *hd; | 140 | struct hook_desc *hd; | |
115 | 141 | |||
116 | while ((hd = LIST_FIRST(list)) != NULL) { | 142 | while ((hd = LIST_FIRST(list)) != NULL) { | |
117 | LIST_REMOVE(hd, hk_list); | 143 | LIST_REMOVE(hd, hk_list); | |
118 | free(hd, M_DEVBUF); | 144 | free(hd, M_DEVBUF); | |
119 | } | 145 | } | |
120 | } | 146 | } | |
121 | 147 | |||
122 | static void | 148 | static void | |
123 | hook_proc_run(hook_list_t *list, struct proc *p) | 149 | hook_proc_run(hook_list_t *list, krwlock_t *lock, struct proc *p) | |
124 | { | 150 | { | |
125 | struct hook_desc *hd; | 151 | struct hook_desc *hd; | |
126 | 152 | |||
153 | RUN_ONCE(&hook_control, hook_init); | |||
154 | ||||
155 | if (lock) | |||
156 | rw_enter(lock, RW_READER); | |||
127 | LIST_FOREACH(hd, list, hk_list) { | 157 | LIST_FOREACH(hd, list, hk_list) { | |
128 | __FPTRCAST(void (*)(struct proc *, void *), *hd->hk_fn)(p, | 158 | __FPTRCAST(void (*)(struct proc *, void *), *hd->hk_fn)(p, | |
129 | hd->hk_arg); | 159 | hd->hk_arg); | |
130 | } | 160 | } | |
161 | if (lock) | |||
162 | rw_exit(lock); | |||
131 | } | 163 | } | |
132 | 164 | |||
133 | /* | 165 | /* | |
134 | * "Shutdown hook" types, functions, and variables. | 166 | * "Shutdown hook" types, functions, and variables. | |
135 | * | 167 | * | |
136 | * Should be invoked immediately before the | 168 | * Should be invoked immediately before the | |
137 | * system is halted or rebooted, i.e. after file systems unmounted, | 169 | * system is halted or rebooted, i.e. after file systems unmounted, | |
138 | * after crash dump done, etc. | 170 | * after crash dump done, etc. | |
139 | * | 171 | * | |
140 | * Each shutdown hook is removed from the list before it's run, so that | 172 | * Each shutdown hook is removed from the list before it's run, so that | |
141 | * it won't be run again. | 173 | * it won't be run again. | |
142 | */ | 174 | */ | |
143 | 175 | |||
144 | static hook_list_t shutdownhook_list = LIST_HEAD_INITIALIZER(shutdownhook_list); | 176 | static hook_list_t shutdownhook_list = LIST_HEAD_INITIALIZER(shutdownhook_list); | |
145 | 177 | |||
146 | void * | 178 | void * | |
147 | shutdownhook_establish(void (*fn)(void *), void *arg) | 179 | shutdownhook_establish(void (*fn)(void *), void *arg) | |
148 | { | 180 | { | |
149 | return hook_establish(&shutdownhook_list, fn, arg); | 181 | return hook_establish(&shutdownhook_list, NULL, fn, arg); | |
150 | } | 182 | } | |
151 | 183 | |||
152 | void | 184 | void | |
153 | shutdownhook_disestablish(void *vhook) | 185 | shutdownhook_disestablish(void *vhook) | |
154 | { | 186 | { | |
155 | hook_disestablish(&shutdownhook_list, vhook); | 187 | hook_disestablish(&shutdownhook_list, NULL, vhook); | |
156 | } | 188 | } | |
157 | 189 | |||
158 | /* | 190 | /* | |
159 | * Run shutdown hooks. Should be invoked immediately before the | 191 | * Run shutdown hooks. Should be invoked immediately before the | |
160 | * system is halted or rebooted, i.e. after file systems unmounted, | 192 | * system is halted or rebooted, i.e. after file systems unmounted, | |
161 | * after crash dump done, etc. | 193 | * after crash dump done, etc. | |
162 | * | 194 | * | |
163 | * Each shutdown hook is removed from the list before it's run, so that | 195 | * Each shutdown hook is removed from the list before it's run, so that | |
164 | * it won't be run again. | 196 | * it won't be run again. | |
165 | */ | 197 | */ | |
166 | void | 198 | void | |
167 | doshutdownhooks(void) | 199 | doshutdownhooks(void) | |
168 | { | 200 | { | |
@@ -183,152 +215,152 @@ doshutdownhooks(void) | @@ -183,152 +215,152 @@ doshutdownhooks(void) | |||
183 | #endif | 215 | #endif | |
184 | } | 216 | } | |
185 | } | 217 | } | |
186 | 218 | |||
187 | /* | 219 | /* | |
188 | * "Mountroot hook" types, functions, and variables. | 220 | * "Mountroot hook" types, functions, and variables. | |
189 | */ | 221 | */ | |
190 | 222 | |||
191 | static hook_list_t mountroothook_list=LIST_HEAD_INITIALIZER(mountroothook_list); | 223 | static hook_list_t mountroothook_list=LIST_HEAD_INITIALIZER(mountroothook_list); | |
192 | 224 | |||
193 | void * | 225 | void * | |
194 | mountroothook_establish(void (*fn)(device_t), device_t dev) | 226 | mountroothook_establish(void (*fn)(device_t), device_t dev) | |
195 | { | 227 | { | |
196 | return hook_establish(&mountroothook_list, __FPTRCAST(void (*), fn), | 228 | return hook_establish(&mountroothook_list, NULL, | |
197 | dev); | 229 | __FPTRCAST(void (*), fn), dev); | |
198 | } | 230 | } | |
199 | 231 | |||
200 | void | 232 | void | |
201 | mountroothook_disestablish(void *vhook) | 233 | mountroothook_disestablish(void *vhook) | |
202 | { | 234 | { | |
203 | hook_disestablish(&mountroothook_list, vhook); | 235 | hook_disestablish(&mountroothook_list, NULL, vhook); | |
204 | } | 236 | } | |
205 | 237 | |||
206 | void | 238 | void | |
207 | mountroothook_destroy(void) | 239 | mountroothook_destroy(void) | |
208 | { | 240 | { | |
209 | hook_destroy(&mountroothook_list); | 241 | hook_destroy(&mountroothook_list); | |
210 | } | 242 | } | |
211 | 243 | |||
212 | void | 244 | void | |
213 | domountroothook(device_t therootdev) | 245 | domountroothook(device_t therootdev) | |
214 | { | 246 | { | |
215 | struct hook_desc *hd; | 247 | struct hook_desc *hd; | |
216 | 248 | |||
217 | LIST_FOREACH(hd, &mountroothook_list, hk_list) { | 249 | LIST_FOREACH(hd, &mountroothook_list, hk_list) { | |
218 | if (hd->hk_arg == therootdev) { | 250 | if (hd->hk_arg == therootdev) { | |
219 | (*hd->hk_fn)(hd->hk_arg); | 251 | (*hd->hk_fn)(hd->hk_arg); | |
220 | return; | 252 | return; | |
221 | } | 253 | } | |
222 | } | 254 | } | |
223 | } | 255 | } | |
224 | 256 | |||
225 | static hook_list_t exechook_list = LIST_HEAD_INITIALIZER(exechook_list); | 257 | static hook_list_t exechook_list = LIST_HEAD_INITIALIZER(exechook_list); | |
226 | 258 | |||
227 | void * | 259 | void * | |
228 | exechook_establish(void (*fn)(struct proc *, void *), void *arg) | 260 | exechook_establish(void (*fn)(struct proc *, void *), void *arg) | |
229 | { | 261 | { | |
230 | return hook_establish(&exechook_list, __FPTRCAST(void (*)(void *), fn), | 262 | return hook_establish(&exechook_list, &exec_lock, | |
231 | arg); | 263 | __FPTRCAST(void (*)(void *), fn), arg); | |
232 | } | 264 | } | |
233 | 265 | |||
234 | void | 266 | void | |
235 | exechook_disestablish(void *vhook) | 267 | exechook_disestablish(void *vhook) | |
236 | { | 268 | { | |
237 | hook_disestablish(&exechook_list, vhook); | 269 | hook_disestablish(&exechook_list, &exec_lock, vhook); | |
238 | } | 270 | } | |
239 | 271 | |||
240 | /* | 272 | /* | |
241 | * Run exec hooks. | 273 | * Run exec hooks. | |
242 | */ | 274 | */ | |
243 | void | 275 | void | |
244 | doexechooks(struct proc *p) | 276 | doexechooks(struct proc *p) | |
245 | { | 277 | { | |
246 | hook_proc_run(&exechook_list, p); | 278 | KASSERT(rw_lock_held(&exec_lock)); | |
279 | ||||
280 | hook_proc_run(&exechook_list, NULL, p); | |||
247 | } | 281 | } | |
248 | 282 | |||
249 | static hook_list_t exithook_list = LIST_HEAD_INITIALIZER(exithook_list); | 283 | static hook_list_t exithook_list = LIST_HEAD_INITIALIZER(exithook_list); | |
250 | 284 | |||
251 | void * | 285 | void * | |
252 | exithook_establish(void (*fn)(struct proc *, void *), void *arg) | 286 | exithook_establish(void (*fn)(struct proc *, void *), void *arg) | |
253 | { | 287 | { | |
254 | void *rv; | |||
255 | 288 | |||
256 | rw_enter(&exec_lock, RW_WRITER); | 289 | return hook_establish(&exithook_list, &exithook_lock, | |
257 | rv = hook_establish(&exithook_list, __FPTRCAST(void (*)(void *), fn), | 290 | __FPTRCAST(void (*)(void *), fn), arg); | |
258 | arg); | |||
259 | rw_exit(&exec_lock); | |||
260 | return rv; | |||
261 | } | 291 | } | |
262 | 292 | |||
263 | void | 293 | void | |
264 | exithook_disestablish(void *vhook) | 294 | exithook_disestablish(void *vhook) | |
265 | { | 295 | { | |
266 | 296 | |||
267 | rw_enter(&exec_lock, RW_WRITER); | 297 | hook_disestablish(&exithook_list, &exithook_lock, vhook); | |
268 | hook_disestablish(&exithook_list, vhook); | |||
269 | rw_exit(&exec_lock); | |||
270 | } | 298 | } | |
271 | 299 | |||
272 | /* | 300 | /* | |
273 | * Run exit hooks. | 301 | * Run exit hooks. | |
274 | */ | 302 | */ | |
275 | void | 303 | void | |
276 | doexithooks(struct proc *p) | 304 | doexithooks(struct proc *p) | |
277 | { | 305 | { | |
278 | hook_proc_run(&exithook_list, p); | 306 | hook_proc_run(&exithook_list, &exithook_lock, p); | |
279 | } | 307 | } | |
280 | 308 | |||
281 | static hook_list_t forkhook_list = LIST_HEAD_INITIALIZER(forkhook_list); | 309 | static hook_list_t forkhook_list = LIST_HEAD_INITIALIZER(forkhook_list); | |
282 | 310 | |||
283 | void * | 311 | void * | |
284 | forkhook_establish(void (*fn)(struct proc *, struct proc *)) | 312 | forkhook_establish(void (*fn)(struct proc *, struct proc *)) | |
285 | { | 313 | { | |
286 | return hook_establish(&forkhook_list, __FPTRCAST(void (*)(void *), fn), | 314 | return hook_establish(&forkhook_list, &forkhook_lock, | |
287 | NULL); | 315 | __FPTRCAST(void (*)(void *), fn), NULL); | |
288 | } | 316 | } | |
289 | 317 | |||
290 | void | 318 | void | |
291 | forkhook_disestablish(void *vhook) | 319 | forkhook_disestablish(void *vhook) | |
292 | { | 320 | { | |
293 | hook_disestablish(&forkhook_list, vhook); | 321 | hook_disestablish(&forkhook_list, &forkhook_lock, vhook); | |
294 | } | 322 | } | |
295 | 323 | |||
296 | /* | 324 | /* | |
297 | * Run fork hooks. | 325 | * Run fork hooks. | |
298 | */ | 326 | */ | |
299 | void | 327 | void | |
300 | doforkhooks(struct proc *p2, struct proc *p1) | 328 | doforkhooks(struct proc *p2, struct proc *p1) | |
301 | { | 329 | { | |
302 | struct hook_desc *hd; | 330 | struct hook_desc *hd; | |
303 | 331 | |||
332 | RUN_ONCE(&hook_control, hook_init); | |||
333 | ||||
334 | rw_enter(&forkhook_lock, RW_READER); | |||
304 | LIST_FOREACH(hd, &forkhook_list, hk_list) { | 335 | LIST_FOREACH(hd, &forkhook_list, hk_list) { | |
305 | __FPTRCAST(void (*)(struct proc *, struct proc *), *hd->hk_fn) | 336 | __FPTRCAST(void (*)(struct proc *, struct proc *), *hd->hk_fn) | |
306 | (p2, p1); | 337 | (p2, p1); | |
307 | } | 338 | } | |
339 | rw_exit(&forkhook_lock); | |||
308 | } | 340 | } | |
309 | 341 | |||
310 | static hook_list_t critpollhook_list = LIST_HEAD_INITIALIZER(critpollhook_list); | 342 | static hook_list_t critpollhook_list = LIST_HEAD_INITIALIZER(critpollhook_list); | |
311 | 343 | |||
312 | void * | 344 | void * | |
313 | critpollhook_establish(void (*fn)(void *), void *arg) | 345 | critpollhook_establish(void (*fn)(void *), void *arg) | |
314 | { | 346 | { | |
315 | return hook_establish(&critpollhook_list, fn, arg); | 347 | return hook_establish(&critpollhook_list, NULL, fn, arg); | |
316 | } | 348 | } | |
317 | 349 | |||
318 | void | 350 | void | |
319 | critpollhook_disestablish(void *vhook) | 351 | critpollhook_disestablish(void *vhook) | |
320 | { | 352 | { | |
321 | hook_disestablish(&critpollhook_list, vhook); | 353 | hook_disestablish(&critpollhook_list, NULL, vhook); | |
322 | } | 354 | } | |
323 | 355 | |||
324 | /* | 356 | /* | |
325 | * Run critical polling hooks. | 357 | * Run critical polling hooks. | |
326 | */ | 358 | */ | |
327 | void | 359 | void | |
328 | docritpollhooks(void) | 360 | docritpollhooks(void) | |
329 | { | 361 | { | |
330 | struct hook_desc *hd; | 362 | struct hook_desc *hd; | |
331 | 363 | |||
332 | LIST_FOREACH(hd, &critpollhook_list, hk_list) { | 364 | LIST_FOREACH(hd, &critpollhook_list, hk_list) { | |
333 | (*hd->hk_fn)(hd->hk_arg); | 365 | (*hd->hk_fn)(hd->hk_arg); | |
334 | } | 366 | } |
--- src/sys/kern/vfs_mount.c 2022/12/09 10:33:18 1.101
+++ src/sys/kern/vfs_mount.c 2024/04/18 18:22:10 1.101.2.1
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: vfs_mount.c,v 1.101 2022/12/09 10:33:18 hannken Exp $ */ | 1 | /* $NetBSD: vfs_mount.c,v 1.101.2.1 2024/04/18 18:22:10 martin Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1997-2020 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1997-2020 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | 8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | |
9 | * NASA Ames Research Center, by Charles M. Hannum, and by Andrew Doran. | 9 | * NASA Ames Research Center, by Charles M. Hannum, and by Andrew Doran. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
@@ -57,27 +57,27 @@ | @@ -57,27 +57,27 @@ | |||
57 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 57 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
58 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 58 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
59 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 59 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
60 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 60 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
61 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 61 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
62 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 62 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
63 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 63 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
64 | * SUCH DAMAGE. | 64 | * SUCH DAMAGE. | |
65 | * | 65 | * | |
66 | * @(#)vfs_subr.c 8.13 (Berkeley) 4/18/94 | 66 | * @(#)vfs_subr.c 8.13 (Berkeley) 4/18/94 | |
67 | */ | 67 | */ | |
68 | 68 | |||
69 | #include <sys/cdefs.h> | 69 | #include <sys/cdefs.h> | |
70 | __KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.101 2022/12/09 10:33:18 hannken Exp $"); | 70 | __KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.101.2.1 2024/04/18 18:22:10 martin Exp $"); | |
71 | 71 | |||
72 | #include <sys/param.h> | 72 | #include <sys/param.h> | |
73 | #include <sys/kernel.h> | 73 | #include <sys/kernel.h> | |
74 | 74 | |||
75 | #include <sys/atomic.h> | 75 | #include <sys/atomic.h> | |
76 | #include <sys/buf.h> | 76 | #include <sys/buf.h> | |
77 | #include <sys/conf.h> | 77 | #include <sys/conf.h> | |
78 | #include <sys/fcntl.h> | 78 | #include <sys/fcntl.h> | |
79 | #include <sys/filedesc.h> | 79 | #include <sys/filedesc.h> | |
80 | #include <sys/device.h> | 80 | #include <sys/device.h> | |
81 | #include <sys/kauth.h> | 81 | #include <sys/kauth.h> | |
82 | #include <sys/kmem.h> | 82 | #include <sys/kmem.h> | |
83 | #include <sys/module.h> | 83 | #include <sys/module.h> | |
@@ -927,27 +927,27 @@ err_mounted: | @@ -927,27 +927,27 @@ err_mounted: | |||
927 | 927 | |||
928 | return error; | 928 | return error; | |
929 | } | 929 | } | |
930 | 930 | |||
931 | /* | 931 | /* | |
932 | * Do the actual file system unmount. File system is assumed to have | 932 | * Do the actual file system unmount. File system is assumed to have | |
933 | * been locked by the caller. | 933 | * been locked by the caller. | |
934 | * | 934 | * | |
935 | * => Caller hold reference to the mount, explicitly for dounmount(). | 935 | * => Caller hold reference to the mount, explicitly for dounmount(). | |
936 | */ | 936 | */ | |
937 | int | 937 | int | |
938 | dounmount(struct mount *mp, int flags, struct lwp *l) | 938 | dounmount(struct mount *mp, int flags, struct lwp *l) | |
939 | { | 939 | { | |
940 | vnode_t *coveredvp; | 940 | vnode_t *coveredvp, *vp; | |
941 | int error, async, used_syncer, used_extattr; | 941 | int error, async, used_syncer, used_extattr; | |
942 | const bool was_suspended = fstrans_is_owner(mp); | 942 | const bool was_suspended = fstrans_is_owner(mp); | |
943 | 943 | |||
944 | #if NVERIEXEC > 0 | 944 | #if NVERIEXEC > 0 | |
945 | error = veriexec_unmountchk(mp); | 945 | error = veriexec_unmountchk(mp); | |
946 | if (error) | 946 | if (error) | |
947 | return (error); | 947 | return (error); | |
948 | #endif /* NVERIEXEC > 0 */ | 948 | #endif /* NVERIEXEC > 0 */ | |
949 | 949 | |||
950 | if (!was_suspended) { | 950 | if (!was_suspended) { | |
951 | error = vfs_suspend(mp, 0); | 951 | error = vfs_suspend(mp, 0); | |
952 | if (error) { | 952 | if (error) { | |
953 | return error; | 953 | return error; | |
@@ -994,28 +994,30 @@ dounmount(struct mount *mp, int flags, s | @@ -994,28 +994,30 @@ dounmount(struct mount *mp, int flags, s | |||
994 | /* | 994 | /* | |
995 | * mark filesystem as gone to prevent further umounts | 995 | * mark filesystem as gone to prevent further umounts | |
996 | * after mnt_umounting lock is gone, this also prevents | 996 | * after mnt_umounting lock is gone, this also prevents | |
997 | * vfs_busy() from succeeding. | 997 | * vfs_busy() from succeeding. | |
998 | */ | 998 | */ | |
999 | mp->mnt_iflag |= IMNT_GONE; | 999 | mp->mnt_iflag |= IMNT_GONE; | |
1000 | if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) { | 1000 | if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) { | |
1001 | coveredvp->v_mountedhere = NULL; | 1001 | coveredvp->v_mountedhere = NULL; | |
1002 | } | 1002 | } | |
1003 | if (!was_suspended) | 1003 | if (!was_suspended) | |
1004 | vfs_resume(mp); | 1004 | vfs_resume(mp); | |
1005 | 1005 | |||
1006 | mountlist_remove(mp); | 1006 | mountlist_remove(mp); | |
1007 | if (TAILQ_FIRST(&mp->mnt_vnodelist) != NULL) | 1007 | if ((vp = VIMPL_TO_VNODE(TAILQ_FIRST(&mp->mnt_vnodelist))) != NULL) { | |
1008 | vprint("dangling", vp); | |||
1008 | panic("unmount: dangling vnode"); | 1009 | panic("unmount: dangling vnode"); | |
1010 | } | |||
1009 | vfs_hooks_unmount(mp); | 1011 | vfs_hooks_unmount(mp); | |
1010 | 1012 | |||
1011 | vfs_set_lowermount(mp, NULL); | 1013 | vfs_set_lowermount(mp, NULL); | |
1012 | vfs_rele(mp); /* reference from mount() */ | 1014 | vfs_rele(mp); /* reference from mount() */ | |
1013 | if (coveredvp != NULLVP) { | 1015 | if (coveredvp != NULLVP) { | |
1014 | vrele(coveredvp); | 1016 | vrele(coveredvp); | |
1015 | } | 1017 | } | |
1016 | return (0); | 1018 | return (0); | |
1017 | } | 1019 | } | |
1018 | 1020 | |||
1019 | /* | 1021 | /* | |
1020 | * Unmount all file systems. | 1022 | * Unmount all file systems. | |
1021 | * We traverse the list in reverse order under the assumption that doing so | 1023 | * We traverse the list in reverse order under the assumption that doing so |
--- src/sys/miscfs/procfs/procfs.h 2022/01/19 10:23:00 1.82
+++ src/sys/miscfs/procfs/procfs.h 2024/04/18 18:22:10 1.82.4.1
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: procfs.h,v 1.82 2022/01/19 10:23:00 martin Exp $ */ | 1 | /* $NetBSD: procfs.h,v 1.82.4.1 2024/04/18 18:22:10 martin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1993 | 4 | * Copyright (c) 1993 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to Berkeley by | 7 | * This code is derived from software contributed to Berkeley by | |
8 | * Jan-Simon Pendry. | 8 | * Jan-Simon Pendry. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -119,27 +119,29 @@ typedef enum { | @@ -119,27 +119,29 @@ typedef enum { | |||
119 | #endif | 119 | #endif | |
120 | PFSlast, /* track number of types */ | 120 | PFSlast, /* track number of types */ | |
121 | } pfstype; | 121 | } pfstype; | |
122 | 122 | |||
123 | /* | 123 | /* | |
124 | * control data for the proc file system. | 124 | * control data for the proc file system. | |
125 | */ | 125 | */ | |
126 | struct pfskey { | 126 | struct pfskey { | |
127 | pfstype pk_type; /* type of procfs node */ | 127 | pfstype pk_type; /* type of procfs node */ | |
128 | pid_t pk_pid; /* associated process */ | 128 | pid_t pk_pid; /* associated process */ | |
129 | int pk_fd; /* associated fd if not -1 */ | 129 | int pk_fd; /* associated fd if not -1 */ | |
130 | }; | 130 | }; | |
131 | struct pfsnode { | 131 | struct pfsnode { | |
132 | LIST_ENTRY(pfsnode) pfs_hash; /* per pid hash list */ | |||
132 | struct vnode *pfs_vnode; /* vnode associated with this pfsnode */ | 133 | struct vnode *pfs_vnode; /* vnode associated with this pfsnode */ | |
134 | struct mount *pfs_mount; /* mount associated with this pfsnode */ | |||
133 | struct pfskey pfs_key; | 135 | struct pfskey pfs_key; | |
134 | #define pfs_type pfs_key.pk_type | 136 | #define pfs_type pfs_key.pk_type | |
135 | #define pfs_pid pfs_key.pk_pid | 137 | #define pfs_pid pfs_key.pk_pid | |
136 | #define pfs_fd pfs_key.pk_fd | 138 | #define pfs_fd pfs_key.pk_fd | |
137 | mode_t pfs_mode; /* mode bits for stat() */ | 139 | mode_t pfs_mode; /* mode bits for stat() */ | |
138 | u_long pfs_flags; /* open flags */ | 140 | u_long pfs_flags; /* open flags */ | |
139 | uint64_t pfs_fileno; /* unique file id */ | 141 | uint64_t pfs_fileno; /* unique file id */ | |
140 | }; | 142 | }; | |
141 | 143 | |||
142 | #define PROCFS_NOTELEN 64 /* max length of a note (/proc/$pid/note) */ | 144 | #define PROCFS_NOTELEN 64 /* max length of a note (/proc/$pid/note) */ | |
143 | #define PROCFS_MAXNAMLEN 255 | 145 | #define PROCFS_MAXNAMLEN 255 | |
144 | 146 | |||
145 | #endif /* _KERNEL */ | 147 | #endif /* _KERNEL */ | |
@@ -180,27 +182,26 @@ procfs_fileno(pid_t _pid, pfstype _type, | @@ -180,27 +182,26 @@ procfs_fileno(pid_t _pid, pfstype _type, | |||
180 | default: | 182 | default: | |
181 | _ino = _pid + 1; | 183 | _ino = _pid + 1; | |
182 | if (_fd != -1) | 184 | if (_fd != -1) | |
183 | _ino = _ino << 32 | _fd; | 185 | _ino = _ino << 32 | _fd; | |
184 | return _ino * PFSlast + _type; | 186 | return _ino * PFSlast + _type; | |
185 | } | 187 | } | |
186 | } | 188 | } | |
187 | 189 | |||
188 | #define PROCFS_FILENO(pid, type, fd) procfs_fileno(pid, type, fd) | 190 | #define PROCFS_FILENO(pid, type, fd) procfs_fileno(pid, type, fd) | |
189 | 191 | |||
190 | #define PROCFS_TYPE(type) ((type) % PFSlast) | 192 | #define PROCFS_TYPE(type) ((type) % PFSlast) | |
191 | 193 | |||
192 | struct procfsmount { | 194 | struct procfsmount { | |
193 | void *pmnt_exechook; | |||
194 | int pmnt_flags; | 195 | int pmnt_flags; | |
195 | }; | 196 | }; | |
196 | 197 | |||
197 | #define VFSTOPROC(mp) ((struct procfsmount *)(mp)->mnt_data) | 198 | #define VFSTOPROC(mp) ((struct procfsmount *)(mp)->mnt_data) | |
198 | 199 | |||
199 | /* | 200 | /* | |
200 | * Convert between pfsnode vnode | 201 | * Convert between pfsnode vnode | |
201 | */ | 202 | */ | |
202 | #define VTOPFS(vp) ((struct pfsnode *)(vp)->v_data) | 203 | #define VTOPFS(vp) ((struct pfsnode *)(vp)->v_data) | |
203 | #define PFSTOV(pfs) ((pfs)->pfs_vnode) | 204 | #define PFSTOV(pfs) ((pfs)->pfs_vnode) | |
204 | 205 | |||
205 | typedef struct vfs_namemap vfs_namemap_t; | 206 | typedef struct vfs_namemap vfs_namemap_t; | |
206 | struct vfs_namemap { | 207 | struct vfs_namemap { | |
@@ -259,27 +260,27 @@ int procfs_dofd(struct lwp *, struct pro | @@ -259,27 +260,27 @@ int procfs_dofd(struct lwp *, struct pro | |||
259 | int procfs_douptime(struct lwp *, struct proc *, struct pfsnode *, | 260 | int procfs_douptime(struct lwp *, struct proc *, struct pfsnode *, | |
260 | struct uio *); | 261 | struct uio *); | |
261 | int procfs_domounts(struct lwp *, struct proc *, struct pfsnode *, | 262 | int procfs_domounts(struct lwp *, struct proc *, struct pfsnode *, | |
262 | struct uio *); | 263 | struct uio *); | |
263 | int procfs_doemul(struct lwp *, struct proc *, struct pfsnode *, | 264 | int procfs_doemul(struct lwp *, struct proc *, struct pfsnode *, | |
264 | struct uio *); | 265 | struct uio *); | |
265 | int procfs_doversion(struct lwp *, struct proc *, struct pfsnode *, | 266 | int procfs_doversion(struct lwp *, struct proc *, struct pfsnode *, | |
266 | struct uio *); | 267 | struct uio *); | |
267 | int procfs_doauxv(struct lwp *, struct proc *, struct pfsnode *, | 268 | int procfs_doauxv(struct lwp *, struct proc *, struct pfsnode *, | |
268 | struct uio *); | 269 | struct uio *); | |
269 | int procfs_dolimit(struct lwp *, struct proc *, struct pfsnode *, | 270 | int procfs_dolimit(struct lwp *, struct proc *, struct pfsnode *, | |
270 | struct uio *); | 271 | struct uio *); | |
271 | 272 | |||
272 | void procfs_revoke_vnodes(struct proc *, void *); | 273 | void procfs_hashrem(struct pfsnode *); | |
273 | int procfs_getfp(struct pfsnode *, struct proc *, struct file **); | 274 | int procfs_getfp(struct pfsnode *, struct proc *, struct file **); | |
274 | 275 | |||
275 | /* functions to check whether or not files should be displayed */ | 276 | /* functions to check whether or not files should be displayed */ | |
276 | int procfs_validauxv(struct lwp *, struct mount *); | 277 | int procfs_validauxv(struct lwp *, struct mount *); | |
277 | int procfs_validfile(struct lwp *, struct mount *); | 278 | int procfs_validfile(struct lwp *, struct mount *); | |
278 | int procfs_validfpregs(struct lwp *, struct mount *); | 279 | int procfs_validfpregs(struct lwp *, struct mount *); | |
279 | int procfs_validregs(struct lwp *, struct mount *); | 280 | int procfs_validregs(struct lwp *, struct mount *); | |
280 | int procfs_validmap(struct lwp *, struct mount *); | 281 | int procfs_validmap(struct lwp *, struct mount *); | |
281 | 282 | |||
282 | int procfs_rw(void *); | 283 | int procfs_rw(void *); | |
283 | 284 | |||
284 | int procfs_getcpuinfstr(char *, size_t *); | 285 | int procfs_getcpuinfstr(char *, size_t *); | |
285 | 286 |
--- src/sys/miscfs/procfs/procfs_subr.c 2020/05/23 23:42:43 1.116
+++ src/sys/miscfs/procfs/procfs_subr.c 2024/04/18 18:22:10 1.116.20.1
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: procfs_subr.c,v 1.116 2020/05/23 23:42:43 ad Exp $ */ | 1 | /* $NetBSD: procfs_subr.c,v 1.116.20.1 2024/04/18 18:22:10 martin Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Andrew Doran. | 8 | * by Andrew Doran. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -92,27 +92,27 @@ | @@ -92,27 +92,27 @@ | |||
92 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 92 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
93 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 93 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
94 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 94 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
95 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 95 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
96 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 96 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
97 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 97 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
98 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 98 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
99 | * SUCH DAMAGE. | 99 | * SUCH DAMAGE. | |
100 | * | 100 | * | |
101 | * @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95 | 101 | * @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95 | |
102 | */ | 102 | */ | |
103 | 103 | |||
104 | #include <sys/cdefs.h> | 104 | #include <sys/cdefs.h> | |
105 | __KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.116 2020/05/23 23:42:43 ad Exp $"); | 105 | __KERNEL_RCSID(0, "$NetBSD: procfs_subr.c,v 1.116.20.1 2024/04/18 18:22:10 martin Exp $"); | |
106 | 106 | |||
107 | #include <sys/param.h> | 107 | #include <sys/param.h> | |
108 | #include <sys/systm.h> | 108 | #include <sys/systm.h> | |
109 | #include <sys/time.h> | 109 | #include <sys/time.h> | |
110 | #include <sys/kernel.h> | 110 | #include <sys/kernel.h> | |
111 | #include <sys/proc.h> | 111 | #include <sys/proc.h> | |
112 | #include <sys/fstrans.h> | 112 | #include <sys/fstrans.h> | |
113 | #include <sys/vnode.h> | 113 | #include <sys/vnode.h> | |
114 | #include <sys/stat.h> | 114 | #include <sys/stat.h> | |
115 | #include <sys/file.h> | 115 | #include <sys/file.h> | |
116 | #include <sys/filedesc.h> | 116 | #include <sys/filedesc.h> | |
117 | #include <sys/kauth.h> | 117 | #include <sys/kauth.h> | |
118 | #include <sys/sysctl.h> | 118 | #include <sys/sysctl.h> | |
@@ -348,77 +348,26 @@ vfs_getuserstr(struct uio *uio, char *bf | @@ -348,77 +348,26 @@ vfs_getuserstr(struct uio *uio, char *bf | |||
348 | } | 348 | } | |
349 | 349 | |||
350 | const vfs_namemap_t * | 350 | const vfs_namemap_t * | |
351 | vfs_findname(const vfs_namemap_t *nm, const char *bf, int buflen) | 351 | vfs_findname(const vfs_namemap_t *nm, const char *bf, int buflen) | |
352 | { | 352 | { | |
353 | 353 | |||
354 | for (; nm->nm_name; nm++) | 354 | for (; nm->nm_name; nm++) | |
355 | if (memcmp(bf, nm->nm_name, buflen+1) == 0) | 355 | if (memcmp(bf, nm->nm_name, buflen+1) == 0) | |
356 | return (nm); | 356 | return (nm); | |
357 | 357 | |||
358 | return (0); | 358 | return (0); | |
359 | } | 359 | } | |
360 | 360 | |||
361 | static bool | |||
362 | procfs_revoke_selector(void *arg, struct vnode *vp) | |||
363 | { | |||
364 | struct proc *p = arg; | |||
365 | struct pfsnode *pfs; | |||
366 | ||||
367 | KASSERT(mutex_owned(vp->v_interlock)); | |||
368 | ||||
369 | pfs = VTOPFS(vp); | |||
370 | ||||
371 | return (pfs != NULL && pfs->pfs_pid == p->p_pid); | |||
372 | } | |||
373 | ||||
374 | void | |||
375 | procfs_revoke_vnodes(struct proc *p, void *arg) | |||
376 | { | |||
377 | int error; | |||
378 | bool suspended; | |||
379 | struct vnode *vp; | |||
380 | struct vnode_iterator *marker; | |||
381 | struct mount *mp = (struct mount *)arg; | |||
382 | ||||
383 | if (!(p->p_flag & PK_SUGID)) | |||
384 | return; | |||
385 | ||||
386 | suspended = false; | |||
387 | vfs_vnode_iterator_init(mp, &marker); | |||
388 | ||||
389 | while ((vp = vfs_vnode_iterator_next(marker, | |||
390 | procfs_revoke_selector, p)) != NULL) { | |||
391 | if (vrecycle(vp)) | |||
392 | continue; | |||
393 | /* Vnode is busy, we have to suspend the mount for vgone(). */ | |||
394 | while (! suspended) { | |||
395 | error = vfs_suspend(mp, 0); | |||
396 | if (error == 0) { | |||
397 | suspended = true; | |||
398 | } else if (error != EINTR && error != ERESTART) { | |||
399 | KASSERT(error == EOPNOTSUPP); | |||
400 | break; | |||
401 | } | |||
402 | } | |||
403 | vgone(vp); | |||
404 | } | |||
405 | ||||
406 | if (suspended) | |||
407 | vfs_resume(mp); | |||
408 | ||||
409 | vfs_vnode_iterator_destroy(marker); | |||
410 | } | |||
411 | ||||
412 | bool | 361 | bool | |
413 | procfs_use_linux_compat(struct mount *mp) | 362 | procfs_use_linux_compat(struct mount *mp) | |
414 | { | 363 | { | |
415 | const int flags = VFSTOPROC(mp)->pmnt_flags; | 364 | const int flags = VFSTOPROC(mp)->pmnt_flags; | |
416 | 365 | |||
417 | return (flags & PROCFSMNT_LINUXCOMPAT) ? true : false; | 366 | return (flags & PROCFSMNT_LINUXCOMPAT) ? true : false; | |
418 | } | 367 | } | |
419 | 368 | |||
420 | struct proc * | 369 | struct proc * | |
421 | procfs_proc_find(struct mount *mp, pid_t pid) | 370 | procfs_proc_find(struct mount *mp, pid_t pid) | |
422 | { | 371 | { | |
423 | 372 | |||
424 | KASSERT(mutex_owned(&proc_lock)); | 373 | KASSERT(mutex_owned(&proc_lock)); |
--- src/sys/miscfs/procfs/procfs_vfsops.c 2022/01/17 11:20:00 1.111
+++ src/sys/miscfs/procfs/procfs_vfsops.c 2024/04/18 18:22:10 1.111.4.1
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: procfs_vfsops.c,v 1.111 2022/01/17 11:20:00 bouyer Exp $ */ | 1 | /* $NetBSD: procfs_vfsops.c,v 1.111.4.1 2024/04/18 18:22:10 martin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1993 | 4 | * Copyright (c) 1993 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to Berkeley by | 7 | * This code is derived from software contributed to Berkeley by | |
8 | * Jan-Simon Pendry. | 8 | * Jan-Simon Pendry. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -66,61 +66,88 @@ | @@ -66,61 +66,88 @@ | |||
66 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 66 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
67 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 67 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
68 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 68 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
69 | * SUCH DAMAGE. | 69 | * SUCH DAMAGE. | |
70 | * | 70 | * | |
71 | * @(#)procfs_vfsops.c 8.7 (Berkeley) 5/10/95 | 71 | * @(#)procfs_vfsops.c 8.7 (Berkeley) 5/10/95 | |
72 | */ | 72 | */ | |
73 | 73 | |||
74 | /* | 74 | /* | |
75 | * procfs VFS interface | 75 | * procfs VFS interface | |
76 | */ | 76 | */ | |
77 | 77 | |||
78 | #include <sys/cdefs.h> | 78 | #include <sys/cdefs.h> | |
79 | __KERNEL_RCSID(0, "$NetBSD: procfs_vfsops.c,v 1.111 2022/01/17 11:20:00 bouyer Exp $"); | 79 | __KERNEL_RCSID(0, "$NetBSD: procfs_vfsops.c,v 1.111.4.1 2024/04/18 18:22:10 martin Exp $"); | |
80 | 80 | |||
81 | #if defined(_KERNEL_OPT) | 81 | #if defined(_KERNEL_OPT) | |
82 | #include "opt_compat_netbsd.h" | 82 | #include "opt_compat_netbsd.h" | |
83 | #endif | 83 | #endif | |
84 | 84 | |||
85 | #include <sys/param.h> | 85 | #include <sys/param.h> | |
86 | #include <sys/atomic.h> | 86 | #include <sys/atomic.h> | |
87 | #include <sys/buf.h> | 87 | #include <sys/buf.h> | |
88 | #include <sys/dirent.h> | 88 | #include <sys/dirent.h> | |
89 | #include <sys/file.h> | 89 | #include <sys/file.h> | |
90 | #include <sys/filedesc.h> | 90 | #include <sys/filedesc.h> | |
91 | #include <sys/fstrans.h> | |||
91 | #include <sys/kauth.h> | 92 | #include <sys/kauth.h> | |
92 | #include <sys/kernel.h> | 93 | #include <sys/kernel.h> | |
93 | #include <sys/module.h> | 94 | #include <sys/module.h> | |
94 | #include <sys/mount.h> | 95 | #include <sys/mount.h> | |
95 | #include <sys/proc.h> | 96 | #include <sys/proc.h> | |
96 | #include <sys/signalvar.h> | 97 | #include <sys/signalvar.h> | |
97 | #include <sys/sysctl.h> | 98 | #include <sys/sysctl.h> | |
98 | #include <sys/syslog.h> | 99 | #include <sys/syslog.h> | |
99 | #include <sys/systm.h> | 100 | #include <sys/systm.h> | |
100 | #include <sys/time.h> | 101 | #include <sys/time.h> | |
101 | #include <sys/vnode.h> | 102 | #include <sys/vnode.h> | |
102 | 103 | |||
103 | #include <miscfs/genfs/genfs.h> | 104 | #include <miscfs/genfs/genfs.h> | |
104 | 105 | |||
105 | #include <miscfs/procfs/procfs.h> | 106 | #include <miscfs/procfs/procfs.h> | |
106 | 107 | |||
107 | #include <uvm/uvm_extern.h> /* for PAGE_SIZE */ | 108 | #include <uvm/uvm_extern.h> /* for PAGE_SIZE */ | |
108 | 109 | |||
109 | MODULE(MODULE_CLASS_VFS, procfs, "ptrace_common"); | 110 | MODULE(MODULE_CLASS_VFS, procfs, "ptrace_common"); | |
110 | 111 | |||
111 | VFS_PROTOS(procfs); | 112 | VFS_PROTOS(procfs); | |
112 | 113 | |||
114 | #define PROCFS_HASHSIZE 256 | |||
115 | #define PROCFS_EXEC_HOOK ((void *)1) | |||
116 | #define PROCFS_EXIT_HOOK ((void *)2) | |||
117 | ||||
113 | static kauth_listener_t procfs_listener; | 118 | static kauth_listener_t procfs_listener; | |
119 | static void *procfs_exechook; | |||
120 | static void *procfs_exithook; | |||
121 | LIST_HEAD(hashhead, pfsnode); | |||
122 | static u_long procfs_hashmask; | |||
123 | static struct hashhead *procfs_hashtab; | |||
124 | static kmutex_t procfs_hashlock; | |||
125 | ||||
126 | static struct hashhead * | |||
127 | procfs_hashhead(pid_t pid) | |||
128 | { | |||
129 | ||||
130 | return &procfs_hashtab[pid & procfs_hashmask]; | |||
131 | } | |||
132 | ||||
133 | void | |||
134 | procfs_hashrem(struct pfsnode *pfs) | |||
135 | { | |||
136 | ||||
137 | mutex_enter(&procfs_hashlock); | |||
138 | LIST_REMOVE(pfs, pfs_hash); | |||
139 | mutex_exit(&procfs_hashlock); | |||
140 | } | |||
114 | 141 | |||
115 | /* | 142 | /* | |
116 | * VFS Operations. | 143 | * VFS Operations. | |
117 | * | 144 | * | |
118 | * mount system call | 145 | * mount system call | |
119 | */ | 146 | */ | |
120 | /* ARGSUSED */ | 147 | /* ARGSUSED */ | |
121 | int | 148 | int | |
122 | procfs_mount( | 149 | procfs_mount( | |
123 | struct mount *mp, | 150 | struct mount *mp, | |
124 | const char *path, | 151 | const char *path, | |
125 | void *data, | 152 | void *data, | |
126 | size_t *data_len) | 153 | size_t *data_len) | |
@@ -156,53 +183,50 @@ procfs_mount( | @@ -156,53 +183,50 @@ procfs_mount( | |||
156 | 183 | |||
157 | if (*data_len >= sizeof *args && args->version != PROCFS_ARGSVERSION) | 184 | if (*data_len >= sizeof *args && args->version != PROCFS_ARGSVERSION) | |
158 | return EINVAL; | 185 | return EINVAL; | |
159 | 186 | |||
160 | pmnt = kmem_zalloc(sizeof(struct procfsmount), KM_SLEEP); | 187 | pmnt = kmem_zalloc(sizeof(struct procfsmount), KM_SLEEP); | |
161 | 188 | |||
162 | mp->mnt_stat.f_namemax = PROCFS_MAXNAMLEN; | 189 | mp->mnt_stat.f_namemax = PROCFS_MAXNAMLEN; | |
163 | mp->mnt_flag |= MNT_LOCAL; | 190 | mp->mnt_flag |= MNT_LOCAL; | |
164 | mp->mnt_data = pmnt; | 191 | mp->mnt_data = pmnt; | |
165 | vfs_getnewfsid(mp); | 192 | vfs_getnewfsid(mp); | |
166 | 193 | |||
167 | error = set_statvfs_info(path, UIO_USERSPACE, "procfs", UIO_SYSSPACE, | 194 | error = set_statvfs_info(path, UIO_USERSPACE, "procfs", UIO_SYSSPACE, | |
168 | mp->mnt_op->vfs_name, mp, l); | 195 | mp->mnt_op->vfs_name, mp, l); | |
169 | pmnt->pmnt_exechook = exechook_establish(procfs_revoke_vnodes, mp); | |||
170 | if (*data_len >= sizeof *args) | 196 | if (*data_len >= sizeof *args) | |
171 | pmnt->pmnt_flags = args->flags; | 197 | pmnt->pmnt_flags = args->flags; | |
172 | else | 198 | else | |
173 | pmnt->pmnt_flags = 0; | 199 | pmnt->pmnt_flags = 0; | |
174 | 200 | |||
175 | mp->mnt_iflag |= IMNT_MPSAFE | IMNT_SHRLOOKUP; | 201 | mp->mnt_iflag |= IMNT_MPSAFE | IMNT_SHRLOOKUP; | |
176 | return error; | 202 | return error; | |
177 | } | 203 | } | |
178 | 204 | |||
179 | /* | 205 | /* | |
180 | * unmount system call | 206 | * unmount system call | |
181 | */ | 207 | */ | |
182 | int | 208 | int | |
183 | procfs_unmount(struct mount *mp, int mntflags) | 209 | procfs_unmount(struct mount *mp, int mntflags) | |
184 | { | 210 | { | |
185 | int error; | 211 | int error; | |
186 | int flags = 0; | 212 | int flags = 0; | |
187 | 213 | |||
188 | if (mntflags & MNT_FORCE) | 214 | if (mntflags & MNT_FORCE) | |
189 | flags |= FORCECLOSE; | 215 | flags |= FORCECLOSE; | |
190 | 216 | |||
191 | if ((error = vflush(mp, 0, flags)) != 0) | 217 | if ((error = vflush(mp, 0, flags)) != 0) | |
192 | return (error); | 218 | return (error); | |
193 | 219 | |||
194 | exechook_disestablish(VFSTOPROC(mp)->pmnt_exechook); | |||
195 | ||||
196 | kmem_free(mp->mnt_data, sizeof(struct procfsmount)); | 220 | kmem_free(mp->mnt_data, sizeof(struct procfsmount)); | |
197 | mp->mnt_data = NULL; | 221 | mp->mnt_data = NULL; | |
198 | 222 | |||
199 | return 0; | 223 | return 0; | |
200 | } | 224 | } | |
201 | 225 | |||
202 | int | 226 | int | |
203 | procfs_root(struct mount *mp, int lktype, struct vnode **vpp) | 227 | procfs_root(struct mount *mp, int lktype, struct vnode **vpp) | |
204 | { | 228 | { | |
205 | int error; | 229 | int error; | |
206 | 230 | |||
207 | error = procfs_allocvp(mp, vpp, 0, PFSroot, -1); | 231 | error = procfs_allocvp(mp, vpp, 0, PFSroot, -1); | |
208 | if (error == 0) { | 232 | if (error == 0) { | |
@@ -269,26 +293,27 @@ procfs_loadvnode(struct mount *mp, struc | @@ -269,26 +293,27 @@ procfs_loadvnode(struct mount *mp, struc | |||
269 | { | 293 | { | |
270 | int error; | 294 | int error; | |
271 | struct pfskey pfskey; | 295 | struct pfskey pfskey; | |
272 | struct pfsnode *pfs; | 296 | struct pfsnode *pfs; | |
273 | 297 | |||
274 | KASSERT(key_len == sizeof(pfskey)); | 298 | KASSERT(key_len == sizeof(pfskey)); | |
275 | memcpy(&pfskey, key, key_len); | 299 | memcpy(&pfskey, key, key_len); | |
276 | 300 | |||
277 | pfs = kmem_alloc(sizeof(*pfs), KM_SLEEP); | 301 | pfs = kmem_alloc(sizeof(*pfs), KM_SLEEP); | |
278 | pfs->pfs_pid = pfskey.pk_pid; | 302 | pfs->pfs_pid = pfskey.pk_pid; | |
279 | pfs->pfs_type = pfskey.pk_type; | 303 | pfs->pfs_type = pfskey.pk_type; | |
280 | pfs->pfs_fd = pfskey.pk_fd; | 304 | pfs->pfs_fd = pfskey.pk_fd; | |
281 | pfs->pfs_vnode = vp; | 305 | pfs->pfs_vnode = vp; | |
306 | pfs->pfs_mount = mp; | |||
282 | pfs->pfs_flags = 0; | 307 | pfs->pfs_flags = 0; | |
283 | pfs->pfs_fileno = | 308 | pfs->pfs_fileno = | |
284 | PROCFS_FILENO(pfs->pfs_pid, pfs->pfs_type, pfs->pfs_fd); | 309 | PROCFS_FILENO(pfs->pfs_pid, pfs->pfs_type, pfs->pfs_fd); | |
285 | vp->v_tag = VT_PROCFS; | 310 | vp->v_tag = VT_PROCFS; | |
286 | vp->v_op = procfs_vnodeop_p; | 311 | vp->v_op = procfs_vnodeop_p; | |
287 | vp->v_data = pfs; | 312 | vp->v_data = pfs; | |
288 | 313 | |||
289 | switch (pfs->pfs_type) { | 314 | switch (pfs->pfs_type) { | |
290 | case PFSroot: /* /proc = dr-xr-xr-x */ | 315 | case PFSroot: /* /proc = dr-xr-xr-x */ | |
291 | vp->v_vflag |= VV_ROOT; | 316 | vp->v_vflag |= VV_ROOT; | |
292 | /*FALLTHROUGH*/ | 317 | /*FALLTHROUGH*/ | |
293 | case PFSproc: /* /proc/N = dr-xr-xr-x */ | 318 | case PFSproc: /* /proc/N = dr-xr-xr-x */ | |
294 | pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; | 319 | pfs->pfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; | |
@@ -411,26 +436,30 @@ procfs_loadvnode(struct mount *mp, struc | @@ -411,26 +436,30 @@ procfs_loadvnode(struct mount *mp, struc | |||
411 | vp->v_type = VREG; | 436 | vp->v_type = VREG; | |
412 | break; | 437 | break; | |
413 | 438 | |||
414 | #ifdef __HAVE_PROCFS_MACHDEP | 439 | #ifdef __HAVE_PROCFS_MACHDEP | |
415 | PROCFS_MACHDEP_NODETYPE_CASES | 440 | PROCFS_MACHDEP_NODETYPE_CASES | |
416 | procfs_machdep_allocvp(vp); | 441 | procfs_machdep_allocvp(vp); | |
417 | break; | 442 | break; | |
418 | #endif | 443 | #endif | |
419 | 444 | |||
420 | default: | 445 | default: | |
421 | panic("procfs_allocvp"); | 446 | panic("procfs_allocvp"); | |
422 | } | 447 | } | |
423 | 448 | |||
449 | mutex_enter(&procfs_hashlock); | |||
450 | LIST_INSERT_HEAD(procfs_hashhead(pfs->pfs_pid), pfs, pfs_hash); | |||
451 | mutex_exit(&procfs_hashlock); | |||
452 | ||||
424 | uvm_vnp_setsize(vp, 0); | 453 | uvm_vnp_setsize(vp, 0); | |
425 | *new_key = &pfs->pfs_key; | 454 | *new_key = &pfs->pfs_key; | |
426 | 455 | |||
427 | return 0; | 456 | return 0; | |
428 | 457 | |||
429 | bad: | 458 | bad: | |
430 | vp->v_tag =VT_NON; | 459 | vp->v_tag =VT_NON; | |
431 | vp->v_type = VNON; | 460 | vp->v_type = VNON; | |
432 | vp->v_op = NULL; | 461 | vp->v_op = NULL; | |
433 | vp->v_data = NULL; | 462 | vp->v_data = NULL; | |
434 | kmem_free(pfs, sizeof(*pfs)); | 463 | kmem_free(pfs, sizeof(*pfs)); | |
435 | return error; | 464 | return error; | |
436 | } | 465 | } | |
@@ -476,26 +505,68 @@ struct vfsops procfs_vfsops = { | @@ -476,26 +505,68 @@ struct vfsops procfs_vfsops = { | |||
476 | .vfs_vptofh = (void *)eopnotsupp, | 505 | .vfs_vptofh = (void *)eopnotsupp, | |
477 | .vfs_init = procfs_init, | 506 | .vfs_init = procfs_init, | |
478 | .vfs_reinit = procfs_reinit, | 507 | .vfs_reinit = procfs_reinit, | |
479 | .vfs_done = procfs_done, | 508 | .vfs_done = procfs_done, | |
480 | .vfs_snapshot = (void *)eopnotsupp, | 509 | .vfs_snapshot = (void *)eopnotsupp, | |
481 | .vfs_extattrctl = vfs_stdextattrctl, | 510 | .vfs_extattrctl = vfs_stdextattrctl, | |
482 | .vfs_suspendctl = genfs_suspendctl, | 511 | .vfs_suspendctl = genfs_suspendctl, | |
483 | .vfs_renamelock_enter = genfs_renamelock_enter, | 512 | .vfs_renamelock_enter = genfs_renamelock_enter, | |
484 | .vfs_renamelock_exit = genfs_renamelock_exit, | 513 | .vfs_renamelock_exit = genfs_renamelock_exit, | |
485 | .vfs_fsync = (void *)eopnotsupp, | 514 | .vfs_fsync = (void *)eopnotsupp, | |
486 | .vfs_opv_descs = procfs_vnodeopv_descs | 515 | .vfs_opv_descs = procfs_vnodeopv_descs | |
487 | }; | 516 | }; | |
488 | 517 | |||
518 | static void | |||
519 | procfs_exechook_cb(struct proc *p, void *arg) | |||
520 | { | |||
521 | struct hashhead *head; | |||
522 | struct pfsnode *pfs; | |||
523 | struct mount *mp; | |||
524 | struct pfskey key; | |||
525 | struct vnode *vp; | |||
526 | int error; | |||
527 | ||||
528 | if (arg == PROCFS_EXEC_HOOK && !(p->p_flag & PK_SUGID)) | |||
529 | return; | |||
530 | ||||
531 | head = procfs_hashhead(p->p_pid); | |||
532 | ||||
533 | again: | |||
534 | mutex_enter(&procfs_hashlock); | |||
535 | LIST_FOREACH(pfs, head, pfs_hash) { | |||
536 | if (pfs->pfs_pid != p->p_pid) | |||
537 | continue; | |||
538 | mp = pfs->pfs_mount; | |||
539 | key = pfs->pfs_key; | |||
540 | vfs_ref(mp); | |||
541 | mutex_exit(&procfs_hashlock); | |||
542 | ||||
543 | error = vcache_get(mp, &key, sizeof(key), &vp); | |||
544 | vfs_rele(mp); | |||
545 | if (error != 0) | |||
546 | goto again; | |||
547 | if (vrecycle(vp)) | |||
548 | goto again; | |||
549 | do { | |||
550 | error = vfs_suspend(mp, 0); | |||
551 | } while (error == EINTR || error == ERESTART); | |||
552 | vgone(vp); | |||
553 | if (error == 0) | |||
554 | vfs_resume(mp); | |||
555 | goto again; | |||
556 | } | |||
557 | mutex_exit(&procfs_hashlock); | |||
558 | } | |||
559 | ||||
489 | static int | 560 | static int | |
490 | procfs_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie, | 561 | procfs_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie, | |
491 | void *arg0, void *arg1, void *arg2, void *arg3) | 562 | void *arg0, void *arg1, void *arg2, void *arg3) | |
492 | { | 563 | { | |
493 | struct proc *p; | 564 | struct proc *p; | |
494 | struct pfsnode *pfs; | 565 | struct pfsnode *pfs; | |
495 | int result; | 566 | int result; | |
496 | 567 | |||
497 | result = KAUTH_RESULT_DEFER; | 568 | result = KAUTH_RESULT_DEFER; | |
498 | p = arg0; | 569 | p = arg0; | |
499 | pfs = arg1; | 570 | pfs = arg1; | |
500 | 571 | |||
501 | if (action != KAUTH_PROCESS_PROCFS) | 572 | if (action != KAUTH_PROCESS_PROCFS) | |
@@ -538,27 +609,40 @@ static int | @@ -538,27 +609,40 @@ static int | |||
538 | procfs_modcmd(modcmd_t cmd, void *arg) | 609 | procfs_modcmd(modcmd_t cmd, void *arg) | |
539 | { | 610 | { | |
540 | int error; | 611 | int error; | |
541 | 612 | |||
542 | switch (cmd) { | 613 | switch (cmd) { | |
543 | case MODULE_CMD_INIT: | 614 | case MODULE_CMD_INIT: | |
544 | error = vfs_attach(&procfs_vfsops); | 615 | error = vfs_attach(&procfs_vfsops); | |
545 | if (error != 0) | 616 | if (error != 0) | |
546 | break; | 617 | break; | |
547 | 618 | |||
548 | procfs_listener = kauth_listen_scope(KAUTH_SCOPE_PROCESS, | 619 | procfs_listener = kauth_listen_scope(KAUTH_SCOPE_PROCESS, | |
549 | procfs_listener_cb, NULL); | 620 | procfs_listener_cb, NULL); | |
550 | 621 | |||
622 | procfs_exechook = exechook_establish(procfs_exechook_cb, | |||
623 | PROCFS_EXEC_HOOK); | |||
624 | procfs_exithook = exithook_establish(procfs_exechook_cb, | |||
625 | PROCFS_EXIT_HOOK); | |||
626 | ||||
627 | mutex_init(&procfs_hashlock, MUTEX_DEFAULT, IPL_NONE); | |||
628 | procfs_hashtab = hashinit(PROCFS_HASHSIZE, HASH_LIST, true, | |||
629 | &procfs_hashmask); | |||
630 | ||||
551 | break; | 631 | break; | |
552 | case MODULE_CMD_FINI: | 632 | case MODULE_CMD_FINI: | |
553 | error = vfs_detach(&procfs_vfsops); | 633 | error = vfs_detach(&procfs_vfsops); | |
554 | if (error != 0) | 634 | if (error != 0) | |
555 | break; | 635 | break; | |
556 | kauth_unlisten_scope(procfs_listener); | 636 | kauth_unlisten_scope(procfs_listener); | |
637 | exechook_disestablish(procfs_exechook); | |||
638 | exithook_disestablish(procfs_exithook); | |||
639 | mutex_destroy(&procfs_hashlock); | |||
640 | hashdone(procfs_hashtab, HASH_LIST, procfs_hashmask); | |||
557 | break; | 641 | break; | |
558 | default: | 642 | default: | |
559 | error = ENOTTY; | 643 | error = ENOTTY; | |
560 | break; | 644 | break; | |
561 | } | 645 | } | |
562 | 646 | |||
563 | return (error); | 647 | return (error); | |
564 | } | 648 | } |
--- src/sys/miscfs/procfs/procfs_vnops.c 2022/06/17 14:30:37 1.229
+++ src/sys/miscfs/procfs/procfs_vnops.c 2024/04/18 18:22:10 1.229.4.1
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: procfs_vnops.c,v 1.229 2022/06/17 14:30:37 shm Exp $ */ | 1 | /* $NetBSD: procfs_vnops.c,v 1.229.4.1 2024/04/18 18:22:10 martin Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2006, 2007, 2008, 2020 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2006, 2007, 2008, 2020 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Andrew Doran. | 8 | * by Andrew Doran. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -95,27 +95,27 @@ | @@ -95,27 +95,27 @@ | |||
95 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 95 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
96 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 96 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
97 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 97 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
98 | * SUCH DAMAGE. | 98 | * SUCH DAMAGE. | |
99 | * | 99 | * | |
100 | * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95 | 100 | * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95 | |
101 | */ | 101 | */ | |
102 | 102 | |||
103 | /* | 103 | /* | |
104 | * procfs vnode interface | 104 | * procfs vnode interface | |
105 | */ | 105 | */ | |
106 | 106 | |||
107 | #include <sys/cdefs.h> | 107 | #include <sys/cdefs.h> | |
108 | __KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.229 2022/06/17 14:30:37 shm Exp $"); | 108 | __KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.229.4.1 2024/04/18 18:22:10 martin Exp $"); | |
109 | 109 | |||
110 | #include <sys/param.h> | 110 | #include <sys/param.h> | |
111 | #include <sys/atomic.h> | 111 | #include <sys/atomic.h> | |
112 | #include <sys/systm.h> | 112 | #include <sys/systm.h> | |
113 | #include <sys/time.h> | 113 | #include <sys/time.h> | |
114 | #include <sys/kernel.h> | 114 | #include <sys/kernel.h> | |
115 | #include <sys/file.h> | 115 | #include <sys/file.h> | |
116 | #include <sys/filedesc.h> | 116 | #include <sys/filedesc.h> | |
117 | #include <sys/proc.h> | 117 | #include <sys/proc.h> | |
118 | #include <sys/vnode.h> | 118 | #include <sys/vnode.h> | |
119 | #include <sys/namei.h> | 119 | #include <sys/namei.h> | |
120 | #include <sys/malloc.h> | 120 | #include <sys/malloc.h> | |
121 | #include <sys/mount.h> | 121 | #include <sys/mount.h> | |
@@ -427,26 +427,27 @@ procfs_reclaim(void *v) | @@ -427,26 +427,27 @@ procfs_reclaim(void *v) | |||
427 | struct vnode *a_vp; | 427 | struct vnode *a_vp; | |
428 | } */ *ap = v; | 428 | } */ *ap = v; | |
429 | struct vnode *vp = ap->a_vp; | 429 | struct vnode *vp = ap->a_vp; | |
430 | struct pfsnode *pfs = VTOPFS(vp); | 430 | struct pfsnode *pfs = VTOPFS(vp); | |
431 | 431 | |||
432 | VOP_UNLOCK(vp); | 432 | VOP_UNLOCK(vp); | |
433 | 433 | |||
434 | /* | 434 | /* | |
435 | * To interlock with procfs_revoke_vnodes(). | 435 | * To interlock with procfs_revoke_vnodes(). | |
436 | */ | 436 | */ | |
437 | mutex_enter(vp->v_interlock); | 437 | mutex_enter(vp->v_interlock); | |
438 | vp->v_data = NULL; | 438 | vp->v_data = NULL; | |
439 | mutex_exit(vp->v_interlock); | 439 | mutex_exit(vp->v_interlock); | |
440 | procfs_hashrem(pfs); | |||
440 | kmem_free(pfs, sizeof(*pfs)); | 441 | kmem_free(pfs, sizeof(*pfs)); | |
441 | return 0; | 442 | return 0; | |
442 | } | 443 | } | |
443 | 444 | |||
444 | /* | 445 | /* | |
445 | * Return POSIX pathconf information applicable to special devices. | 446 | * Return POSIX pathconf information applicable to special devices. | |
446 | */ | 447 | */ | |
447 | int | 448 | int | |
448 | procfs_pathconf(void *v) | 449 | procfs_pathconf(void *v) | |
449 | { | 450 | { | |
450 | struct vop_pathconf_args /* { | 451 | struct vop_pathconf_args /* { | |
451 | struct vnode *a_vp; | 452 | struct vnode *a_vp; | |
452 | int a_name; | 453 | int a_name; |