Thu Aug 29 16:14:37 2019 UTC ()
Pull up following revision(s) (requested by hannken in ticket #1703):

	sys/miscfs/kernfs/kernfs_vnops.c: revision 1.161
	sys/miscfs/procfs/procfs_vnops.c: revision 1.207

Add missing operation VOP_GETPAGES() returning EFAULT.

Without this operation posix_fadvise(..., POSIX_FADV_WILLNEED)
would leave the v_interlock held.

Observed by maxv@


(martin)
diff -r1.154 -r1.154.10.1 src/sys/miscfs/kernfs/kernfs_vnops.c
diff -r1.191 -r1.191.8.1 src/sys/miscfs/procfs/procfs_vnops.c

cvs diff -r1.154 -r1.154.10.1 src/sys/miscfs/kernfs/kernfs_vnops.c (switch to unified diff)

--- src/sys/miscfs/kernfs/kernfs_vnops.c 2014/07/25 08:20:52 1.154
+++ src/sys/miscfs/kernfs/kernfs_vnops.c 2019/08/29 16:14:37 1.154.10.1
@@ -1,1173 +1,1195 @@ @@ -1,1173 +1,1195 @@
1/* $NetBSD: kernfs_vnops.c,v 1.154 2014/07/25 08:20:52 dholland Exp $ */ 1/* $NetBSD: kernfs_vnops.c,v 1.154.10.1 2019/08/29 16:14:37 martin Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1992, 1993 4 * Copyright (c) 1992, 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 donated to Berkeley by 7 * This code is derived from software donated 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.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 * 33 *
34 * @(#)kernfs_vnops.c 8.15 (Berkeley) 5/21/95 34 * @(#)kernfs_vnops.c 8.15 (Berkeley) 5/21/95
35 */ 35 */
36 36
37/* 37/*
38 * Kernel parameter filesystem (/kern) 38 * Kernel parameter filesystem (/kern)
39 */ 39 */
40 40
41#include <sys/cdefs.h> 41#include <sys/cdefs.h>
42__KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.154 2014/07/25 08:20:52 dholland Exp $"); 42__KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.154.10.1 2019/08/29 16:14:37 martin Exp $");
43 43
44#include <sys/param.h> 44#include <sys/param.h>
45#include <sys/systm.h> 45#include <sys/systm.h>
46#include <sys/kernel.h> 46#include <sys/kernel.h>
47#include <sys/vmmeter.h> 47#include <sys/vmmeter.h>
48#include <sys/time.h> 48#include <sys/time.h>
49#include <sys/proc.h> 49#include <sys/proc.h>
50#include <sys/vnode.h> 50#include <sys/vnode.h>
51#include <sys/malloc.h> 51#include <sys/malloc.h>
52#include <sys/file.h> 52#include <sys/file.h>
53#include <sys/stat.h> 53#include <sys/stat.h>
54#include <sys/mount.h> 54#include <sys/mount.h>
55#include <sys/namei.h> 55#include <sys/namei.h>
56#include <sys/buf.h> 56#include <sys/buf.h>
57#include <sys/dirent.h> 57#include <sys/dirent.h>
58#include <sys/msgbuf.h> 58#include <sys/msgbuf.h>
59 59
60#include <miscfs/genfs/genfs.h> 60#include <miscfs/genfs/genfs.h>
61#include <miscfs/kernfs/kernfs.h> 61#include <miscfs/kernfs/kernfs.h>
62#include <miscfs/specfs/specdev.h> 62#include <miscfs/specfs/specdev.h>
63 63
64#include <uvm/uvm_extern.h> 64#include <uvm/uvm_extern.h>
65 65
66#define KSTRING 256 /* Largest I/O available via this filesystem */ 66#define KSTRING 256 /* Largest I/O available via this filesystem */
67#define UIO_MX 32 67#define UIO_MX 32
68 68
69#define READ_MODE (S_IRUSR|S_IRGRP|S_IROTH) 69#define READ_MODE (S_IRUSR|S_IRGRP|S_IROTH)
70#define WRITE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH) 70#define WRITE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
71#define UREAD_MODE (S_IRUSR) 71#define UREAD_MODE (S_IRUSR)
72#define DIR_MODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) 72#define DIR_MODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
73#define UDIR_MODE (S_IRUSR|S_IXUSR) 73#define UDIR_MODE (S_IRUSR|S_IXUSR)
74 74
75#define N(s) sizeof(s)-1, s 75#define N(s) sizeof(s)-1, s
76const struct kern_target kern_targets[] = { 76const struct kern_target kern_targets[] = {
77/* NOTE: The name must be less than UIO_MX-16 chars in length */ 77/* NOTE: The name must be less than UIO_MX-16 chars in length */
78 /* name data tag type ro/rw */ 78 /* name data tag type ro/rw */
79 { DT_DIR, N("."), 0, KFSkern, VDIR, DIR_MODE }, 79 { DT_DIR, N("."), 0, KFSkern, VDIR, DIR_MODE },
80 { DT_DIR, N(".."), 0, KFSroot, VDIR, DIR_MODE }, 80 { DT_DIR, N(".."), 0, KFSroot, VDIR, DIR_MODE },
81 { DT_REG, N("boottime"), &boottime.tv_sec, KFSint, VREG, READ_MODE }, 81 { DT_REG, N("boottime"), &boottime.tv_sec, KFSint, VREG, READ_MODE },
82 /* XXXUNCONST */ 82 /* XXXUNCONST */
83 { DT_REG, N("copyright"), __UNCONST(copyright), 83 { DT_REG, N("copyright"), __UNCONST(copyright),
84 KFSstring, VREG, READ_MODE }, 84 KFSstring, VREG, READ_MODE },
85 { DT_REG, N("hostname"), 0, KFShostname, VREG, WRITE_MODE }, 85 { DT_REG, N("hostname"), 0, KFShostname, VREG, WRITE_MODE },
86 { DT_REG, N("hz"), &hz, KFSint, VREG, READ_MODE }, 86 { DT_REG, N("hz"), &hz, KFSint, VREG, READ_MODE },
87 { DT_REG, N("loadavg"), 0, KFSavenrun, VREG, READ_MODE }, 87 { DT_REG, N("loadavg"), 0, KFSavenrun, VREG, READ_MODE },
88 { DT_REG, N("msgbuf"), 0, KFSmsgbuf, VREG, READ_MODE }, 88 { DT_REG, N("msgbuf"), 0, KFSmsgbuf, VREG, READ_MODE },
89 { DT_REG, N("pagesize"), &uvmexp.pagesize, KFSint, VREG, READ_MODE }, 89 { DT_REG, N("pagesize"), &uvmexp.pagesize, KFSint, VREG, READ_MODE },
90 { DT_REG, N("physmem"), &physmem, KFSint, VREG, READ_MODE }, 90 { DT_REG, N("physmem"), &physmem, KFSint, VREG, READ_MODE },
91#if 0 91#if 0
92 { DT_DIR, N("root"), 0, KFSnull, VDIR, DIR_MODE }, 92 { DT_DIR, N("root"), 0, KFSnull, VDIR, DIR_MODE },
93#endif 93#endif
94 { DT_BLK, N("rootdev"), &rootdev, KFSdevice, VBLK, READ_MODE }, 94 { DT_BLK, N("rootdev"), &rootdev, KFSdevice, VBLK, READ_MODE },
95 { DT_CHR, N("rrootdev"), &rrootdev, KFSdevice, VCHR, READ_MODE }, 95 { DT_CHR, N("rrootdev"), &rrootdev, KFSdevice, VCHR, READ_MODE },
96 { DT_REG, N("time"), 0, KFStime, VREG, READ_MODE }, 96 { DT_REG, N("time"), 0, KFStime, VREG, READ_MODE },
97 /* XXXUNCONST */ 97 /* XXXUNCONST */
98 { DT_REG, N("version"), __UNCONST(version), 98 { DT_REG, N("version"), __UNCONST(version),
99 KFSstring, VREG, READ_MODE }, 99 KFSstring, VREG, READ_MODE },
100}; 100};
101const struct kern_target subdir_targets[] = { 101const struct kern_target subdir_targets[] = {
102/* NOTE: The name must be less than UIO_MX-16 chars in length */ 102/* NOTE: The name must be less than UIO_MX-16 chars in length */
103 /* name data tag type ro/rw */ 103 /* name data tag type ro/rw */
104 { DT_DIR, N("."), 0, KFSsubdir, VDIR, DIR_MODE }, 104 { DT_DIR, N("."), 0, KFSsubdir, VDIR, DIR_MODE },
105 { DT_DIR, N(".."), 0, KFSkern, VDIR, DIR_MODE }, 105 { DT_DIR, N(".."), 0, KFSkern, VDIR, DIR_MODE },
106}; 106};
107#undef N 107#undef N
108SIMPLEQ_HEAD(,dyn_kern_target) dyn_kern_targets = 108SIMPLEQ_HEAD(,dyn_kern_target) dyn_kern_targets =
109 SIMPLEQ_HEAD_INITIALIZER(dyn_kern_targets); 109 SIMPLEQ_HEAD_INITIALIZER(dyn_kern_targets);
110int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]); 110int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
111const int static_nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]); 111const int static_nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
112int nkern_dirs = 2; 112int nkern_dirs = 2;
113 113
114int kernfs_try_fileop(kfstype, kfsfileop, void *, int); 114int kernfs_try_fileop(kfstype, kfsfileop, void *, int);
115int kernfs_try_xread(kfstype, const struct kernfs_node *, char **, 115int kernfs_try_xread(kfstype, const struct kernfs_node *, char **,
116 size_t, int); 116 size_t, int);
117int kernfs_try_xwrite(kfstype, const struct kernfs_node *, char *, 117int kernfs_try_xwrite(kfstype, const struct kernfs_node *, char *,
118 size_t, int); 118 size_t, int);
119 119
120static int kernfs_default_xread(void *v); 120static int kernfs_default_xread(void *v);
121static int kernfs_default_xwrite(void *v); 121static int kernfs_default_xwrite(void *v);
122static int kernfs_default_fileop_getattr(void *); 122static int kernfs_default_fileop_getattr(void *);
123 123
124/* must include all fileop's */ 124/* must include all fileop's */
125const struct kernfs_fileop kernfs_default_fileops[] = { 125const struct kernfs_fileop kernfs_default_fileops[] = {
126 { .kf_fileop = KERNFS_XREAD }, 126 { .kf_fileop = KERNFS_XREAD },
127 { .kf_fileop = KERNFS_XWRITE }, 127 { .kf_fileop = KERNFS_XWRITE },
128 { .kf_fileop = KERNFS_FILEOP_OPEN }, 128 { .kf_fileop = KERNFS_FILEOP_OPEN },
129 { .kf_fileop = KERNFS_FILEOP_GETATTR, 129 { .kf_fileop = KERNFS_FILEOP_GETATTR,
130 .kf_vop = kernfs_default_fileop_getattr }, 130 .kf_vop = kernfs_default_fileop_getattr },
131 { .kf_fileop = KERNFS_FILEOP_IOCTL }, 131 { .kf_fileop = KERNFS_FILEOP_IOCTL },
132 { .kf_fileop = KERNFS_FILEOP_CLOSE }, 132 { .kf_fileop = KERNFS_FILEOP_CLOSE },
133 { .kf_fileop = KERNFS_FILEOP_READ,  133 { .kf_fileop = KERNFS_FILEOP_READ,
134 .kf_vop = kernfs_default_xread }, 134 .kf_vop = kernfs_default_xread },
135 { .kf_fileop = KERNFS_FILEOP_WRITE,  135 { .kf_fileop = KERNFS_FILEOP_WRITE,
136 .kf_vop = kernfs_default_xwrite }, 136 .kf_vop = kernfs_default_xwrite },
137}; 137};
138 138
139int kernfs_lookup(void *); 139int kernfs_lookup(void *);
140#define kernfs_create genfs_eopnotsupp 140#define kernfs_create genfs_eopnotsupp
141#define kernfs_mknod genfs_eopnotsupp 141#define kernfs_mknod genfs_eopnotsupp
142int kernfs_open(void *); 142int kernfs_open(void *);
143int kernfs_close(void *); 143int kernfs_close(void *);
144int kernfs_access(void *); 144int kernfs_access(void *);
145int kernfs_getattr(void *); 145int kernfs_getattr(void *);
146int kernfs_setattr(void *); 146int kernfs_setattr(void *);
147int kernfs_read(void *); 147int kernfs_read(void *);
148int kernfs_write(void *); 148int kernfs_write(void *);
149#define kernfs_fcntl genfs_fcntl 149#define kernfs_fcntl genfs_fcntl
150int kernfs_ioctl(void *); 150int kernfs_ioctl(void *);
151#define kernfs_poll genfs_poll 151#define kernfs_poll genfs_poll
152#define kernfs_revoke genfs_revoke 152#define kernfs_revoke genfs_revoke
153#define kernfs_fsync genfs_nullop 153#define kernfs_fsync genfs_nullop
154#define kernfs_seek genfs_nullop 154#define kernfs_seek genfs_nullop
155#define kernfs_remove genfs_eopnotsupp 155#define kernfs_remove genfs_eopnotsupp
156int kernfs_link(void *); 156int kernfs_link(void *);
157#define kernfs_rename genfs_eopnotsupp 157#define kernfs_rename genfs_eopnotsupp
158#define kernfs_mkdir genfs_eopnotsupp 158#define kernfs_mkdir genfs_eopnotsupp
159#define kernfs_rmdir genfs_eopnotsupp 159#define kernfs_rmdir genfs_eopnotsupp
160int kernfs_symlink(void *); 160int kernfs_symlink(void *);
161int kernfs_readdir(void *); 161int kernfs_readdir(void *);
162#define kernfs_readlink genfs_eopnotsupp 162#define kernfs_readlink genfs_eopnotsupp
163#define kernfs_abortop genfs_abortop 163#define kernfs_abortop genfs_abortop
164int kernfs_inactive(void *); 164int kernfs_inactive(void *);
165int kernfs_reclaim(void *); 165int kernfs_reclaim(void *);
166#define kernfs_lock genfs_lock 166#define kernfs_lock genfs_lock
167#define kernfs_unlock genfs_unlock 167#define kernfs_unlock genfs_unlock
168#define kernfs_bmap genfs_badop 168#define kernfs_bmap genfs_badop
169#define kernfs_strategy genfs_badop 169#define kernfs_strategy genfs_badop
170int kernfs_print(void *); 170int kernfs_print(void *);
171#define kernfs_islocked genfs_islocked 171#define kernfs_islocked genfs_islocked
172int kernfs_pathconf(void *); 172int kernfs_pathconf(void *);
173#define kernfs_advlock genfs_einval 173#define kernfs_advlock genfs_einval
174#define kernfs_bwrite genfs_eopnotsupp 174#define kernfs_bwrite genfs_eopnotsupp
 175int kernfs_getpages(void *);
175#define kernfs_putpages genfs_putpages 176#define kernfs_putpages genfs_putpages
176 177
177static int kernfs_xread(struct kernfs_node *, int, char **, 178static int kernfs_xread(struct kernfs_node *, int, char **,
178 size_t, size_t *); 179 size_t, size_t *);
179static int kernfs_xwrite(const struct kernfs_node *, char *, size_t); 180static int kernfs_xwrite(const struct kernfs_node *, char *, size_t);
180 181
181int (**kernfs_vnodeop_p)(void *); 182int (**kernfs_vnodeop_p)(void *);
182const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = { 183const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
183 { &vop_default_desc, vn_default_error }, 184 { &vop_default_desc, vn_default_error },
184 { &vop_lookup_desc, kernfs_lookup }, /* lookup */ 185 { &vop_lookup_desc, kernfs_lookup }, /* lookup */
185 { &vop_create_desc, kernfs_create }, /* create */ 186 { &vop_create_desc, kernfs_create }, /* create */
186 { &vop_mknod_desc, kernfs_mknod }, /* mknod */ 187 { &vop_mknod_desc, kernfs_mknod }, /* mknod */
187 { &vop_open_desc, kernfs_open }, /* open */ 188 { &vop_open_desc, kernfs_open }, /* open */
188 { &vop_close_desc, kernfs_close }, /* close */ 189 { &vop_close_desc, kernfs_close }, /* close */
189 { &vop_access_desc, kernfs_access }, /* access */ 190 { &vop_access_desc, kernfs_access }, /* access */
190 { &vop_getattr_desc, kernfs_getattr }, /* getattr */ 191 { &vop_getattr_desc, kernfs_getattr }, /* getattr */
191 { &vop_setattr_desc, kernfs_setattr }, /* setattr */ 192 { &vop_setattr_desc, kernfs_setattr }, /* setattr */
192 { &vop_read_desc, kernfs_read }, /* read */ 193 { &vop_read_desc, kernfs_read }, /* read */
193 { &vop_write_desc, kernfs_write }, /* write */ 194 { &vop_write_desc, kernfs_write }, /* write */
194 { &vop_fallocate_desc, genfs_eopnotsupp }, /* fallocate */ 195 { &vop_fallocate_desc, genfs_eopnotsupp }, /* fallocate */
195 { &vop_fdiscard_desc, genfs_eopnotsupp }, /* fdiscard */ 196 { &vop_fdiscard_desc, genfs_eopnotsupp }, /* fdiscard */
196 { &vop_fcntl_desc, kernfs_fcntl }, /* fcntl */ 197 { &vop_fcntl_desc, kernfs_fcntl }, /* fcntl */
197 { &vop_ioctl_desc, kernfs_ioctl }, /* ioctl */ 198 { &vop_ioctl_desc, kernfs_ioctl }, /* ioctl */
198 { &vop_poll_desc, kernfs_poll }, /* poll */ 199 { &vop_poll_desc, kernfs_poll }, /* poll */
199 { &vop_revoke_desc, kernfs_revoke }, /* revoke */ 200 { &vop_revoke_desc, kernfs_revoke }, /* revoke */
200 { &vop_fsync_desc, kernfs_fsync }, /* fsync */ 201 { &vop_fsync_desc, kernfs_fsync }, /* fsync */
201 { &vop_seek_desc, kernfs_seek }, /* seek */ 202 { &vop_seek_desc, kernfs_seek }, /* seek */
202 { &vop_remove_desc, kernfs_remove }, /* remove */ 203 { &vop_remove_desc, kernfs_remove }, /* remove */
203 { &vop_link_desc, kernfs_link }, /* link */ 204 { &vop_link_desc, kernfs_link }, /* link */
204 { &vop_rename_desc, kernfs_rename }, /* rename */ 205 { &vop_rename_desc, kernfs_rename }, /* rename */
205 { &vop_mkdir_desc, kernfs_mkdir }, /* mkdir */ 206 { &vop_mkdir_desc, kernfs_mkdir }, /* mkdir */
206 { &vop_rmdir_desc, kernfs_rmdir }, /* rmdir */ 207 { &vop_rmdir_desc, kernfs_rmdir }, /* rmdir */
207 { &vop_symlink_desc, kernfs_symlink }, /* symlink */ 208 { &vop_symlink_desc, kernfs_symlink }, /* symlink */
208 { &vop_readdir_desc, kernfs_readdir }, /* readdir */ 209 { &vop_readdir_desc, kernfs_readdir }, /* readdir */
209 { &vop_readlink_desc, kernfs_readlink }, /* readlink */ 210 { &vop_readlink_desc, kernfs_readlink }, /* readlink */
210 { &vop_abortop_desc, kernfs_abortop }, /* abortop */ 211 { &vop_abortop_desc, kernfs_abortop }, /* abortop */
211 { &vop_inactive_desc, kernfs_inactive }, /* inactive */ 212 { &vop_inactive_desc, kernfs_inactive }, /* inactive */
212 { &vop_reclaim_desc, kernfs_reclaim }, /* reclaim */ 213 { &vop_reclaim_desc, kernfs_reclaim }, /* reclaim */
213 { &vop_lock_desc, kernfs_lock }, /* lock */ 214 { &vop_lock_desc, kernfs_lock }, /* lock */
214 { &vop_unlock_desc, kernfs_unlock }, /* unlock */ 215 { &vop_unlock_desc, kernfs_unlock }, /* unlock */
215 { &vop_bmap_desc, kernfs_bmap }, /* bmap */ 216 { &vop_bmap_desc, kernfs_bmap }, /* bmap */
216 { &vop_strategy_desc, kernfs_strategy }, /* strategy */ 217 { &vop_strategy_desc, kernfs_strategy }, /* strategy */
217 { &vop_print_desc, kernfs_print }, /* print */ 218 { &vop_print_desc, kernfs_print }, /* print */
218 { &vop_islocked_desc, kernfs_islocked }, /* islocked */ 219 { &vop_islocked_desc, kernfs_islocked }, /* islocked */
219 { &vop_pathconf_desc, kernfs_pathconf }, /* pathconf */ 220 { &vop_pathconf_desc, kernfs_pathconf }, /* pathconf */
220 { &vop_advlock_desc, kernfs_advlock }, /* advlock */ 221 { &vop_advlock_desc, kernfs_advlock }, /* advlock */
221 { &vop_bwrite_desc, kernfs_bwrite }, /* bwrite */ 222 { &vop_bwrite_desc, kernfs_bwrite }, /* bwrite */
 223 { &vop_getpages_desc, kernfs_getpages }, /* getpages */
222 { &vop_putpages_desc, kernfs_putpages }, /* putpages */ 224 { &vop_putpages_desc, kernfs_putpages }, /* putpages */
223 { NULL, NULL } 225 { NULL, NULL }
224}; 226};
225const struct vnodeopv_desc kernfs_vnodeop_opv_desc = 227const struct vnodeopv_desc kernfs_vnodeop_opv_desc =
226 { &kernfs_vnodeop_p, kernfs_vnodeop_entries }; 228 { &kernfs_vnodeop_p, kernfs_vnodeop_entries };
227 229
228static inline int 230static inline int
229kernfs_fileop_compare(struct kernfs_fileop *a, struct kernfs_fileop *b) 231kernfs_fileop_compare(struct kernfs_fileop *a, struct kernfs_fileop *b)
230{ 232{
231 if (a->kf_type < b->kf_type) 233 if (a->kf_type < b->kf_type)
232 return -1; 234 return -1;
233 if (a->kf_type > b->kf_type) 235 if (a->kf_type > b->kf_type)
234 return 1; 236 return 1;
235 if (a->kf_fileop < b->kf_fileop) 237 if (a->kf_fileop < b->kf_fileop)
236 return -1; 238 return -1;
237 if (a->kf_fileop > b->kf_fileop) 239 if (a->kf_fileop > b->kf_fileop)
238 return 1; 240 return 1;
239 return (0); 241 return (0);
240} 242}
241 243
242SPLAY_HEAD(kfsfileoptree, kernfs_fileop) kfsfileoptree = 244SPLAY_HEAD(kfsfileoptree, kernfs_fileop) kfsfileoptree =
243 SPLAY_INITIALIZER(kfsfileoptree); 245 SPLAY_INITIALIZER(kfsfileoptree);
244SPLAY_PROTOTYPE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare); 246SPLAY_PROTOTYPE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
245SPLAY_GENERATE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare); 247SPLAY_GENERATE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare);
246 248
247kfstype 249kfstype
248kernfs_alloctype(int nkf, const struct kernfs_fileop *kf) 250kernfs_alloctype(int nkf, const struct kernfs_fileop *kf)
249{ 251{
250 static u_char nextfreetype = KFSlasttype; 252 static u_char nextfreetype = KFSlasttype;
251 struct kernfs_fileop *dkf, *fkf, skf; 253 struct kernfs_fileop *dkf, *fkf, skf;
252 int i; 254 int i;
253 255
254 /* XXX need to keep track of dkf's memory if we support 256 /* XXX need to keep track of dkf's memory if we support
255 deallocating types */ 257 deallocating types */
256 dkf = malloc(sizeof(kernfs_default_fileops), M_TEMP, M_WAITOK); 258 dkf = malloc(sizeof(kernfs_default_fileops), M_TEMP, M_WAITOK);
257 memcpy(dkf, kernfs_default_fileops, sizeof(kernfs_default_fileops)); 259 memcpy(dkf, kernfs_default_fileops, sizeof(kernfs_default_fileops));
258 260
259 for (i = 0; i < sizeof(kernfs_default_fileops) / 261 for (i = 0; i < sizeof(kernfs_default_fileops) /
260 sizeof(kernfs_default_fileops[0]); i++) { 262 sizeof(kernfs_default_fileops[0]); i++) {
261 dkf[i].kf_type = nextfreetype; 263 dkf[i].kf_type = nextfreetype;
262 SPLAY_INSERT(kfsfileoptree, &kfsfileoptree, &dkf[i]); 264 SPLAY_INSERT(kfsfileoptree, &kfsfileoptree, &dkf[i]);
263 } 265 }
264 266
265 for (i = 0; i < nkf; i++) { 267 for (i = 0; i < nkf; i++) {
266 skf.kf_type = nextfreetype; 268 skf.kf_type = nextfreetype;
267 skf.kf_fileop = kf[i].kf_fileop; 269 skf.kf_fileop = kf[i].kf_fileop;
268 if ((fkf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf))) 270 if ((fkf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
269 fkf->kf_vop = kf[i].kf_vop; 271 fkf->kf_vop = kf[i].kf_vop;
270 } 272 }
271 273
272 return nextfreetype++; 274 return nextfreetype++;
273} 275}
274 276
275int 277int
276kernfs_try_fileop(kfstype type, kfsfileop fileop, void *v, int error) 278kernfs_try_fileop(kfstype type, kfsfileop fileop, void *v, int error)
277{ 279{
278 struct kernfs_fileop *kf, skf; 280 struct kernfs_fileop *kf, skf;
279 281
280 skf.kf_type = type; 282 skf.kf_type = type;
281 skf.kf_fileop = fileop; 283 skf.kf_fileop = fileop;
282 if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf))) 284 if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
283 if (kf->kf_vop) 285 if (kf->kf_vop)
284 return kf->kf_vop(v); 286 return kf->kf_vop(v);
285 return error; 287 return error;
286} 288}
287 289
288int 290int
289kernfs_try_xread(kfstype type, const struct kernfs_node *kfs, char **bfp, 291kernfs_try_xread(kfstype type, const struct kernfs_node *kfs, char **bfp,
290 size_t len, int error) 292 size_t len, int error)
291{ 293{
292 struct kernfs_fileop *kf, skf; 294 struct kernfs_fileop *kf, skf;
293 295
294 skf.kf_type = type; 296 skf.kf_type = type;
295 skf.kf_fileop = KERNFS_XREAD; 297 skf.kf_fileop = KERNFS_XREAD;
296 if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf))) 298 if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
297 if (kf->kf_xread) 299 if (kf->kf_xread)
298 return kf->kf_xread(kfs, bfp, len); 300 return kf->kf_xread(kfs, bfp, len);
299 return error; 301 return error;
300} 302}
301 303
302int 304int
303kernfs_try_xwrite(kfstype type, const struct kernfs_node *kfs, char *bf, 305kernfs_try_xwrite(kfstype type, const struct kernfs_node *kfs, char *bf,
304 size_t len, int error) 306 size_t len, int error)
305{ 307{
306 struct kernfs_fileop *kf, skf; 308 struct kernfs_fileop *kf, skf;
307 309
308 skf.kf_type = type; 310 skf.kf_type = type;
309 skf.kf_fileop = KERNFS_XWRITE; 311 skf.kf_fileop = KERNFS_XWRITE;
310 if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf))) 312 if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf)))
311 if (kf->kf_xwrite) 313 if (kf->kf_xwrite)
312 return kf->kf_xwrite(kfs, bf, len); 314 return kf->kf_xwrite(kfs, bf, len);
313 return error; 315 return error;
314} 316}
315 317
316int 318int
317kernfs_addentry(kernfs_parentdir_t *pkt, kernfs_entry_t *dkt) 319kernfs_addentry(kernfs_parentdir_t *pkt, kernfs_entry_t *dkt)
318{ 320{
319 struct kernfs_subdir *ks, *parent; 321 struct kernfs_subdir *ks, *parent;
320 322
321 if (pkt == NULL) { 323 if (pkt == NULL) {
322 SIMPLEQ_INSERT_TAIL(&dyn_kern_targets, dkt, dkt_queue); 324 SIMPLEQ_INSERT_TAIL(&dyn_kern_targets, dkt, dkt_queue);
323 nkern_targets++; 325 nkern_targets++;
324 if (dkt->dkt_kt.kt_vtype == VDIR) 326 if (dkt->dkt_kt.kt_vtype == VDIR)
325 nkern_dirs++; 327 nkern_dirs++;
326 } else { 328 } else {
327 parent = (struct kernfs_subdir *)pkt->kt_data; 329 parent = (struct kernfs_subdir *)pkt->kt_data;
328 SIMPLEQ_INSERT_TAIL(&parent->ks_entries, dkt, dkt_queue); 330 SIMPLEQ_INSERT_TAIL(&parent->ks_entries, dkt, dkt_queue);
329 parent->ks_nentries++; 331 parent->ks_nentries++;
330 if (dkt->dkt_kt.kt_vtype == VDIR) 332 if (dkt->dkt_kt.kt_vtype == VDIR)
331 parent->ks_dirs++; 333 parent->ks_dirs++;
332 } 334 }
333 if (dkt->dkt_kt.kt_vtype == VDIR && dkt->dkt_kt.kt_data == NULL) { 335 if (dkt->dkt_kt.kt_vtype == VDIR && dkt->dkt_kt.kt_data == NULL) {
334 ks = malloc(sizeof(struct kernfs_subdir), 336 ks = malloc(sizeof(struct kernfs_subdir),
335 M_TEMP, M_WAITOK); 337 M_TEMP, M_WAITOK);
336 SIMPLEQ_INIT(&ks->ks_entries); 338 SIMPLEQ_INIT(&ks->ks_entries);
337 ks->ks_nentries = 2; /* . and .. */ 339 ks->ks_nentries = 2; /* . and .. */
338 ks->ks_dirs = 2; 340 ks->ks_dirs = 2;
339 ks->ks_parent = pkt ? pkt : &kern_targets[0]; 341 ks->ks_parent = pkt ? pkt : &kern_targets[0];
340 dkt->dkt_kt.kt_data = ks; 342 dkt->dkt_kt.kt_data = ks;
341 } 343 }
342 return 0; 344 return 0;
343} 345}
344 346
345static int 347static int
346kernfs_xread(struct kernfs_node *kfs, int off, char **bufp, size_t len, size_t *wrlen) 348kernfs_xread(struct kernfs_node *kfs, int off, char **bufp, size_t len, size_t *wrlen)
347{ 349{
348 const struct kern_target *kt; 350 const struct kern_target *kt;
349 int err; 351 int err;
350 352
351 kt = kfs->kfs_kt; 353 kt = kfs->kfs_kt;
352 354
353 switch (kfs->kfs_type) { 355 switch (kfs->kfs_type) {
354 case KFStime: { 356 case KFStime: {
355 struct timeval tv; 357 struct timeval tv;
356 358
357 microtime(&tv); 359 microtime(&tv);
358 snprintf(*bufp, len, "%lld %ld\n", (long long)tv.tv_sec, 360 snprintf(*bufp, len, "%lld %ld\n", (long long)tv.tv_sec,
359 (long)tv.tv_usec); 361 (long)tv.tv_usec);
360 break; 362 break;
361 } 363 }
362 364
363 case KFSint: { 365 case KFSint: {
364 int *ip = kt->kt_data; 366 int *ip = kt->kt_data;
365 367
366 snprintf(*bufp, len, "%d\n", *ip); 368 snprintf(*bufp, len, "%d\n", *ip);
367 break; 369 break;
368 } 370 }
369 371
370 case KFSstring: { 372 case KFSstring: {
371 char *cp = kt->kt_data; 373 char *cp = kt->kt_data;
372 374
373 *bufp = cp; 375 *bufp = cp;
374 break; 376 break;
375 } 377 }
376 378
377 case KFSmsgbuf: { 379 case KFSmsgbuf: {
378 long n; 380 long n;
379 381
380 /* 382 /*
381 * deal with cases where the message buffer has 383 * deal with cases where the message buffer has
382 * become corrupted. 384 * become corrupted.
383 */ 385 */
384 if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) { 386 if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
385 msgbufenabled = 0; 387 msgbufenabled = 0;
386 return (ENXIO); 388 return (ENXIO);
387 } 389 }
388 390
389 /* 391 /*
390 * Note that reads of /kern/msgbuf won't necessarily yield 392 * Note that reads of /kern/msgbuf won't necessarily yield
391 * consistent results, if the message buffer is modified 393 * consistent results, if the message buffer is modified
392 * while the read is in progress. The worst that can happen 394 * while the read is in progress. The worst that can happen
393 * is that incorrect data will be read. There's no way 395 * is that incorrect data will be read. There's no way
394 * that this can crash the system unless the values in the 396 * that this can crash the system unless the values in the
395 * message buffer header are corrupted, but that'll cause 397 * message buffer header are corrupted, but that'll cause
396 * the system to die anyway. 398 * the system to die anyway.
397 */ 399 */
398 if (off >= msgbufp->msg_bufs) { 400 if (off >= msgbufp->msg_bufs) {
399 *wrlen = 0; 401 *wrlen = 0;
400 return (0); 402 return (0);
401 } 403 }
402 n = msgbufp->msg_bufx + off; 404 n = msgbufp->msg_bufx + off;
403 if (n >= msgbufp->msg_bufs) 405 if (n >= msgbufp->msg_bufs)
404 n -= msgbufp->msg_bufs; 406 n -= msgbufp->msg_bufs;
405 len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off); 407 len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off);
406 *bufp = msgbufp->msg_bufc + n; 408 *bufp = msgbufp->msg_bufc + n;
407 *wrlen = len; 409 *wrlen = len;
408 return (0); 410 return (0);
409 } 411 }
410 412
411 case KFShostname: { 413 case KFShostname: {
412 char *cp = hostname; 414 char *cp = hostname;
413 size_t xlen = hostnamelen; 415 size_t xlen = hostnamelen;
414 416
415 if (xlen >= (len - 2)) 417 if (xlen >= (len - 2))
416 return (EINVAL); 418 return (EINVAL);
417 419
418 memcpy(*bufp, cp, xlen); 420 memcpy(*bufp, cp, xlen);
419 (*bufp)[xlen] = '\n'; 421 (*bufp)[xlen] = '\n';
420 (*bufp)[xlen+1] = '\0'; 422 (*bufp)[xlen+1] = '\0';
421 break; 423 break;
422 } 424 }
423 425
424 case KFSavenrun: 426 case KFSavenrun:
425 averunnable.fscale = FSCALE; 427 averunnable.fscale = FSCALE;
426 snprintf(*bufp, len, "%d %d %d %ld\n", 428 snprintf(*bufp, len, "%d %d %d %ld\n",
427 averunnable.ldavg[0], averunnable.ldavg[1], 429 averunnable.ldavg[0], averunnable.ldavg[1],
428 averunnable.ldavg[2], averunnable.fscale); 430 averunnable.ldavg[2], averunnable.fscale);
429 break; 431 break;
430 432
431 default: 433 default:
432 err = kernfs_try_xread(kfs->kfs_type, kfs, bufp, len, 434 err = kernfs_try_xread(kfs->kfs_type, kfs, bufp, len,
433 EOPNOTSUPP); 435 EOPNOTSUPP);
434 if (err) 436 if (err)
435 return err; 437 return err;
436 } 438 }
437 439
438 len = strlen(*bufp); 440 len = strlen(*bufp);
439 if (len <= off) 441 if (len <= off)
440 *wrlen = 0; 442 *wrlen = 0;
441 else { 443 else {
442 *bufp += off; 444 *bufp += off;
443 *wrlen = len - off; 445 *wrlen = len - off;
444 } 446 }
445 return (0); 447 return (0);
446} 448}
447 449
448static int 450static int
449kernfs_xwrite(const struct kernfs_node *kfs, char *bf, size_t len) 451kernfs_xwrite(const struct kernfs_node *kfs, char *bf, size_t len)
450{ 452{
451 453
452 switch (kfs->kfs_type) { 454 switch (kfs->kfs_type) {
453 case KFShostname: 455 case KFShostname:
454 if (bf[len-1] == '\n') 456 if (bf[len-1] == '\n')
455 --len; 457 --len;
456 memcpy(hostname, bf, len); 458 memcpy(hostname, bf, len);
457 hostname[len] = '\0'; 459 hostname[len] = '\0';
458 hostnamelen = (size_t) len; 460 hostnamelen = (size_t) len;
459 return (0); 461 return (0);
460 462
461 default: 463 default:
462 return kernfs_try_xwrite(kfs->kfs_type, kfs, bf, len, EIO); 464 return kernfs_try_xwrite(kfs->kfs_type, kfs, bf, len, EIO);
463 } 465 }
464} 466}
465 467
466 468
467/* 469/*
468 * vp is the current namei directory 470 * vp is the current namei directory
469 * ndp is the name to locate in that directory... 471 * ndp is the name to locate in that directory...
470 */ 472 */
471int 473int
472kernfs_lookup(void *v) 474kernfs_lookup(void *v)
473{ 475{
474 struct vop_lookup_v2_args /* { 476 struct vop_lookup_v2_args /* {
475 struct vnode * a_dvp; 477 struct vnode * a_dvp;
476 struct vnode ** a_vpp; 478 struct vnode ** a_vpp;
477 struct componentname * a_cnp; 479 struct componentname * a_cnp;
478 } */ *ap = v; 480 } */ *ap = v;
479 struct componentname *cnp = ap->a_cnp; 481 struct componentname *cnp = ap->a_cnp;
480 struct vnode **vpp = ap->a_vpp; 482 struct vnode **vpp = ap->a_vpp;
481 struct vnode *dvp = ap->a_dvp; 483 struct vnode *dvp = ap->a_dvp;
482 const char *pname = cnp->cn_nameptr; 484 const char *pname = cnp->cn_nameptr;
483 const struct kernfs_node *kfs; 485 const struct kernfs_node *kfs;
484 const struct kern_target *kt; 486 const struct kern_target *kt;
485 const struct dyn_kern_target *dkt; 487 const struct dyn_kern_target *dkt;
486 const struct kernfs_subdir *ks; 488 const struct kernfs_subdir *ks;
487 int error, i; 489 int error, i;
488 490
489 *vpp = NULLVP; 491 *vpp = NULLVP;
490 492
491 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) 493 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
492 return (EROFS); 494 return (EROFS);
493 495
494 if (cnp->cn_namelen == 1 && *pname == '.') { 496 if (cnp->cn_namelen == 1 && *pname == '.') {
495 *vpp = dvp; 497 *vpp = dvp;
496 vref(dvp); 498 vref(dvp);
497 return (0); 499 return (0);
498 } 500 }
499 501
500 kfs = VTOKERN(dvp); 502 kfs = VTOKERN(dvp);
501 switch (kfs->kfs_type) { 503 switch (kfs->kfs_type) {
502 case KFSkern: 504 case KFSkern:
503 /* 505 /*
504 * Shouldn't get here with .. in the root node. 506 * Shouldn't get here with .. in the root node.
505 */ 507 */
506 if (cnp->cn_flags & ISDOTDOT) 508 if (cnp->cn_flags & ISDOTDOT)
507 return (EIO); 509 return (EIO);
508 510
509 for (i = 0; i < static_nkern_targets; i++) { 511 for (i = 0; i < static_nkern_targets; i++) {
510 kt = &kern_targets[i]; 512 kt = &kern_targets[i];
511 if (cnp->cn_namelen == kt->kt_namlen && 513 if (cnp->cn_namelen == kt->kt_namlen &&
512 memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0) 514 memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0)
513 goto found; 515 goto found;
514 } 516 }
515 SIMPLEQ_FOREACH(dkt, &dyn_kern_targets, dkt_queue) { 517 SIMPLEQ_FOREACH(dkt, &dyn_kern_targets, dkt_queue) {
516 if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen && 518 if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
517 memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) { 519 memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
518 kt = &dkt->dkt_kt; 520 kt = &dkt->dkt_kt;
519 goto found; 521 goto found;
520 } 522 }
521 } 523 }
522 break; 524 break;
523 525
524 found: 526 found:
525 error = vcache_get(dvp->v_mount, &kt, sizeof(kt), vpp); 527 error = vcache_get(dvp->v_mount, &kt, sizeof(kt), vpp);
526 return error; 528 return error;
527 529
528 case KFSsubdir: 530 case KFSsubdir:
529 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data; 531 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
530 if (cnp->cn_flags & ISDOTDOT) { 532 if (cnp->cn_flags & ISDOTDOT) {
531 kt = ks->ks_parent; 533 kt = ks->ks_parent;
532 goto found; 534 goto found;
533 } 535 }
534 536
535 SIMPLEQ_FOREACH(dkt, &ks->ks_entries, dkt_queue) { 537 SIMPLEQ_FOREACH(dkt, &ks->ks_entries, dkt_queue) {
536 if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen && 538 if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen &&
537 memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) { 539 memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) {
538 kt = &dkt->dkt_kt; 540 kt = &dkt->dkt_kt;
539 goto found; 541 goto found;
540 } 542 }
541 } 543 }
542 break; 544 break;
543 545
544 default: 546 default:
545 return (ENOTDIR); 547 return (ENOTDIR);
546 } 548 }
547 549
548 return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS); 550 return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
549} 551}
550 552
551int 553int
552kernfs_open(void *v) 554kernfs_open(void *v)
553{ 555{
554 struct vop_open_args /* { 556 struct vop_open_args /* {
555 struct vnode *a_vp; 557 struct vnode *a_vp;
556 int a_mode; 558 int a_mode;
557 kauth_cred_t a_cred; 559 kauth_cred_t a_cred;
558 } */ *ap = v; 560 } */ *ap = v;
559 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 561 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
560 562
561 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_OPEN, v, 0); 563 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_OPEN, v, 0);
562} 564}
563 565
564int 566int
565kernfs_close(void *v) 567kernfs_close(void *v)
566{ 568{
567 struct vop_close_args /* { 569 struct vop_close_args /* {
568 struct vnode *a_vp; 570 struct vnode *a_vp;
569 int a_fflag; 571 int a_fflag;
570 kauth_cred_t a_cred; 572 kauth_cred_t a_cred;
571 } */ *ap = v; 573 } */ *ap = v;
572 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 574 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
573 575
574 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_CLOSE, v, 0); 576 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_CLOSE, v, 0);
575} 577}
576 578
577int 579int
578kernfs_access(void *v) 580kernfs_access(void *v)
579{ 581{
580 struct vop_access_args /* { 582 struct vop_access_args /* {
581 struct vnode *a_vp; 583 struct vnode *a_vp;
582 int a_mode; 584 int a_mode;
583 kauth_cred_t a_cred; 585 kauth_cred_t a_cred;
584 } */ *ap = v; 586 } */ *ap = v;
585 struct vattr va; 587 struct vattr va;
586 int error; 588 int error;
587 589
588 if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred)) != 0) 590 if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred)) != 0)
589 return (error); 591 return (error);
590 592
591 return kauth_authorize_vnode(ap->a_cred, 593 return kauth_authorize_vnode(ap->a_cred,
592 KAUTH_ACCESS_ACTION(ap->a_mode, ap->a_vp->v_type, va.va_mode), 594 KAUTH_ACCESS_ACTION(ap->a_mode, ap->a_vp->v_type, va.va_mode),
593 ap->a_vp, NULL, genfs_can_access(va.va_type, va.va_mode, 595 ap->a_vp, NULL, genfs_can_access(va.va_type, va.va_mode,
594 va.va_uid, va.va_gid, ap->a_mode, ap->a_cred)); 596 va.va_uid, va.va_gid, ap->a_mode, ap->a_cred));
595} 597}
596 598
597static int 599static int
598kernfs_default_fileop_getattr(void *v) 600kernfs_default_fileop_getattr(void *v)
599{ 601{
600 struct vop_getattr_args /* { 602 struct vop_getattr_args /* {
601 struct vnode *a_vp; 603 struct vnode *a_vp;
602 struct vattr *a_vap; 604 struct vattr *a_vap;
603 kauth_cred_t a_cred; 605 kauth_cred_t a_cred;
604 } */ *ap = v; 606 } */ *ap = v;
605 struct vattr *vap = ap->a_vap; 607 struct vattr *vap = ap->a_vap;
606 608
607 vap->va_nlink = 1; 609 vap->va_nlink = 1;
608 vap->va_bytes = vap->va_size = 0; 610 vap->va_bytes = vap->va_size = 0;
609 611
610 return 0; 612 return 0;
611} 613}
612 614
613int 615int
614kernfs_getattr(void *v) 616kernfs_getattr(void *v)
615{ 617{
616 struct vop_getattr_args /* { 618 struct vop_getattr_args /* {
617 struct vnode *a_vp; 619 struct vnode *a_vp;
618 struct vattr *a_vap; 620 struct vattr *a_vap;
619 kauth_cred_t a_cred; 621 kauth_cred_t a_cred;
620 } */ *ap = v; 622 } */ *ap = v;
621 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 623 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
622 struct kernfs_subdir *ks; 624 struct kernfs_subdir *ks;
623 struct vattr *vap = ap->a_vap; 625 struct vattr *vap = ap->a_vap;
624 int error = 0; 626 int error = 0;
625 char strbuf[KSTRING], *bf; 627 char strbuf[KSTRING], *bf;
626 size_t nread, total; 628 size_t nread, total;
627 629
628 vattr_null(vap); 630 vattr_null(vap);
629 vap->va_type = ap->a_vp->v_type; 631 vap->va_type = ap->a_vp->v_type;
630 vap->va_uid = 0; 632 vap->va_uid = 0;
631 vap->va_gid = 0; 633 vap->va_gid = 0;
632 vap->va_mode = kfs->kfs_mode; 634 vap->va_mode = kfs->kfs_mode;
633 vap->va_fileid = kfs->kfs_fileno; 635 vap->va_fileid = kfs->kfs_fileno;
634 vap->va_flags = 0; 636 vap->va_flags = 0;
635 vap->va_size = 0; 637 vap->va_size = 0;
636 vap->va_blocksize = DEV_BSIZE; 638 vap->va_blocksize = DEV_BSIZE;
637 /* Make all times be current TOD, except for the "boottime" node. */ 639 /* Make all times be current TOD, except for the "boottime" node. */
638 if (kfs->kfs_kt->kt_namlen == 8 && 640 if (kfs->kfs_kt->kt_namlen == 8 &&
639 !memcmp(kfs->kfs_kt->kt_name, "boottime", 8)) { 641 !memcmp(kfs->kfs_kt->kt_name, "boottime", 8)) {
640 vap->va_ctime = boottime; 642 vap->va_ctime = boottime;
641 } else { 643 } else {
642 getnanotime(&vap->va_ctime); 644 getnanotime(&vap->va_ctime);
643 } 645 }
644 vap->va_atime = vap->va_mtime = vap->va_ctime; 646 vap->va_atime = vap->va_mtime = vap->va_ctime;
645 vap->va_gen = 0; 647 vap->va_gen = 0;
646 vap->va_flags = 0; 648 vap->va_flags = 0;
647 vap->va_rdev = 0; 649 vap->va_rdev = 0;
648 vap->va_bytes = 0; 650 vap->va_bytes = 0;
649 651
650 switch (kfs->kfs_type) { 652 switch (kfs->kfs_type) {
651 case KFSkern: 653 case KFSkern:
652 vap->va_nlink = nkern_dirs; 654 vap->va_nlink = nkern_dirs;
653 vap->va_bytes = vap->va_size = DEV_BSIZE; 655 vap->va_bytes = vap->va_size = DEV_BSIZE;
654 break; 656 break;
655 657
656 case KFSdevice: 658 case KFSdevice:
657 vap->va_nlink = 1; 659 vap->va_nlink = 1;
658 vap->va_rdev = ap->a_vp->v_rdev; 660 vap->va_rdev = ap->a_vp->v_rdev;
659 break; 661 break;
660 662
661 case KFSroot: 663 case KFSroot:
662 vap->va_nlink = 1; 664 vap->va_nlink = 1;
663 vap->va_bytes = vap->va_size = DEV_BSIZE; 665 vap->va_bytes = vap->va_size = DEV_BSIZE;
664 break; 666 break;
665 667
666 case KFSsubdir: 668 case KFSsubdir:
667 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data; 669 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
668 vap->va_nlink = ks->ks_dirs; 670 vap->va_nlink = ks->ks_dirs;
669 vap->va_bytes = vap->va_size = DEV_BSIZE; 671 vap->va_bytes = vap->va_size = DEV_BSIZE;
670 break; 672 break;
671 673
672 case KFSnull: 674 case KFSnull:
673 case KFStime: 675 case KFStime:
674 case KFSint: 676 case KFSint:
675 case KFSstring: 677 case KFSstring:
676 case KFShostname: 678 case KFShostname:
677 case KFSavenrun: 679 case KFSavenrun:
678 case KFSmsgbuf: 680 case KFSmsgbuf:
679 vap->va_nlink = 1; 681 vap->va_nlink = 1;
680 total = 0; 682 total = 0;
681 do { 683 do {
682 bf = strbuf; 684 bf = strbuf;
683 error = kernfs_xread(kfs, total, &bf, 685 error = kernfs_xread(kfs, total, &bf,
684 sizeof(strbuf), &nread); 686 sizeof(strbuf), &nread);
685 total += nread; 687 total += nread;
686 } while (error == 0 && nread != 0); 688 } while (error == 0 && nread != 0);
687 vap->va_bytes = vap->va_size = total; 689 vap->va_bytes = vap->va_size = total;
688 break; 690 break;
689 691
690 default: 692 default:
691 error = kernfs_try_fileop(kfs->kfs_type, 693 error = kernfs_try_fileop(kfs->kfs_type,
692 KERNFS_FILEOP_GETATTR, v, EINVAL); 694 KERNFS_FILEOP_GETATTR, v, EINVAL);
693 break; 695 break;
694 } 696 }
695 697
696 return (error); 698 return (error);
697} 699}
698 700
699/*ARGSUSED*/ 701/*ARGSUSED*/
700int 702int
701kernfs_setattr(void *v) 703kernfs_setattr(void *v)
702{ 704{
703 705
704 /* 706 /*
705 * Silently ignore attribute changes. 707 * Silently ignore attribute changes.
706 * This allows for open with truncate to have no 708 * This allows for open with truncate to have no
707 * effect until some data is written. I want to 709 * effect until some data is written. I want to
708 * do it this way because all writes are atomic. 710 * do it this way because all writes are atomic.
709 */ 711 */
710 return (0); 712 return (0);
711} 713}
712 714
713int 715int
714kernfs_default_xread(void *v) 716kernfs_default_xread(void *v)
715{ 717{
716 struct vop_read_args /* { 718 struct vop_read_args /* {
717 struct vnode *a_vp; 719 struct vnode *a_vp;
718 struct uio *a_uio; 720 struct uio *a_uio;
719 int a_ioflag; 721 int a_ioflag;
720 kauth_cred_t a_cred; 722 kauth_cred_t a_cred;
721 } */ *ap = v; 723 } */ *ap = v;
722 struct uio *uio = ap->a_uio; 724 struct uio *uio = ap->a_uio;
723 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 725 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
724 char strbuf[KSTRING], *bf; 726 char strbuf[KSTRING], *bf;
725 int off; 727 int off;
726 size_t len; 728 size_t len;
727 int error; 729 int error;
728 730
729 if (ap->a_vp->v_type == VDIR) 731 if (ap->a_vp->v_type == VDIR)
730 return EISDIR; 732 return EISDIR;
731 733
732 off = (int)uio->uio_offset; 734 off = (int)uio->uio_offset;
733 /* Don't allow negative offsets */ 735 /* Don't allow negative offsets */
734 if (off < 0) 736 if (off < 0)
735 return EINVAL; 737 return EINVAL;
736 738
737 bf = strbuf; 739 bf = strbuf;
738 if ((error = kernfs_xread(kfs, off, &bf, sizeof(strbuf), &len)) == 0) 740 if ((error = kernfs_xread(kfs, off, &bf, sizeof(strbuf), &len)) == 0)
739 error = uiomove(bf, len, uio); 741 error = uiomove(bf, len, uio);
740 return (error); 742 return (error);
741} 743}
742 744
743int 745int
744kernfs_read(void *v) 746kernfs_read(void *v)
745{ 747{
746 struct vop_read_args /* { 748 struct vop_read_args /* {
747 struct vnode *a_vp; 749 struct vnode *a_vp;
748 struct uio *a_uio; 750 struct uio *a_uio;
749 int a_ioflag; 751 int a_ioflag;
750 struct ucred *a_cred; 752 struct ucred *a_cred;
751 } */ *ap = v; 753 } */ *ap = v;
752 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 754 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
753 755
754 if (kfs->kfs_type < KFSlasttype) { 756 if (kfs->kfs_type < KFSlasttype) {
755 /* use default function */ 757 /* use default function */
756 return kernfs_default_xread(v); 758 return kernfs_default_xread(v);
757 } 759 }
758 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_READ, v, 760 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_READ, v,
759 EOPNOTSUPP); 761 EOPNOTSUPP);
760} 762}
761 763
762static int 764static int
763kernfs_default_xwrite(void *v) 765kernfs_default_xwrite(void *v)
764{ 766{
765 struct vop_write_args /* { 767 struct vop_write_args /* {
766 struct vnode *a_vp; 768 struct vnode *a_vp;
767 struct uio *a_uio; 769 struct uio *a_uio;
768 int a_ioflag; 770 int a_ioflag;
769 kauth_cred_t a_cred; 771 kauth_cred_t a_cred;
770 } */ *ap = v; 772 } */ *ap = v;
771 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 773 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
772 struct uio *uio = ap->a_uio; 774 struct uio *uio = ap->a_uio;
773 int error; 775 int error;
774 size_t xlen; 776 size_t xlen;
775 char strbuf[KSTRING]; 777 char strbuf[KSTRING];
776 778
777 if (uio->uio_offset != 0) 779 if (uio->uio_offset != 0)
778 return (EINVAL); 780 return (EINVAL);
779 781
780 xlen = min(uio->uio_resid, KSTRING-1); 782 xlen = min(uio->uio_resid, KSTRING-1);
781 if ((error = uiomove(strbuf, xlen, uio)) != 0) 783 if ((error = uiomove(strbuf, xlen, uio)) != 0)
782 return (error); 784 return (error);
783 785
784 if (uio->uio_resid != 0) 786 if (uio->uio_resid != 0)
785 return (EIO); 787 return (EIO);
786 788
787 strbuf[xlen] = '\0'; 789 strbuf[xlen] = '\0';
788 xlen = strlen(strbuf); 790 xlen = strlen(strbuf);
789 return (kernfs_xwrite(kfs, strbuf, xlen)); 791 return (kernfs_xwrite(kfs, strbuf, xlen));
790} 792}
791 793
792int 794int
793kernfs_write(void *v) 795kernfs_write(void *v)
794{ 796{
795 struct vop_write_args /* { 797 struct vop_write_args /* {
796 struct vnode *a_vp; 798 struct vnode *a_vp;
797 struct uio *a_uio; 799 struct uio *a_uio;
798 int a_ioflag; 800 int a_ioflag;
799 kauth_cred_t a_cred; 801 kauth_cred_t a_cred;
800 } */ *ap = v; 802 } */ *ap = v;
801 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 803 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
802 804
803 if (kfs->kfs_type < KFSlasttype) { 805 if (kfs->kfs_type < KFSlasttype) {
804 /* use default function */ 806 /* use default function */
805 return kernfs_default_xwrite(v); 807 return kernfs_default_xwrite(v);
806 } 808 }
807 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_WRITE, v, 809 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_WRITE, v,
808 EOPNOTSUPP); 810 EOPNOTSUPP);
809} 811}
810 812
811int 813int
812kernfs_ioctl(void *v) 814kernfs_ioctl(void *v)
813{ 815{
814 struct vop_ioctl_args /* { 816 struct vop_ioctl_args /* {
815 const struct vnodeop_desc *a_desc; 817 const struct vnodeop_desc *a_desc;
816 struct vnode *a_vp; 818 struct vnode *a_vp;
817 u_long a_command; 819 u_long a_command;
818 void *a_data; 820 void *a_data;
819 int a_fflag; 821 int a_fflag;
820 kauth_cred_t a_cred; 822 kauth_cred_t a_cred;
821 } */ *ap = v; 823 } */ *ap = v;
822 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 824 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
823 825
824 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_IOCTL, v, 826 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_IOCTL, v,
825 EPASSTHROUGH); 827 EPASSTHROUGH);
826} 828}
827 829
828static int 830static int
829kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt, 831kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt,
830 struct vop_readdir_args *ap) 832 struct vop_readdir_args *ap)
831{ 833{
832 struct kernfs_node *kfs; 834 struct kernfs_node *kfs;
833 struct vnode *vp; 835 struct vnode *vp;
834 int error; 836 int error;
835 837
836 if ((error = vcache_get(ap->a_vp->v_mount, &kt, sizeof(kt), &vp)) != 0) 838 if ((error = vcache_get(ap->a_vp->v_mount, &kt, sizeof(kt), &vp)) != 0)
837 return error; 839 return error;
838 kfs = VTOKERN(vp); 840 kfs = VTOKERN(vp);
839 d->d_fileno = kfs->kfs_fileno; 841 d->d_fileno = kfs->kfs_fileno;
840 vrele(vp); 842 vrele(vp);
841 return 0; 843 return 0;
842} 844}
843 845
844static int 846static int
845kernfs_setdirentfileno(struct dirent *d, off_t entry, 847kernfs_setdirentfileno(struct dirent *d, off_t entry,
846 struct kernfs_node *thisdir_kfs, const struct kern_target *parent_kt, 848 struct kernfs_node *thisdir_kfs, const struct kern_target *parent_kt,
847 const struct kern_target *kt, struct vop_readdir_args *ap) 849 const struct kern_target *kt, struct vop_readdir_args *ap)
848{ 850{
849 const struct kern_target *ikt; 851 const struct kern_target *ikt;
850 int error; 852 int error;
851 853
852 switch (entry) { 854 switch (entry) {
853 case 0: 855 case 0:
854 d->d_fileno = thisdir_kfs->kfs_fileno; 856 d->d_fileno = thisdir_kfs->kfs_fileno;
855 return 0; 857 return 0;
856 case 1: 858 case 1:
857 ikt = parent_kt; 859 ikt = parent_kt;
858 break; 860 break;
859 default: 861 default:
860 ikt = kt; 862 ikt = kt;
861 break; 863 break;
862 } 864 }
863 if (ikt != thisdir_kfs->kfs_kt) { 865 if (ikt != thisdir_kfs->kfs_kt) {
864 if ((error = kernfs_setdirentfileno_kt(d, ikt, ap)) != 0) 866 if ((error = kernfs_setdirentfileno_kt(d, ikt, ap)) != 0)
865 return error; 867 return error;
866 } else 868 } else
867 d->d_fileno = thisdir_kfs->kfs_fileno; 869 d->d_fileno = thisdir_kfs->kfs_fileno;
868 return 0; 870 return 0;
869} 871}
870 872
871int 873int
872kernfs_readdir(void *v) 874kernfs_readdir(void *v)
873{ 875{
874 struct vop_readdir_args /* { 876 struct vop_readdir_args /* {
875 struct vnode *a_vp; 877 struct vnode *a_vp;
876 struct uio *a_uio; 878 struct uio *a_uio;
877 kauth_cred_t a_cred; 879 kauth_cred_t a_cred;
878 int *a_eofflag; 880 int *a_eofflag;
879 off_t **a_cookies; 881 off_t **a_cookies;
880 int a_*ncookies; 882 int a_*ncookies;
881 } */ *ap = v; 883 } */ *ap = v;
882 struct uio *uio = ap->a_uio; 884 struct uio *uio = ap->a_uio;
883 struct dirent d; 885 struct dirent d;
884 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 886 struct kernfs_node *kfs = VTOKERN(ap->a_vp);
885 const struct kern_target *kt; 887 const struct kern_target *kt;
886 const struct dyn_kern_target *dkt = NULL; 888 const struct dyn_kern_target *dkt = NULL;
887 const struct kernfs_subdir *ks; 889 const struct kernfs_subdir *ks;
888 off_t i, j; 890 off_t i, j;
889 int error; 891 int error;
890 off_t *cookies = NULL; 892 off_t *cookies = NULL;
891 int ncookies = 0, n; 893 int ncookies = 0, n;
892 894
893 if (uio->uio_resid < UIO_MX) 895 if (uio->uio_resid < UIO_MX)
894 return (EINVAL); 896 return (EINVAL);
895 if (uio->uio_offset < 0) 897 if (uio->uio_offset < 0)
896 return (EINVAL); 898 return (EINVAL);
897 899
898 error = 0; 900 error = 0;
899 i = uio->uio_offset; 901 i = uio->uio_offset;
900 memset(&d, 0, sizeof(d)); 902 memset(&d, 0, sizeof(d));
901 d.d_reclen = UIO_MX; 903 d.d_reclen = UIO_MX;
902 ncookies = uio->uio_resid / UIO_MX; 904 ncookies = uio->uio_resid / UIO_MX;
903 905
904 switch (kfs->kfs_type) { 906 switch (kfs->kfs_type) {
905 case KFSkern: 907 case KFSkern:
906 if (i >= nkern_targets) 908 if (i >= nkern_targets)
907 return (0); 909 return (0);
908 910
909 if (ap->a_ncookies) { 911 if (ap->a_ncookies) {
910 ncookies = min(ncookies, (nkern_targets - i)); 912 ncookies = min(ncookies, (nkern_targets - i));
911 cookies = malloc(ncookies * sizeof(off_t), M_TEMP, 913 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
912 M_WAITOK); 914 M_WAITOK);
913 *ap->a_cookies = cookies; 915 *ap->a_cookies = cookies;
914 } 916 }
915 917
916 n = 0; 918 n = 0;
917 for (; i < nkern_targets && uio->uio_resid >= UIO_MX; i++) { 919 for (; i < nkern_targets && uio->uio_resid >= UIO_MX; i++) {
918 if (i < static_nkern_targets) 920 if (i < static_nkern_targets)
919 kt = &kern_targets[i]; 921 kt = &kern_targets[i];
920 else { 922 else {
921 if (dkt == NULL) { 923 if (dkt == NULL) {
922 dkt = SIMPLEQ_FIRST(&dyn_kern_targets); 924 dkt = SIMPLEQ_FIRST(&dyn_kern_targets);
923 for (j = static_nkern_targets; j < i && 925 for (j = static_nkern_targets; j < i &&
924 dkt != NULL; j++) 926 dkt != NULL; j++)
925 dkt = SIMPLEQ_NEXT(dkt, dkt_queue); 927 dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
926 if (j != i) 928 if (j != i)
927 break; 929 break;
928 } else { 930 } else {
929 dkt = SIMPLEQ_NEXT(dkt, dkt_queue); 931 dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
930 } 932 }
931 if (dkt == NULL) 933 if (dkt == NULL)
932 break; 934 break;
933 kt = &dkt->dkt_kt; 935 kt = &dkt->dkt_kt;
934 } 936 }
935 if (kt->kt_tag == KFSdevice) { 937 if (kt->kt_tag == KFSdevice) {
936 dev_t *dp = kt->kt_data; 938 dev_t *dp = kt->kt_data;
937 struct vnode *fvp; 939 struct vnode *fvp;
938 940
939 if (*dp == NODEV || 941 if (*dp == NODEV ||
940 !vfinddev(*dp, kt->kt_vtype, &fvp)) 942 !vfinddev(*dp, kt->kt_vtype, &fvp))
941 continue; 943 continue;
942 vrele(fvp); 944 vrele(fvp);
943 } 945 }
944 if (kt->kt_tag == KFSmsgbuf) { 946 if (kt->kt_tag == KFSmsgbuf) {
945 if (!msgbufenabled 947 if (!msgbufenabled
946 || msgbufp->msg_magic != MSG_MAGIC) { 948 || msgbufp->msg_magic != MSG_MAGIC) {
947 continue; 949 continue;
948 } 950 }
949 } 951 }
950 d.d_namlen = kt->kt_namlen; 952 d.d_namlen = kt->kt_namlen;
951 if ((error = kernfs_setdirentfileno(&d, i, kfs, 953 if ((error = kernfs_setdirentfileno(&d, i, kfs,
952 &kern_targets[0], kt, ap)) != 0) 954 &kern_targets[0], kt, ap)) != 0)
953 break; 955 break;
954 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); 956 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
955 d.d_type = kt->kt_type; 957 d.d_type = kt->kt_type;
956 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 958 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
957 break; 959 break;
958 if (cookies) 960 if (cookies)
959 *cookies++ = i + 1; 961 *cookies++ = i + 1;
960 n++; 962 n++;
961 } 963 }
962 ncookies = n; 964 ncookies = n;
963 break; 965 break;
964 966
965 case KFSroot: 967 case KFSroot:
966 if (i >= 2) 968 if (i >= 2)
967 return 0; 969 return 0;
968 970
969 if (ap->a_ncookies) { 971 if (ap->a_ncookies) {
970 ncookies = min(ncookies, (2 - i)); 972 ncookies = min(ncookies, (2 - i));
971 cookies = malloc(ncookies * sizeof(off_t), M_TEMP, 973 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
972 M_WAITOK); 974 M_WAITOK);
973 *ap->a_cookies = cookies; 975 *ap->a_cookies = cookies;
974 } 976 }
975 977
976 n = 0; 978 n = 0;
977 for (; i < 2 && uio->uio_resid >= UIO_MX; i++) { 979 for (; i < 2 && uio->uio_resid >= UIO_MX; i++) {
978 kt = &kern_targets[i]; 980 kt = &kern_targets[i];
979 d.d_namlen = kt->kt_namlen; 981 d.d_namlen = kt->kt_namlen;
980 d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0); 982 d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0);
981 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); 983 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
982 d.d_type = kt->kt_type; 984 d.d_type = kt->kt_type;
983 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 985 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
984 break; 986 break;
985 if (cookies) 987 if (cookies)
986 *cookies++ = i + 1; 988 *cookies++ = i + 1;
987 n++; 989 n++;
988 } 990 }
989 ncookies = n; 991 ncookies = n;
990 break; 992 break;
991 993
992 case KFSsubdir: 994 case KFSsubdir:
993 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data; 995 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
994 if (i >= ks->ks_nentries) 996 if (i >= ks->ks_nentries)
995 return (0); 997 return (0);
996 998
997 if (ap->a_ncookies) { 999 if (ap->a_ncookies) {
998 ncookies = min(ncookies, (ks->ks_nentries - i)); 1000 ncookies = min(ncookies, (ks->ks_nentries - i));
999 cookies = malloc(ncookies * sizeof(off_t), M_TEMP, 1001 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
1000 M_WAITOK); 1002 M_WAITOK);
1001 *ap->a_cookies = cookies; 1003 *ap->a_cookies = cookies;
1002 } 1004 }
1003 1005
1004 dkt = SIMPLEQ_FIRST(&ks->ks_entries); 1006 dkt = SIMPLEQ_FIRST(&ks->ks_entries);
1005 for (j = 0; j < i && dkt != NULL; j++) 1007 for (j = 0; j < i && dkt != NULL; j++)
1006 dkt = SIMPLEQ_NEXT(dkt, dkt_queue); 1008 dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1007 n = 0; 1009 n = 0;
1008 for (; i < ks->ks_nentries && uio->uio_resid >= UIO_MX; i++) { 1010 for (; i < ks->ks_nentries && uio->uio_resid >= UIO_MX; i++) {
1009 if (i < 2) 1011 if (i < 2)
1010 kt = &subdir_targets[i]; 1012 kt = &subdir_targets[i];
1011 else { 1013 else {
1012 /* check if ks_nentries lied to us */ 1014 /* check if ks_nentries lied to us */
1013 if (dkt == NULL) 1015 if (dkt == NULL)
1014 break; 1016 break;
1015 kt = &dkt->dkt_kt; 1017 kt = &dkt->dkt_kt;
1016 dkt = SIMPLEQ_NEXT(dkt, dkt_queue); 1018 dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1017 } 1019 }
1018 if (kt->kt_tag == KFSdevice) { 1020 if (kt->kt_tag == KFSdevice) {
1019 dev_t *dp = kt->kt_data; 1021 dev_t *dp = kt->kt_data;
1020 struct vnode *fvp; 1022 struct vnode *fvp;
1021 1023
1022 if (*dp == NODEV || 1024 if (*dp == NODEV ||
1023 !vfinddev(*dp, kt->kt_vtype, &fvp)) 1025 !vfinddev(*dp, kt->kt_vtype, &fvp))
1024 continue; 1026 continue;
1025 vrele(fvp); 1027 vrele(fvp);
1026 } 1028 }
1027 d.d_namlen = kt->kt_namlen; 1029 d.d_namlen = kt->kt_namlen;
1028 if ((error = kernfs_setdirentfileno(&d, i, kfs, 1030 if ((error = kernfs_setdirentfileno(&d, i, kfs,
1029 ks->ks_parent, kt, ap)) != 0) 1031 ks->ks_parent, kt, ap)) != 0)
1030 break; 1032 break;
1031 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); 1033 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1032 d.d_type = kt->kt_type; 1034 d.d_type = kt->kt_type;
1033 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 1035 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1034 break; 1036 break;
1035 if (cookies) 1037 if (cookies)
1036 *cookies++ = i + 1; 1038 *cookies++ = i + 1;
1037 n++; 1039 n++;
1038 } 1040 }
1039 ncookies = n; 1041 ncookies = n;
1040 break; 1042 break;
1041 1043
1042 default: 1044 default:
1043 error = ENOTDIR; 1045 error = ENOTDIR;
1044 break; 1046 break;
1045 } 1047 }
1046 1048
1047 if (ap->a_ncookies) { 1049 if (ap->a_ncookies) {
1048 if (error) { 1050 if (error) {
1049 if (cookies) 1051 if (cookies)
1050 free(*ap->a_cookies, M_TEMP); 1052 free(*ap->a_cookies, M_TEMP);
1051 *ap->a_ncookies = 0; 1053 *ap->a_ncookies = 0;
1052 *ap->a_cookies = NULL; 1054 *ap->a_cookies = NULL;
1053 } else 1055 } else
1054 *ap->a_ncookies = ncookies; 1056 *ap->a_ncookies = ncookies;
1055 } 1057 }
1056 1058
1057 uio->uio_offset = i; 1059 uio->uio_offset = i;
1058 return (error); 1060 return (error);
1059} 1061}
1060 1062
1061int 1063int
1062kernfs_inactive(void *v) 1064kernfs_inactive(void *v)
1063{ 1065{
1064 struct vop_inactive_args /* { 1066 struct vop_inactive_args /* {
1065 struct vnode *a_vp; 1067 struct vnode *a_vp;
1066 bool *a_recycle; 1068 bool *a_recycle;
1067 } */ *ap = v; 1069 } */ *ap = v;
1068 struct vnode *vp = ap->a_vp; 1070 struct vnode *vp = ap->a_vp;
1069 1071
1070 *ap->a_recycle = false; 1072 *ap->a_recycle = false;
1071 VOP_UNLOCK(vp); 1073 VOP_UNLOCK(vp);
1072 return (0); 1074 return (0);
1073} 1075}
1074 1076
1075int 1077int
1076kernfs_reclaim(void *v) 1078kernfs_reclaim(void *v)
1077{ 1079{
1078 struct vop_reclaim_args /* { 1080 struct vop_reclaim_args /* {
1079 struct vnode *a_vp; 1081 struct vnode *a_vp;
1080 } */ *ap = v; 1082 } */ *ap = v;
1081 struct vnode *vp = ap->a_vp; 1083 struct vnode *vp = ap->a_vp;
1082 struct kernfs_node *kfs = VTOKERN(vp); 1084 struct kernfs_node *kfs = VTOKERN(vp);
1083 1085
1084 vp->v_data = NULL; 1086 vp->v_data = NULL;
1085 vcache_remove(vp->v_mount, &kfs->kfs_kt, sizeof(kfs->kfs_kt)); 1087 vcache_remove(vp->v_mount, &kfs->kfs_kt, sizeof(kfs->kfs_kt));
1086 mutex_enter(&kfs_lock); 1088 mutex_enter(&kfs_lock);
1087 TAILQ_REMOVE(&VFSTOKERNFS(vp->v_mount)->nodelist, kfs, kfs_list); 1089 TAILQ_REMOVE(&VFSTOKERNFS(vp->v_mount)->nodelist, kfs, kfs_list);
1088 mutex_exit(&kfs_lock); 1090 mutex_exit(&kfs_lock);
1089 kmem_free(kfs, sizeof(struct kernfs_node)); 1091 kmem_free(kfs, sizeof(struct kernfs_node));
1090 1092
1091 return 0; 1093 return 0;
1092} 1094}
1093 1095
1094/* 1096/*
1095 * Return POSIX pathconf information applicable to special devices. 1097 * Return POSIX pathconf information applicable to special devices.
1096 */ 1098 */
1097int 1099int
1098kernfs_pathconf(void *v) 1100kernfs_pathconf(void *v)
1099{ 1101{
1100 struct vop_pathconf_args /* { 1102 struct vop_pathconf_args /* {
1101 struct vnode *a_vp; 1103 struct vnode *a_vp;
1102 int a_name; 1104 int a_name;
1103 register_t *a_retval; 1105 register_t *a_retval;
1104 } */ *ap = v; 1106 } */ *ap = v;
1105 1107
1106 switch (ap->a_name) { 1108 switch (ap->a_name) {
1107 case _PC_LINK_MAX: 1109 case _PC_LINK_MAX:
1108 *ap->a_retval = LINK_MAX; 1110 *ap->a_retval = LINK_MAX;
1109 return (0); 1111 return (0);
1110 case _PC_MAX_CANON: 1112 case _PC_MAX_CANON:
1111 *ap->a_retval = MAX_CANON; 1113 *ap->a_retval = MAX_CANON;
1112 return (0); 1114 return (0);
1113 case _PC_MAX_INPUT: 1115 case _PC_MAX_INPUT:
1114 *ap->a_retval = MAX_INPUT; 1116 *ap->a_retval = MAX_INPUT;
1115 return (0); 1117 return (0);
1116 case _PC_PIPE_BUF: 1118 case _PC_PIPE_BUF:
1117 *ap->a_retval = PIPE_BUF; 1119 *ap->a_retval = PIPE_BUF;
1118 return (0); 1120 return (0);
1119 case _PC_CHOWN_RESTRICTED: 1121 case _PC_CHOWN_RESTRICTED:
1120 *ap->a_retval = 1; 1122 *ap->a_retval = 1;
1121 return (0); 1123 return (0);
1122 case _PC_VDISABLE: 1124 case _PC_VDISABLE:
1123 *ap->a_retval = _POSIX_VDISABLE; 1125 *ap->a_retval = _POSIX_VDISABLE;
1124 return (0); 1126 return (0);
1125 case _PC_SYNC_IO: 1127 case _PC_SYNC_IO:
1126 *ap->a_retval = 1; 1128 *ap->a_retval = 1;
1127 return (0); 1129 return (0);
1128 default: 1130 default:
1129 return (EINVAL); 1131 return (EINVAL);
1130 } 1132 }
1131 /* NOTREACHED */ 1133 /* NOTREACHED */
1132} 1134}
1133 1135
1134/* 1136/*
1135 * Print out the contents of a /dev/fd vnode. 1137 * Print out the contents of a /dev/fd vnode.
1136 */ 1138 */
1137/* ARGSUSED */ 1139/* ARGSUSED */
1138int 1140int
1139kernfs_print(void *v) 1141kernfs_print(void *v)
1140{ 1142{
1141 1143
1142 printf("tag VT_KERNFS, kernfs vnode\n"); 1144 printf("tag VT_KERNFS, kernfs vnode\n");
1143 return (0); 1145 return (0);
1144} 1146}
1145 1147
1146int 1148int
1147kernfs_link(void *v) 1149kernfs_link(void *v)
1148{ 1150{
1149 struct vop_link_args /* { 1151 struct vop_link_args /* {
1150 struct vnode *a_dvp; 1152 struct vnode *a_dvp;
1151 struct vnode *a_vp; 1153 struct vnode *a_vp;
1152 struct componentname *a_cnp; 1154 struct componentname *a_cnp;
1153 } */ *ap = v; 1155 } */ *ap = v;
1154 1156
1155 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 1157 VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
1156 vput(ap->a_dvp); 1158 vput(ap->a_dvp);
1157 return (EROFS); 1159 return (EROFS);
1158} 1160}
1159 1161
1160int 1162int
1161kernfs_symlink(void *v) 1163kernfs_symlink(void *v)
1162{ 1164{
1163 struct vop_symlink_v3_args /* { 1165 struct vop_symlink_v3_args /* {
1164 struct vnode *a_dvp; 1166 struct vnode *a_dvp;
1165 struct vnode **a_vpp; 1167 struct vnode **a_vpp;
1166 struct componentname *a_cnp; 1168 struct componentname *a_cnp;
1167 struct vattr *a_vap; 1169 struct vattr *a_vap;
1168 char *a_target; 1170 char *a_target;
1169 } */ *ap = v; 1171 } */ *ap = v;
1170 1172
1171 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 1173 VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
1172 return (EROFS); 1174 return (EROFS);
1173} 1175}
 1176
 1177int
 1178kernfs_getpages(void *v)
 1179{
 1180 struct vop_getpages_args /* {
 1181 struct vnode *a_vp;
 1182 voff_t a_offset;
 1183 struct vm_page **a_m;
 1184 int *a_count;
 1185 int a_centeridx;
 1186 vm_prot_t a_access_type;
 1187 int a_advice;
 1188 int a_flags;
 1189 } */ *ap = v;
 1190
 1191 if ((ap->a_flags & PGO_LOCKED) == 0)
 1192 mutex_exit(ap->a_vp->v_interlock);
 1193
 1194 return (EFAULT);
 1195}

cvs diff -r1.191 -r1.191.8.1 src/sys/miscfs/procfs/procfs_vnops.c (switch to unified diff)

--- src/sys/miscfs/procfs/procfs_vnops.c 2014/07/27 16:47:26 1.191
+++ src/sys/miscfs/procfs/procfs_vnops.c 2019/08/29 16:14:37 1.191.8.1
@@ -1,1728 +1,1750 @@ @@ -1,1728 +1,1750 @@
1/* $NetBSD: procfs_vnops.c,v 1.191 2014/07/27 16:47:26 hannken Exp $ */ 1/* $NetBSD: procfs_vnops.c,v 1.191.8.1 2019/08/29 16:14:37 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.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * Copyright (c) 1993, 1995 33 * Copyright (c) 1993, 1995
34 * The Regents of the University of California. All rights reserved. 34 * The Regents of the University of California. All rights reserved.
35 * 35 *
36 * This code is derived from software contributed to Berkeley by 36 * This code is derived from software contributed to Berkeley by
37 * Jan-Simon Pendry. 37 * Jan-Simon Pendry.
38 * 38 *
39 * Redistribution and use in source and binary forms, with or without 39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions 40 * modification, are permitted provided that the following conditions
41 * are met: 41 * are met:
42 * 1. Redistributions of source code must retain the above copyright 42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer. 43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright 44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the 45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution. 46 * documentation and/or other materials provided with the distribution.
47 * 3. Neither the name of the University nor the names of its contributors 47 * 3. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software 48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission. 49 * without specific prior written permission.
50 * 50 *
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * SUCH DAMAGE. 61 * SUCH DAMAGE.
62 * 62 *
63 * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95 63 * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95
64 */ 64 */
65 65
66/* 66/*
67 * Copyright (c) 1993 Jan-Simon Pendry 67 * Copyright (c) 1993 Jan-Simon Pendry
68 * 68 *
69 * This code is derived from software contributed to Berkeley by 69 * This code is derived from software contributed to Berkeley by
70 * Jan-Simon Pendry. 70 * Jan-Simon Pendry.
71 * 71 *
72 * Redistribution and use in source and binary forms, with or without 72 * Redistribution and use in source and binary forms, with or without
73 * modification, are permitted provided that the following conditions 73 * modification, are permitted provided that the following conditions
74 * are met: 74 * are met:
75 * 1. Redistributions of source code must retain the above copyright 75 * 1. Redistributions of source code must retain the above copyright
76 * notice, this list of conditions and the following disclaimer. 76 * notice, this list of conditions and the following disclaimer.
77 * 2. Redistributions in binary form must reproduce the above copyright 77 * 2. Redistributions in binary form must reproduce the above copyright
78 * notice, this list of conditions and the following disclaimer in the 78 * notice, this list of conditions and the following disclaimer in the
79 * documentation and/or other materials provided with the distribution. 79 * documentation and/or other materials provided with the distribution.
80 * 3. All advertising materials mentioning features or use of this software 80 * 3. All advertising materials mentioning features or use of this software
81 * must display the following acknowledgement: 81 * must display the following acknowledgement:
82 * This product includes software developed by the University of 82 * This product includes software developed by the University of
83 * California, Berkeley and its contributors. 83 * California, Berkeley and its contributors.
84 * 4. Neither the name of the University nor the names of its contributors 84 * 4. Neither the name of the University nor the names of its contributors
85 * may be used to endorse or promote products derived from this software 85 * may be used to endorse or promote products derived from this software
86 * without specific prior written permission. 86 * without specific prior written permission.
87 * 87 *
88 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 88 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
89 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 89 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
90 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 90 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
91 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 91 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
92 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 92 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
93 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 93 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
94 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 94 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
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.191 2014/07/27 16:47:26 hannken Exp $"); 108__KERNEL_RCSID(0, "$NetBSD: procfs_vnops.c,v 1.191.8.1 2019/08/29 16:14:37 martin Exp $");
109 109
110#include <sys/param.h> 110#include <sys/param.h>
111#include <sys/systm.h> 111#include <sys/systm.h>
112#include <sys/time.h> 112#include <sys/time.h>
113#include <sys/kernel.h> 113#include <sys/kernel.h>
114#include <sys/file.h> 114#include <sys/file.h>
115#include <sys/filedesc.h> 115#include <sys/filedesc.h>
116#include <sys/proc.h> 116#include <sys/proc.h>
117#include <sys/vnode.h> 117#include <sys/vnode.h>
118#include <sys/namei.h> 118#include <sys/namei.h>
119#include <sys/malloc.h> 119#include <sys/malloc.h>
120#include <sys/mount.h> 120#include <sys/mount.h>
121#include <sys/dirent.h> 121#include <sys/dirent.h>
122#include <sys/resourcevar.h> 122#include <sys/resourcevar.h>
123#include <sys/stat.h> 123#include <sys/stat.h>
124#include <sys/ptrace.h> 124#include <sys/ptrace.h>
125#include <sys/kauth.h> 125#include <sys/kauth.h>
126 126
127#include <uvm/uvm_extern.h> /* for PAGE_SIZE */ 127#include <uvm/uvm_extern.h> /* for PAGE_SIZE */
128 128
129#include <machine/reg.h> 129#include <machine/reg.h>
130 130
131#include <miscfs/genfs/genfs.h> 131#include <miscfs/genfs/genfs.h>
132#include <miscfs/procfs/procfs.h> 132#include <miscfs/procfs/procfs.h>
133 133
134/* 134/*
135 * Vnode Operations. 135 * Vnode Operations.
136 * 136 *
137 */ 137 */
138 138
139static int procfs_validfile_linux(struct lwp *, struct mount *); 139static int procfs_validfile_linux(struct lwp *, struct mount *);
140static int procfs_root_readdir_callback(struct proc *, void *); 140static int procfs_root_readdir_callback(struct proc *, void *);
141static void procfs_dir(pfstype, struct lwp *, struct proc *, char **, char *, 141static void procfs_dir(pfstype, struct lwp *, struct proc *, char **, char *,
142 size_t); 142 size_t);
143 143
144/* 144/*
145 * This is a list of the valid names in the 145 * This is a list of the valid names in the
146 * process-specific sub-directories. It is 146 * process-specific sub-directories. It is
147 * used in procfs_lookup and procfs_readdir 147 * used in procfs_lookup and procfs_readdir
148 */ 148 */
149static const struct proc_target { 149static const struct proc_target {
150 u_char pt_type; 150 u_char pt_type;
151 u_char pt_namlen; 151 u_char pt_namlen;
152 const char *pt_name; 152 const char *pt_name;
153 pfstype pt_pfstype; 153 pfstype pt_pfstype;
154 int (*pt_valid)(struct lwp *, struct mount *); 154 int (*pt_valid)(struct lwp *, struct mount *);
155} proc_targets[] = { 155} proc_targets[] = {
156#define N(s) sizeof(s)-1, s 156#define N(s) sizeof(s)-1, s
157 /* name type validp */ 157 /* name type validp */
158 { DT_DIR, N("."), PFSproc, NULL }, 158 { DT_DIR, N("."), PFSproc, NULL },
159 { DT_DIR, N(".."), PFSroot, NULL }, 159 { DT_DIR, N(".."), PFSroot, NULL },
160 { DT_DIR, N("fd"), PFSfd, NULL }, 160 { DT_DIR, N("fd"), PFSfd, NULL },
161 { DT_REG, N("file"), PFSfile, procfs_validfile }, 161 { DT_REG, N("file"), PFSfile, procfs_validfile },
162 { DT_REG, N("mem"), PFSmem, NULL }, 162 { DT_REG, N("mem"), PFSmem, NULL },
163 { DT_REG, N("regs"), PFSregs, procfs_validregs }, 163 { DT_REG, N("regs"), PFSregs, procfs_validregs },
164 { DT_REG, N("fpregs"), PFSfpregs, procfs_validfpregs }, 164 { DT_REG, N("fpregs"), PFSfpregs, procfs_validfpregs },
165 { DT_REG, N("ctl"), PFSctl, NULL }, 165 { DT_REG, N("ctl"), PFSctl, NULL },
166 { DT_REG, N("stat"), PFSstat, procfs_validfile_linux }, 166 { DT_REG, N("stat"), PFSstat, procfs_validfile_linux },
167 { DT_REG, N("status"), PFSstatus, NULL }, 167 { DT_REG, N("status"), PFSstatus, NULL },
168 { DT_REG, N("note"), PFSnote, NULL }, 168 { DT_REG, N("note"), PFSnote, NULL },
169 { DT_REG, N("notepg"), PFSnotepg, NULL }, 169 { DT_REG, N("notepg"), PFSnotepg, NULL },
170 { DT_REG, N("map"), PFSmap, procfs_validmap }, 170 { DT_REG, N("map"), PFSmap, procfs_validmap },
171 { DT_REG, N("maps"), PFSmaps, procfs_validmap }, 171 { DT_REG, N("maps"), PFSmaps, procfs_validmap },
172 { DT_REG, N("cmdline"), PFScmdline, NULL }, 172 { DT_REG, N("cmdline"), PFScmdline, NULL },
173 { DT_REG, N("exe"), PFSexe, procfs_validfile }, 173 { DT_REG, N("exe"), PFSexe, procfs_validfile },
174 { DT_LNK, N("cwd"), PFScwd, NULL }, 174 { DT_LNK, N("cwd"), PFScwd, NULL },
175 { DT_LNK, N("root"), PFSchroot, NULL }, 175 { DT_LNK, N("root"), PFSchroot, NULL },
176 { DT_LNK, N("emul"), PFSemul, NULL }, 176 { DT_LNK, N("emul"), PFSemul, NULL },
177 { DT_REG, N("statm"), PFSstatm, procfs_validfile_linux }, 177 { DT_REG, N("statm"), PFSstatm, procfs_validfile_linux },
178 { DT_DIR, N("task"), PFStask, procfs_validfile_linux }, 178 { DT_DIR, N("task"), PFStask, procfs_validfile_linux },
179#ifdef __HAVE_PROCFS_MACHDEP 179#ifdef __HAVE_PROCFS_MACHDEP
180 PROCFS_MACHDEP_NODETYPE_DEFNS 180 PROCFS_MACHDEP_NODETYPE_DEFNS
181#endif 181#endif
182#undef N 182#undef N
183}; 183};
184static const int nproc_targets = sizeof(proc_targets) / sizeof(proc_targets[0]); 184static const int nproc_targets = sizeof(proc_targets) / sizeof(proc_targets[0]);
185 185
186/* 186/*
187 * List of files in the root directory. Note: the validate function will 187 * List of files in the root directory. Note: the validate function will
188 * be called with p == NULL for these ones. 188 * be called with p == NULL for these ones.
189 */ 189 */
190static const struct proc_target proc_root_targets[] = { 190static const struct proc_target proc_root_targets[] = {
191#define N(s) sizeof(s)-1, s 191#define N(s) sizeof(s)-1, s
192 /* name type validp */ 192 /* name type validp */
193 { DT_REG, N("meminfo"), PFSmeminfo, procfs_validfile_linux }, 193 { DT_REG, N("meminfo"), PFSmeminfo, procfs_validfile_linux },
194 { DT_REG, N("cpuinfo"), PFScpuinfo, procfs_validfile_linux }, 194 { DT_REG, N("cpuinfo"), PFScpuinfo, procfs_validfile_linux },
195 { DT_REG, N("uptime"), PFSuptime, procfs_validfile_linux }, 195 { DT_REG, N("uptime"), PFSuptime, procfs_validfile_linux },
196 { DT_REG, N("mounts"), PFSmounts, procfs_validfile_linux }, 196 { DT_REG, N("mounts"), PFSmounts, procfs_validfile_linux },
197 { DT_REG, N("devices"), PFSdevices, procfs_validfile_linux }, 197 { DT_REG, N("devices"), PFSdevices, procfs_validfile_linux },
198 { DT_REG, N("stat"), PFScpustat, procfs_validfile_linux }, 198 { DT_REG, N("stat"), PFScpustat, procfs_validfile_linux },
199 { DT_REG, N("loadavg"), PFSloadavg, procfs_validfile_linux }, 199 { DT_REG, N("loadavg"), PFSloadavg, procfs_validfile_linux },
200 { DT_REG, N("version"), PFSversion, procfs_validfile_linux }, 200 { DT_REG, N("version"), PFSversion, procfs_validfile_linux },
201#undef N 201#undef N
202}; 202};
203static const int nproc_root_targets = 203static const int nproc_root_targets =
204 sizeof(proc_root_targets) / sizeof(proc_root_targets[0]); 204 sizeof(proc_root_targets) / sizeof(proc_root_targets[0]);
205 205
206int procfs_lookup(void *); 206int procfs_lookup(void *);
207#define procfs_create genfs_eopnotsupp 207#define procfs_create genfs_eopnotsupp
208#define procfs_mknod genfs_eopnotsupp 208#define procfs_mknod genfs_eopnotsupp
209int procfs_open(void *); 209int procfs_open(void *);
210int procfs_close(void *); 210int procfs_close(void *);
211int procfs_access(void *); 211int procfs_access(void *);
212int procfs_getattr(void *); 212int procfs_getattr(void *);
213int procfs_setattr(void *); 213int procfs_setattr(void *);
214#define procfs_read procfs_rw 214#define procfs_read procfs_rw
215#define procfs_write procfs_rw 215#define procfs_write procfs_rw
216#define procfs_fcntl genfs_fcntl 216#define procfs_fcntl genfs_fcntl
217#define procfs_ioctl genfs_enoioctl 217#define procfs_ioctl genfs_enoioctl
218#define procfs_poll genfs_poll 218#define procfs_poll genfs_poll
219#define procfs_revoke genfs_revoke 219#define procfs_revoke genfs_revoke
220#define procfs_fsync genfs_nullop 220#define procfs_fsync genfs_nullop
221#define procfs_seek genfs_nullop 221#define procfs_seek genfs_nullop
222#define procfs_remove genfs_eopnotsupp 222#define procfs_remove genfs_eopnotsupp
223int procfs_link(void *); 223int procfs_link(void *);
224#define procfs_rename genfs_eopnotsupp 224#define procfs_rename genfs_eopnotsupp
225#define procfs_mkdir genfs_eopnotsupp 225#define procfs_mkdir genfs_eopnotsupp
226#define procfs_rmdir genfs_eopnotsupp 226#define procfs_rmdir genfs_eopnotsupp
227int procfs_symlink(void *); 227int procfs_symlink(void *);
228int procfs_readdir(void *); 228int procfs_readdir(void *);
229int procfs_readlink(void *); 229int procfs_readlink(void *);
230#define procfs_abortop genfs_abortop 230#define procfs_abortop genfs_abortop
231int procfs_inactive(void *); 231int procfs_inactive(void *);
232int procfs_reclaim(void *); 232int procfs_reclaim(void *);
233#define procfs_lock genfs_lock 233#define procfs_lock genfs_lock
234#define procfs_unlock genfs_unlock 234#define procfs_unlock genfs_unlock
235#define procfs_bmap genfs_badop 235#define procfs_bmap genfs_badop
236#define procfs_strategy genfs_badop 236#define procfs_strategy genfs_badop
237int procfs_print(void *); 237int procfs_print(void *);
238int procfs_pathconf(void *); 238int procfs_pathconf(void *);
239#define procfs_islocked genfs_islocked 239#define procfs_islocked genfs_islocked
240#define procfs_advlock genfs_einval 240#define procfs_advlock genfs_einval
241#define procfs_bwrite genfs_eopnotsupp 241#define procfs_bwrite genfs_eopnotsupp
 242int procfs_getpages(void *);
242#define procfs_putpages genfs_null_putpages 243#define procfs_putpages genfs_null_putpages
243 244
244static int atoi(const char *, size_t); 245static int atoi(const char *, size_t);
245 246
246/* 247/*
247 * procfs vnode operations. 248 * procfs vnode operations.
248 */ 249 */
249int (**procfs_vnodeop_p)(void *); 250int (**procfs_vnodeop_p)(void *);
250const struct vnodeopv_entry_desc procfs_vnodeop_entries[] = { 251const struct vnodeopv_entry_desc procfs_vnodeop_entries[] = {
251 { &vop_default_desc, vn_default_error }, 252 { &vop_default_desc, vn_default_error },
252 { &vop_lookup_desc, procfs_lookup }, /* lookup */ 253 { &vop_lookup_desc, procfs_lookup }, /* lookup */
253 { &vop_create_desc, procfs_create }, /* create */ 254 { &vop_create_desc, procfs_create }, /* create */
254 { &vop_mknod_desc, procfs_mknod }, /* mknod */ 255 { &vop_mknod_desc, procfs_mknod }, /* mknod */
255 { &vop_open_desc, procfs_open }, /* open */ 256 { &vop_open_desc, procfs_open }, /* open */
256 { &vop_close_desc, procfs_close }, /* close */ 257 { &vop_close_desc, procfs_close }, /* close */
257 { &vop_access_desc, procfs_access }, /* access */ 258 { &vop_access_desc, procfs_access }, /* access */
258 { &vop_getattr_desc, procfs_getattr }, /* getattr */ 259 { &vop_getattr_desc, procfs_getattr }, /* getattr */
259 { &vop_setattr_desc, procfs_setattr }, /* setattr */ 260 { &vop_setattr_desc, procfs_setattr }, /* setattr */
260 { &vop_read_desc, procfs_read }, /* read */ 261 { &vop_read_desc, procfs_read }, /* read */
261 { &vop_write_desc, procfs_write }, /* write */ 262 { &vop_write_desc, procfs_write }, /* write */
262 { &vop_fallocate_desc, genfs_eopnotsupp }, /* fallocate */ 263 { &vop_fallocate_desc, genfs_eopnotsupp }, /* fallocate */
263 { &vop_fdiscard_desc, genfs_eopnotsupp }, /* fdiscard */ 264 { &vop_fdiscard_desc, genfs_eopnotsupp }, /* fdiscard */
264 { &vop_fcntl_desc, procfs_fcntl }, /* fcntl */ 265 { &vop_fcntl_desc, procfs_fcntl }, /* fcntl */
265 { &vop_ioctl_desc, procfs_ioctl }, /* ioctl */ 266 { &vop_ioctl_desc, procfs_ioctl }, /* ioctl */
266 { &vop_poll_desc, procfs_poll }, /* poll */ 267 { &vop_poll_desc, procfs_poll }, /* poll */
267 { &vop_revoke_desc, procfs_revoke }, /* revoke */ 268 { &vop_revoke_desc, procfs_revoke }, /* revoke */
268 { &vop_fsync_desc, procfs_fsync }, /* fsync */ 269 { &vop_fsync_desc, procfs_fsync }, /* fsync */
269 { &vop_seek_desc, procfs_seek }, /* seek */ 270 { &vop_seek_desc, procfs_seek }, /* seek */
270 { &vop_remove_desc, procfs_remove }, /* remove */ 271 { &vop_remove_desc, procfs_remove }, /* remove */
271 { &vop_link_desc, procfs_link }, /* link */ 272 { &vop_link_desc, procfs_link }, /* link */
272 { &vop_rename_desc, procfs_rename }, /* rename */ 273 { &vop_rename_desc, procfs_rename }, /* rename */
273 { &vop_mkdir_desc, procfs_mkdir }, /* mkdir */ 274 { &vop_mkdir_desc, procfs_mkdir }, /* mkdir */
274 { &vop_rmdir_desc, procfs_rmdir }, /* rmdir */ 275 { &vop_rmdir_desc, procfs_rmdir }, /* rmdir */
275 { &vop_symlink_desc, procfs_symlink }, /* symlink */ 276 { &vop_symlink_desc, procfs_symlink }, /* symlink */
276 { &vop_readdir_desc, procfs_readdir }, /* readdir */ 277 { &vop_readdir_desc, procfs_readdir }, /* readdir */
277 { &vop_readlink_desc, procfs_readlink }, /* readlink */ 278 { &vop_readlink_desc, procfs_readlink }, /* readlink */
278 { &vop_abortop_desc, procfs_abortop }, /* abortop */ 279 { &vop_abortop_desc, procfs_abortop }, /* abortop */
279 { &vop_inactive_desc, procfs_inactive }, /* inactive */ 280 { &vop_inactive_desc, procfs_inactive }, /* inactive */
280 { &vop_reclaim_desc, procfs_reclaim }, /* reclaim */ 281 { &vop_reclaim_desc, procfs_reclaim }, /* reclaim */
281 { &vop_lock_desc, procfs_lock }, /* lock */ 282 { &vop_lock_desc, procfs_lock }, /* lock */
282 { &vop_unlock_desc, procfs_unlock }, /* unlock */ 283 { &vop_unlock_desc, procfs_unlock }, /* unlock */
283 { &vop_bmap_desc, procfs_bmap }, /* bmap */ 284 { &vop_bmap_desc, procfs_bmap }, /* bmap */
284 { &vop_strategy_desc, procfs_strategy }, /* strategy */ 285 { &vop_strategy_desc, procfs_strategy }, /* strategy */
285 { &vop_print_desc, procfs_print }, /* print */ 286 { &vop_print_desc, procfs_print }, /* print */
286 { &vop_islocked_desc, procfs_islocked }, /* islocked */ 287 { &vop_islocked_desc, procfs_islocked }, /* islocked */
287 { &vop_pathconf_desc, procfs_pathconf }, /* pathconf */ 288 { &vop_pathconf_desc, procfs_pathconf }, /* pathconf */
288 { &vop_advlock_desc, procfs_advlock }, /* advlock */ 289 { &vop_advlock_desc, procfs_advlock }, /* advlock */
 290 { &vop_getpages_desc, procfs_getpages }, /* getpages */
289 { &vop_putpages_desc, procfs_putpages }, /* putpages */ 291 { &vop_putpages_desc, procfs_putpages }, /* putpages */
290 { NULL, NULL } 292 { NULL, NULL }
291}; 293};
292const struct vnodeopv_desc procfs_vnodeop_opv_desc = 294const struct vnodeopv_desc procfs_vnodeop_opv_desc =
293 { &procfs_vnodeop_p, procfs_vnodeop_entries }; 295 { &procfs_vnodeop_p, procfs_vnodeop_entries };
294/* 296/*
295 * set things up for doing i/o on 297 * set things up for doing i/o on
296 * the pfsnode (vp). (vp) is locked 298 * the pfsnode (vp). (vp) is locked
297 * on entry, and should be left locked 299 * on entry, and should be left locked
298 * on exit. 300 * on exit.
299 * 301 *
300 * for procfs we don't need to do anything 302 * for procfs we don't need to do anything
301 * in particular for i/o. all that is done 303 * in particular for i/o. all that is done
302 * is to support exclusive open on process 304 * is to support exclusive open on process
303 * memory images. 305 * memory images.
304 */ 306 */
305int 307int
306procfs_open(void *v) 308procfs_open(void *v)
307{ 309{
308 struct vop_open_args /* { 310 struct vop_open_args /* {
309 struct vnode *a_vp; 311 struct vnode *a_vp;
310 int a_mode; 312 int a_mode;
311 kauth_cred_t a_cred; 313 kauth_cred_t a_cred;
312 } */ *ap = v; 314 } */ *ap = v;
313 struct pfsnode *pfs = VTOPFS(ap->a_vp); 315 struct pfsnode *pfs = VTOPFS(ap->a_vp);
314 struct lwp *l1; 316 struct lwp *l1;
315 struct proc *p2; 317 struct proc *p2;
316 int error; 318 int error;
317 319
318 if ((error = procfs_proc_lock(pfs->pfs_pid, &p2, ENOENT)) != 0) 320 if ((error = procfs_proc_lock(pfs->pfs_pid, &p2, ENOENT)) != 0)
319 return error; 321 return error;
320 322
321 l1 = curlwp; /* tracer */ 323 l1 = curlwp; /* tracer */
322 324
323#define M2K(m) (((m) & FREAD) && ((m) & FWRITE) ? \ 325#define M2K(m) (((m) & FREAD) && ((m) & FWRITE) ? \
324 KAUTH_REQ_PROCESS_PROCFS_RW : \ 326 KAUTH_REQ_PROCESS_PROCFS_RW : \
325 (m) & FWRITE ? KAUTH_REQ_PROCESS_PROCFS_WRITE : \ 327 (m) & FWRITE ? KAUTH_REQ_PROCESS_PROCFS_WRITE : \
326 KAUTH_REQ_PROCESS_PROCFS_READ) 328 KAUTH_REQ_PROCESS_PROCFS_READ)
327 329
328 mutex_enter(p2->p_lock); 330 mutex_enter(p2->p_lock);
329 error = kauth_authorize_process(l1->l_cred, KAUTH_PROCESS_PROCFS, 331 error = kauth_authorize_process(l1->l_cred, KAUTH_PROCESS_PROCFS,
330 p2, pfs, KAUTH_ARG(M2K(ap->a_mode)), NULL); 332 p2, pfs, KAUTH_ARG(M2K(ap->a_mode)), NULL);
331 mutex_exit(p2->p_lock); 333 mutex_exit(p2->p_lock);
332 if (error) { 334 if (error) {
333 procfs_proc_unlock(p2); 335 procfs_proc_unlock(p2);
334 return (error); 336 return (error);
335 } 337 }
336 338
337#undef M2K 339#undef M2K
338 340
339 switch (pfs->pfs_type) { 341 switch (pfs->pfs_type) {
340 case PFSmem: 342 case PFSmem:
341 if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) || 343 if (((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) ||
342 ((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))) { 344 ((pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))) {
343 error = EBUSY; 345 error = EBUSY;
344 break; 346 break;
345 } 347 }
346 348
347 if (!proc_isunder(p2, l1)) { 349 if (!proc_isunder(p2, l1)) {
348 error = EPERM; 350 error = EPERM;
349 break; 351 break;
350 } 352 }
351 353
352 if (ap->a_mode & FWRITE) 354 if (ap->a_mode & FWRITE)
353 pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL); 355 pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL);
354 356
355 break; 357 break;
356 358
357 case PFSregs: 359 case PFSregs:
358 case PFSfpregs: 360 case PFSfpregs:
359 if (!proc_isunder(p2, l1)) { 361 if (!proc_isunder(p2, l1)) {
360 error = EPERM; 362 error = EPERM;
361 break; 363 break;
362 } 364 }
363 break; 365 break;
364 366
365 default: 367 default:
366 break; 368 break;
367 } 369 }
368 370
369 procfs_proc_unlock(p2); 371 procfs_proc_unlock(p2);
370 return (error); 372 return (error);
371} 373}
372 374
373/* 375/*
374 * close the pfsnode (vp) after doing i/o. 376 * close the pfsnode (vp) after doing i/o.
375 * (vp) is not locked on entry or exit. 377 * (vp) is not locked on entry or exit.
376 * 378 *
377 * nothing to do for procfs other than undo 379 * nothing to do for procfs other than undo
378 * any exclusive open flag (see _open above). 380 * any exclusive open flag (see _open above).
379 */ 381 */
380int 382int
381procfs_close(void *v) 383procfs_close(void *v)
382{ 384{
383 struct vop_close_args /* { 385 struct vop_close_args /* {
384 struct vnode *a_vp; 386 struct vnode *a_vp;
385 int a_fflag; 387 int a_fflag;
386 kauth_cred_t a_cred; 388 kauth_cred_t a_cred;
387 } */ *ap = v; 389 } */ *ap = v;
388 struct pfsnode *pfs = VTOPFS(ap->a_vp); 390 struct pfsnode *pfs = VTOPFS(ap->a_vp);
389 391
390 switch (pfs->pfs_type) { 392 switch (pfs->pfs_type) {
391 case PFSmem: 393 case PFSmem:
392 if ((ap->a_fflag & FWRITE) && (pfs->pfs_flags & O_EXCL)) 394 if ((ap->a_fflag & FWRITE) && (pfs->pfs_flags & O_EXCL))
393 pfs->pfs_flags &= ~(FWRITE|O_EXCL); 395 pfs->pfs_flags &= ~(FWRITE|O_EXCL);
394 break; 396 break;
395 397
396 default: 398 default:
397 break; 399 break;
398 } 400 }
399 401
400 return (0); 402 return (0);
401} 403}
402 404
403/* 405/*
404 * _inactive is called when the pfsnode 406 * _inactive is called when the pfsnode
405 * is vrele'd and the reference count goes 407 * is vrele'd and the reference count goes
406 * to zero. (vp) will be on the vnode free 408 * to zero. (vp) will be on the vnode free
407 * list, so to get it back vget() must be 409 * list, so to get it back vget() must be
408 * used. 410 * used.
409 * 411 *
410 * (vp) is locked on entry, but must be unlocked on exit. 412 * (vp) is locked on entry, but must be unlocked on exit.
411 */ 413 */
412int 414int
413procfs_inactive(void *v) 415procfs_inactive(void *v)
414{ 416{
415 struct vop_inactive_args /* { 417 struct vop_inactive_args /* {
416 struct vnode *a_vp; 418 struct vnode *a_vp;
417 bool *a_recycle; 419 bool *a_recycle;
418 } */ *ap = v; 420 } */ *ap = v;
419 struct vnode *vp = ap->a_vp; 421 struct vnode *vp = ap->a_vp;
420 struct pfsnode *pfs = VTOPFS(vp); 422 struct pfsnode *pfs = VTOPFS(vp);
421 423
422 mutex_enter(proc_lock); 424 mutex_enter(proc_lock);
423 *ap->a_recycle = (proc_find(pfs->pfs_pid) == NULL); 425 *ap->a_recycle = (proc_find(pfs->pfs_pid) == NULL);
424 mutex_exit(proc_lock); 426 mutex_exit(proc_lock);
425 427
426 VOP_UNLOCK(vp); 428 VOP_UNLOCK(vp);
427 429
428 return (0); 430 return (0);
429} 431}
430 432
431/* 433/*
432 * _reclaim is called when getnewvnode() 434 * _reclaim is called when getnewvnode()
433 * wants to make use of an entry on the vnode 435 * wants to make use of an entry on the vnode
434 * free list. at this time the filesystem needs 436 * free list. at this time the filesystem needs
435 * to free any private data and remove the node 437 * to free any private data and remove the node
436 * from any private lists. 438 * from any private lists.
437 */ 439 */
438int 440int
439procfs_reclaim(void *v) 441procfs_reclaim(void *v)
440{ 442{
441 struct vop_reclaim_args /* { 443 struct vop_reclaim_args /* {
442 struct vnode *a_vp; 444 struct vnode *a_vp;
443 } */ *ap = v; 445 } */ *ap = v;
444 struct vnode *vp = ap->a_vp; 446 struct vnode *vp = ap->a_vp;
445 struct pfsnode *pfs = VTOPFS(vp); 447 struct pfsnode *pfs = VTOPFS(vp);
446 448
447 /* 449 /*
448 * To interlock with procfs_revoke_vnodes(). 450 * To interlock with procfs_revoke_vnodes().
449 */ 451 */
450 mutex_enter(vp->v_interlock); 452 mutex_enter(vp->v_interlock);
451 vp->v_data = NULL; 453 vp->v_data = NULL;
452 mutex_exit(vp->v_interlock); 454 mutex_exit(vp->v_interlock);
453 vcache_remove(vp->v_mount, &pfs->pfs_key, sizeof(pfs->pfs_key)); 455 vcache_remove(vp->v_mount, &pfs->pfs_key, sizeof(pfs->pfs_key));
454 kmem_free(pfs, sizeof(*pfs)); 456 kmem_free(pfs, sizeof(*pfs));
455 return 0; 457 return 0;
456} 458}
457 459
458/* 460/*
459 * Return POSIX pathconf information applicable to special devices. 461 * Return POSIX pathconf information applicable to special devices.
460 */ 462 */
461int 463int
462procfs_pathconf(void *v) 464procfs_pathconf(void *v)
463{ 465{
464 struct vop_pathconf_args /* { 466 struct vop_pathconf_args /* {
465 struct vnode *a_vp; 467 struct vnode *a_vp;
466 int a_name; 468 int a_name;
467 register_t *a_retval; 469 register_t *a_retval;
468 } */ *ap = v; 470 } */ *ap = v;
469 471
470 switch (ap->a_name) { 472 switch (ap->a_name) {
471 case _PC_LINK_MAX: 473 case _PC_LINK_MAX:
472 *ap->a_retval = LINK_MAX; 474 *ap->a_retval = LINK_MAX;
473 return (0); 475 return (0);
474 case _PC_MAX_CANON: 476 case _PC_MAX_CANON:
475 *ap->a_retval = MAX_CANON; 477 *ap->a_retval = MAX_CANON;
476 return (0); 478 return (0);
477 case _PC_MAX_INPUT: 479 case _PC_MAX_INPUT:
478 *ap->a_retval = MAX_INPUT; 480 *ap->a_retval = MAX_INPUT;
479 return (0); 481 return (0);
480 case _PC_PIPE_BUF: 482 case _PC_PIPE_BUF:
481 *ap->a_retval = PIPE_BUF; 483 *ap->a_retval = PIPE_BUF;
482 return (0); 484 return (0);
483 case _PC_CHOWN_RESTRICTED: 485 case _PC_CHOWN_RESTRICTED:
484 *ap->a_retval = 1; 486 *ap->a_retval = 1;
485 return (0); 487 return (0);
486 case _PC_VDISABLE: 488 case _PC_VDISABLE:
487 *ap->a_retval = _POSIX_VDISABLE; 489 *ap->a_retval = _POSIX_VDISABLE;
488 return (0); 490 return (0);
489 case _PC_SYNC_IO: 491 case _PC_SYNC_IO:
490 *ap->a_retval = 1; 492 *ap->a_retval = 1;
491 return (0); 493 return (0);
492 default: 494 default:
493 return (EINVAL); 495 return (EINVAL);
494 } 496 }
495 /* NOTREACHED */ 497 /* NOTREACHED */
496} 498}
497 499
498/* 500/*
499 * _print is used for debugging. 501 * _print is used for debugging.
500 * just print a readable description 502 * just print a readable description
501 * of (vp). 503 * of (vp).
502 */ 504 */
503int 505int
504procfs_print(void *v) 506procfs_print(void *v)
505{ 507{
506 struct vop_print_args /* { 508 struct vop_print_args /* {
507 struct vnode *a_vp; 509 struct vnode *a_vp;
508 } */ *ap = v; 510 } */ *ap = v;
509 struct pfsnode *pfs = VTOPFS(ap->a_vp); 511 struct pfsnode *pfs = VTOPFS(ap->a_vp);
510 512
511 printf("tag VT_PROCFS, type %d, pid %d, mode %x, flags %lx\n", 513 printf("tag VT_PROCFS, type %d, pid %d, mode %x, flags %lx\n",
512 pfs->pfs_type, pfs->pfs_pid, pfs->pfs_mode, pfs->pfs_flags); 514 pfs->pfs_type, pfs->pfs_pid, pfs->pfs_mode, pfs->pfs_flags);
513 return 0; 515 return 0;
514} 516}
515 517
516int 518int
517procfs_link(void *v) 519procfs_link(void *v)
518{ 520{
519 struct vop_link_args /* { 521 struct vop_link_args /* {
520 struct vnode *a_dvp; 522 struct vnode *a_dvp;
521 struct vnode *a_vp; 523 struct vnode *a_vp;
522 struct componentname *a_cnp; 524 struct componentname *a_cnp;
523 } */ *ap = v; 525 } */ *ap = v;
524 526
525 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 527 VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
526 vput(ap->a_dvp); 528 vput(ap->a_dvp);
527 return (EROFS); 529 return (EROFS);
528} 530}
529 531
530int 532int
531procfs_symlink(void *v) 533procfs_symlink(void *v)
532{ 534{
533 struct vop_symlink_v3_args /* { 535 struct vop_symlink_v3_args /* {
534 struct vnode *a_dvp; 536 struct vnode *a_dvp;
535 struct vnode **a_vpp; 537 struct vnode **a_vpp;
536 struct componentname *a_cnp; 538 struct componentname *a_cnp;
537 struct vattr *a_vap; 539 struct vattr *a_vap;
538 char *a_target; 540 char *a_target;
539 } */ *ap = v; 541 } */ *ap = v;
540 542
541 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 543 VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
542 return (EROFS); 544 return (EROFS);
543} 545}
544 546
545/* 547/*
546 * Works out the path to (and vnode of) the target process's current 548 * Works out the path to (and vnode of) the target process's current
547 * working directory or chroot. If the caller is in a chroot and 549 * working directory or chroot. If the caller is in a chroot and
548 * can't "reach" the target's cwd or root (or some other error 550 * can't "reach" the target's cwd or root (or some other error
549 * occurs), a "/" is returned for the path and a NULL pointer is 551 * occurs), a "/" is returned for the path and a NULL pointer is
550 * returned for the vnode. 552 * returned for the vnode.
551 */ 553 */
552static void 554static void
553procfs_dir(pfstype t, struct lwp *caller, struct proc *target, char **bpp, 555procfs_dir(pfstype t, struct lwp *caller, struct proc *target, char **bpp,
554 char *path, size_t len) 556 char *path, size_t len)
555{ 557{
556 struct cwdinfo *cwdi; 558 struct cwdinfo *cwdi;
557 struct vnode *vp, *rvp; 559 struct vnode *vp, *rvp;
558 char *bp; 560 char *bp;
559 561
560 cwdi = caller->l_proc->p_cwdi; 562 cwdi = caller->l_proc->p_cwdi;
561 rw_enter(&cwdi->cwdi_lock, RW_READER); 563 rw_enter(&cwdi->cwdi_lock, RW_READER);
562 564
563 rvp = cwdi->cwdi_rdir; 565 rvp = cwdi->cwdi_rdir;
564 bp = bpp ? *bpp : NULL; 566 bp = bpp ? *bpp : NULL;
565 567
566 switch (t) { 568 switch (t) {
567 case PFScwd: 569 case PFScwd:
568 vp = target->p_cwdi->cwdi_cdir; 570 vp = target->p_cwdi->cwdi_cdir;
569 break; 571 break;
570 case PFSchroot: 572 case PFSchroot:
571 vp = target->p_cwdi->cwdi_rdir; 573 vp = target->p_cwdi->cwdi_rdir;
572 break; 574 break;
573 case PFSexe: 575 case PFSexe:
574 vp = target->p_textvp; 576 vp = target->p_textvp;
575 break; 577 break;
576 default: 578 default:
577 rw_exit(&cwdi->cwdi_lock); 579 rw_exit(&cwdi->cwdi_lock);
578 return; 580 return;
579 } 581 }
580 582
581 /* 583 /*
582 * XXX: this horrible kludge avoids locking panics when 584 * XXX: this horrible kludge avoids locking panics when
583 * attempting to lookup links that point to within procfs 585 * attempting to lookup links that point to within procfs
584 */ 586 */
585 if (vp != NULL && vp->v_tag == VT_PROCFS) { 587 if (vp != NULL && vp->v_tag == VT_PROCFS) {
586 if (bpp) { 588 if (bpp) {
587 *--bp = '/'; 589 *--bp = '/';
588 *bpp = bp; 590 *bpp = bp;
589 } 591 }
590 rw_exit(&cwdi->cwdi_lock); 592 rw_exit(&cwdi->cwdi_lock);
591 return; 593 return;
592 } 594 }
593 595
594 if (rvp == NULL) 596 if (rvp == NULL)
595 rvp = rootvnode; 597 rvp = rootvnode;
596 if (vp == NULL || getcwd_common(vp, rvp, bp ? &bp : NULL, path, 598 if (vp == NULL || getcwd_common(vp, rvp, bp ? &bp : NULL, path,
597 len / 2, 0, caller) != 0) { 599 len / 2, 0, caller) != 0) {
598 vp = NULL; 600 vp = NULL;
599 if (bpp) { 601 if (bpp) {
600/*  602/*
601 if (t == PFSexe) { 603 if (t == PFSexe) {
602 snprintf(path, len, "%s/%d/file" 604 snprintf(path, len, "%s/%d/file"
603 mp->mnt_stat.f_mntonname, pfs->pfs_pid); 605 mp->mnt_stat.f_mntonname, pfs->pfs_pid);
604 } else */ { 606 } else */ {
605 bp = *bpp; 607 bp = *bpp;
606 *--bp = '/'; 608 *--bp = '/';
607 } 609 }
608 } 610 }
609 } 611 }
610 612
611 if (bpp) 613 if (bpp)
612 *bpp = bp; 614 *bpp = bp;
613 615
614 rw_exit(&cwdi->cwdi_lock); 616 rw_exit(&cwdi->cwdi_lock);
615} 617}
616 618
617/* 619/*
618 * Invent attributes for pfsnode (vp) and store 620 * Invent attributes for pfsnode (vp) and store
619 * them in (vap). 621 * them in (vap).
620 * Directories lengths are returned as zero since 622 * Directories lengths are returned as zero since
621 * any real length would require the genuine size 623 * any real length would require the genuine size
622 * to be computed, and nothing cares anyway. 624 * to be computed, and nothing cares anyway.
623 * 625 *
624 * this is relatively minimal for procfs. 626 * this is relatively minimal for procfs.
625 */ 627 */
626int 628int
627procfs_getattr(void *v) 629procfs_getattr(void *v)
628{ 630{
629 struct vop_getattr_args /* { 631 struct vop_getattr_args /* {
630 struct vnode *a_vp; 632 struct vnode *a_vp;
631 struct vattr *a_vap; 633 struct vattr *a_vap;
632 kauth_cred_t a_cred; 634 kauth_cred_t a_cred;
633 } */ *ap = v; 635 } */ *ap = v;
634 struct pfsnode *pfs = VTOPFS(ap->a_vp); 636 struct pfsnode *pfs = VTOPFS(ap->a_vp);
635 struct vattr *vap = ap->a_vap; 637 struct vattr *vap = ap->a_vap;
636 struct proc *procp; 638 struct proc *procp;
637 char *path; 639 char *path;
638 int error; 640 int error;
639 641
640 /* first check the process still exists */ 642 /* first check the process still exists */
641 switch (pfs->pfs_type) { 643 switch (pfs->pfs_type) {
642 case PFSroot: 644 case PFSroot:
643 case PFScurproc: 645 case PFScurproc:
644 case PFSself: 646 case PFSself:
645 procp = NULL; 647 procp = NULL;
646 break; 648 break;
647 649
648 default: 650 default:
649 error = procfs_proc_lock(pfs->pfs_pid, &procp, ENOENT); 651 error = procfs_proc_lock(pfs->pfs_pid, &procp, ENOENT);
650 if (error != 0) 652 if (error != 0)
651 return (error); 653 return (error);
652 break; 654 break;
653 } 655 }
654 656
655 switch (pfs->pfs_type) { 657 switch (pfs->pfs_type) {
656 case PFStask: 658 case PFStask:
657 if (pfs->pfs_fd == -1) { 659 if (pfs->pfs_fd == -1) {
658 path = NULL; 660 path = NULL;
659 break; 661 break;
660 } 662 }
661 /*FALLTHROUGH*/ 663 /*FALLTHROUGH*/
662 case PFScwd: 664 case PFScwd:
663 case PFSchroot: 665 case PFSchroot:
664 case PFSexe: 666 case PFSexe:
665 path = malloc(MAXPATHLEN + 4, M_TEMP, M_WAITOK|M_CANFAIL); 667 path = malloc(MAXPATHLEN + 4, M_TEMP, M_WAITOK|M_CANFAIL);
666 if (path == NULL && procp != NULL) { 668 if (path == NULL && procp != NULL) {
667 procfs_proc_unlock(procp); 669 procfs_proc_unlock(procp);
668 return (ENOMEM); 670 return (ENOMEM);
669 } 671 }
670 break; 672 break;
671 673
672 default: 674 default:
673 path = NULL; 675 path = NULL;
674 break; 676 break;
675 } 677 }
676 678
677 if (procp != NULL) { 679 if (procp != NULL) {
678 mutex_enter(procp->p_lock); 680 mutex_enter(procp->p_lock);
679 error = kauth_authorize_process(kauth_cred_get(), 681 error = kauth_authorize_process(kauth_cred_get(),
680 KAUTH_PROCESS_CANSEE, procp, 682 KAUTH_PROCESS_CANSEE, procp,
681 KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL); 683 KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
682 mutex_exit(procp->p_lock); 684 mutex_exit(procp->p_lock);
683 if (error != 0) { 685 if (error != 0) {
684 procfs_proc_unlock(procp); 686 procfs_proc_unlock(procp);
685 if (path != NULL) 687 if (path != NULL)
686 free(path, M_TEMP); 688 free(path, M_TEMP);
687 return (ENOENT); 689 return (ENOENT);
688 } 690 }
689 } 691 }
690 692
691 error = 0; 693 error = 0;
692 694
693 /* start by zeroing out the attributes */ 695 /* start by zeroing out the attributes */
694 vattr_null(vap); 696 vattr_null(vap);
695 697
696 /* next do all the common fields */ 698 /* next do all the common fields */
697 vap->va_type = ap->a_vp->v_type; 699 vap->va_type = ap->a_vp->v_type;
698 vap->va_mode = pfs->pfs_mode; 700 vap->va_mode = pfs->pfs_mode;
699 vap->va_fileid = pfs->pfs_fileno; 701 vap->va_fileid = pfs->pfs_fileno;
700 vap->va_flags = 0; 702 vap->va_flags = 0;
701 vap->va_blocksize = PAGE_SIZE; 703 vap->va_blocksize = PAGE_SIZE;
702 704
703 /* 705 /*
704 * Make all times be current TOD. 706 * Make all times be current TOD.
705 * 707 *
706 * It would be possible to get the process start 708 * It would be possible to get the process start
707 * time from the p_stats structure, but there's 709 * time from the p_stats structure, but there's
708 * no "file creation" time stamp anyway, and the 710 * no "file creation" time stamp anyway, and the
709 * p_stats structure is not addressable if u. gets 711 * p_stats structure is not addressable if u. gets
710 * swapped out for that process. 712 * swapped out for that process.
711 */ 713 */
712 getnanotime(&vap->va_ctime); 714 getnanotime(&vap->va_ctime);
713 vap->va_atime = vap->va_mtime = vap->va_ctime; 715 vap->va_atime = vap->va_mtime = vap->va_ctime;
714 if (procp) 716 if (procp)
715 TIMEVAL_TO_TIMESPEC(&procp->p_stats->p_start, 717 TIMEVAL_TO_TIMESPEC(&procp->p_stats->p_start,
716 &vap->va_birthtime); 718 &vap->va_birthtime);
717 else 719 else
718 getnanotime(&vap->va_birthtime); 720 getnanotime(&vap->va_birthtime);
719 721
720 switch (pfs->pfs_type) { 722 switch (pfs->pfs_type) {
721 case PFSmem: 723 case PFSmem:
722 case PFSregs: 724 case PFSregs:
723 case PFSfpregs: 725 case PFSfpregs:
724#if defined(__HAVE_PROCFS_MACHDEP) && defined(PROCFS_MACHDEP_PROTECT_CASES) 726#if defined(__HAVE_PROCFS_MACHDEP) && defined(PROCFS_MACHDEP_PROTECT_CASES)
725 PROCFS_MACHDEP_PROTECT_CASES 727 PROCFS_MACHDEP_PROTECT_CASES
726#endif 728#endif
727 /* 729 /*
728 * If the process has exercised some setuid or setgid 730 * If the process has exercised some setuid or setgid
729 * privilege, then rip away read/write permission so 731 * privilege, then rip away read/write permission so
730 * that only root can gain access. 732 * that only root can gain access.
731 */ 733 */
732 if (procp->p_flag & PK_SUGID) 734 if (procp->p_flag & PK_SUGID)
733 vap->va_mode &= ~(S_IRUSR|S_IWUSR); 735 vap->va_mode &= ~(S_IRUSR|S_IWUSR);
734 /* FALLTHROUGH */ 736 /* FALLTHROUGH */
735 case PFSctl: 737 case PFSctl:
736 case PFSstatus: 738 case PFSstatus:
737 case PFSstat: 739 case PFSstat:
738 case PFSnote: 740 case PFSnote:
739 case PFSnotepg: 741 case PFSnotepg:
740 case PFSmap: 742 case PFSmap:
741 case PFSmaps: 743 case PFSmaps:
742 case PFScmdline: 744 case PFScmdline:
743 case PFSemul: 745 case PFSemul:
744 case PFSstatm: 746 case PFSstatm:
745 if (pfs->pfs_type == PFSmap || pfs->pfs_type == PFSmaps) 747 if (pfs->pfs_type == PFSmap || pfs->pfs_type == PFSmaps)
746 vap->va_mode = S_IRUSR; 748 vap->va_mode = S_IRUSR;
747 vap->va_nlink = 1; 749 vap->va_nlink = 1;
748 vap->va_uid = kauth_cred_geteuid(procp->p_cred); 750 vap->va_uid = kauth_cred_geteuid(procp->p_cred);
749 vap->va_gid = kauth_cred_getegid(procp->p_cred); 751 vap->va_gid = kauth_cred_getegid(procp->p_cred);
750 break; 752 break;
751 case PFSmeminfo: 753 case PFSmeminfo:
752 case PFSdevices: 754 case PFSdevices:
753 case PFScpuinfo: 755 case PFScpuinfo:
754 case PFSuptime: 756 case PFSuptime:
755 case PFSmounts: 757 case PFSmounts:
756 case PFScpustat: 758 case PFScpustat:
757 case PFSloadavg: 759 case PFSloadavg:
758 case PFSversion: 760 case PFSversion:
759 vap->va_nlink = 1; 761 vap->va_nlink = 1;
760 vap->va_uid = vap->va_gid = 0; 762 vap->va_uid = vap->va_gid = 0;
761 break; 763 break;
762 764
763 default: 765 default:
764 break; 766 break;
765 } 767 }
766 768
767 /* 769 /*
768 * now do the object specific fields 770 * now do the object specific fields
769 * 771 *
770 * The size could be set from struct reg, but it's hardly 772 * The size could be set from struct reg, but it's hardly
771 * worth the trouble, and it puts some (potentially) machine 773 * worth the trouble, and it puts some (potentially) machine
772 * dependent data into this machine-independent code. If it 774 * dependent data into this machine-independent code. If it
773 * becomes important then this function should break out into 775 * becomes important then this function should break out into
774 * a per-file stat function in the corresponding .c file. 776 * a per-file stat function in the corresponding .c file.
775 */ 777 */
776 778
777 switch (pfs->pfs_type) { 779 switch (pfs->pfs_type) {
778 case PFSroot: 780 case PFSroot:
779 /* 781 /*
780 * Set nlink to 1 to tell fts(3) we don't actually know. 782 * Set nlink to 1 to tell fts(3) we don't actually know.
781 */ 783 */
782 vap->va_nlink = 1; 784 vap->va_nlink = 1;
783 vap->va_uid = 0; 785 vap->va_uid = 0;
784 vap->va_gid = 0; 786 vap->va_gid = 0;
785 vap->va_bytes = vap->va_size = DEV_BSIZE; 787 vap->va_bytes = vap->va_size = DEV_BSIZE;
786 break; 788 break;
787 789
788 case PFSself: 790 case PFSself:
789 case PFScurproc: { 791 case PFScurproc: {
790 char bf[16]; /* should be enough */ 792 char bf[16]; /* should be enough */
791 vap->va_nlink = 1; 793 vap->va_nlink = 1;
792 vap->va_uid = 0; 794 vap->va_uid = 0;
793 vap->va_gid = 0; 795 vap->va_gid = 0;
794 vap->va_bytes = vap->va_size = 796 vap->va_bytes = vap->va_size =
795 snprintf(bf, sizeof(bf), "%ld", (long)curproc->p_pid); 797 snprintf(bf, sizeof(bf), "%ld", (long)curproc->p_pid);
796 break; 798 break;
797 } 799 }
798 case PFStask: 800 case PFStask:
799 if (pfs->pfs_fd != -1) { 801 if (pfs->pfs_fd != -1) {
800 char bf[4]; /* should be enough */ 802 char bf[4]; /* should be enough */
801 vap->va_nlink = 1; 803 vap->va_nlink = 1;
802 vap->va_uid = 0; 804 vap->va_uid = 0;
803 vap->va_gid = 0; 805 vap->va_gid = 0;
804 vap->va_bytes = vap->va_size = 806 vap->va_bytes = vap->va_size =
805 snprintf(bf, sizeof(bf), ".."); 807 snprintf(bf, sizeof(bf), "..");
806 break; 808 break;
807 } 809 }
808 /*FALLTHROUGH*/ 810 /*FALLTHROUGH*/
809 case PFSfd: 811 case PFSfd:
810 if (pfs->pfs_fd != -1) { 812 if (pfs->pfs_fd != -1) {
811 file_t *fp; 813 file_t *fp;
812 814
813 fp = fd_getfile2(procp, pfs->pfs_fd); 815 fp = fd_getfile2(procp, pfs->pfs_fd);
814 if (fp == NULL) { 816 if (fp == NULL) {
815 error = EBADF; 817 error = EBADF;
816 break; 818 break;
817 } 819 }
818 vap->va_nlink = 1; 820 vap->va_nlink = 1;
819 vap->va_uid = kauth_cred_geteuid(fp->f_cred); 821 vap->va_uid = kauth_cred_geteuid(fp->f_cred);
820 vap->va_gid = kauth_cred_getegid(fp->f_cred); 822 vap->va_gid = kauth_cred_getegid(fp->f_cred);
821 switch (fp->f_type) { 823 switch (fp->f_type) {
822 case DTYPE_VNODE: 824 case DTYPE_VNODE:
823 vap->va_bytes = vap->va_size = 825 vap->va_bytes = vap->va_size =
824 ((struct vnode *)fp->f_data)->v_size; 826 ((struct vnode *)fp->f_data)->v_size;
825 break; 827 break;
826 default: 828 default:
827 vap->va_bytes = vap->va_size = 0; 829 vap->va_bytes = vap->va_size = 0;
828 break; 830 break;
829 } 831 }
830 closef(fp); 832 closef(fp);
831 break; 833 break;
832 } 834 }
833 /*FALLTHROUGH*/ 835 /*FALLTHROUGH*/
834 case PFSproc: 836 case PFSproc:
835 vap->va_nlink = 2; 837 vap->va_nlink = 2;
836 vap->va_uid = kauth_cred_geteuid(procp->p_cred); 838 vap->va_uid = kauth_cred_geteuid(procp->p_cred);
837 vap->va_gid = kauth_cred_getegid(procp->p_cred); 839 vap->va_gid = kauth_cred_getegid(procp->p_cred);
838 vap->va_bytes = vap->va_size = DEV_BSIZE; 840 vap->va_bytes = vap->va_size = DEV_BSIZE;
839 break; 841 break;
840 842
841 case PFSfile: 843 case PFSfile:
842 error = EOPNOTSUPP; 844 error = EOPNOTSUPP;
843 break; 845 break;
844 846
845 case PFSmem: 847 case PFSmem:
846 vap->va_bytes = vap->va_size = 848 vap->va_bytes = vap->va_size =
847 ctob(procp->p_vmspace->vm_tsize + 849 ctob(procp->p_vmspace->vm_tsize +
848 procp->p_vmspace->vm_dsize + 850 procp->p_vmspace->vm_dsize +
849 procp->p_vmspace->vm_ssize); 851 procp->p_vmspace->vm_ssize);
850 break; 852 break;
851 853
852#if defined(PT_GETREGS) || defined(PT_SETREGS) 854#if defined(PT_GETREGS) || defined(PT_SETREGS)
853 case PFSregs: 855 case PFSregs:
854 vap->va_bytes = vap->va_size = sizeof(struct reg); 856 vap->va_bytes = vap->va_size = sizeof(struct reg);
855 break; 857 break;
856#endif 858#endif
857 859
858#if defined(PT_GETFPREGS) || defined(PT_SETFPREGS) 860#if defined(PT_GETFPREGS) || defined(PT_SETFPREGS)
859 case PFSfpregs: 861 case PFSfpregs:
860 vap->va_bytes = vap->va_size = sizeof(struct fpreg); 862 vap->va_bytes = vap->va_size = sizeof(struct fpreg);
861 break; 863 break;
862#endif 864#endif
863 865
864 case PFSctl: 866 case PFSctl:
865 case PFSstatus: 867 case PFSstatus:
866 case PFSstat: 868 case PFSstat:
867 case PFSnote: 869 case PFSnote:
868 case PFSnotepg: 870 case PFSnotepg:
869 case PFScmdline: 871 case PFScmdline:
870 case PFSmeminfo: 872 case PFSmeminfo:
871 case PFSdevices: 873 case PFSdevices:
872 case PFScpuinfo: 874 case PFScpuinfo:
873 case PFSuptime: 875 case PFSuptime:
874 case PFSmounts: 876 case PFSmounts:
875 case PFScpustat: 877 case PFScpustat:
876 case PFSloadavg: 878 case PFSloadavg:
877 case PFSstatm: 879 case PFSstatm:
878 case PFSversion: 880 case PFSversion:
879 vap->va_bytes = vap->va_size = 0; 881 vap->va_bytes = vap->va_size = 0;
880 break; 882 break;
881 case PFSmap: 883 case PFSmap:
882 case PFSmaps: 884 case PFSmaps:
883 /* 885 /*
884 * Advise a larger blocksize for the map files, so that 886 * Advise a larger blocksize for the map files, so that
885 * they may be read in one pass. 887 * they may be read in one pass.
886 */ 888 */
887 vap->va_blocksize = 4 * PAGE_SIZE; 889 vap->va_blocksize = 4 * PAGE_SIZE;
888 vap->va_bytes = vap->va_size = 0; 890 vap->va_bytes = vap->va_size = 0;
889 break; 891 break;
890 892
891 case PFScwd: 893 case PFScwd:
892 case PFSchroot: 894 case PFSchroot:
893 case PFSexe: { 895 case PFSexe: {
894 char *bp; 896 char *bp;
895 897
896 vap->va_nlink = 1; 898 vap->va_nlink = 1;
897 vap->va_uid = 0; 899 vap->va_uid = 0;
898 vap->va_gid = 0; 900 vap->va_gid = 0;
899 bp = path + MAXPATHLEN; 901 bp = path + MAXPATHLEN;
900 *--bp = '\0'; 902 *--bp = '\0';
901 procfs_dir(pfs->pfs_type, curlwp, procp, &bp, path, 903 procfs_dir(pfs->pfs_type, curlwp, procp, &bp, path,
902 MAXPATHLEN); 904 MAXPATHLEN);
903 vap->va_bytes = vap->va_size = strlen(bp); 905 vap->va_bytes = vap->va_size = strlen(bp);
904 break; 906 break;
905 } 907 }
906 908
907 case PFSemul: 909 case PFSemul:
908 vap->va_bytes = vap->va_size = strlen(procp->p_emul->e_name); 910 vap->va_bytes = vap->va_size = strlen(procp->p_emul->e_name);
909 break; 911 break;
910 912
911#ifdef __HAVE_PROCFS_MACHDEP 913#ifdef __HAVE_PROCFS_MACHDEP
912 PROCFS_MACHDEP_NODETYPE_CASES 914 PROCFS_MACHDEP_NODETYPE_CASES
913 error = procfs_machdep_getattr(ap->a_vp, vap, procp); 915 error = procfs_machdep_getattr(ap->a_vp, vap, procp);
914 break; 916 break;
915#endif 917#endif
916 918
917 default: 919 default:
918 panic("procfs_getattr"); 920 panic("procfs_getattr");
919 } 921 }
920 922
921 if (procp != NULL) 923 if (procp != NULL)
922 procfs_proc_unlock(procp); 924 procfs_proc_unlock(procp);
923 if (path != NULL) 925 if (path != NULL)
924 free(path, M_TEMP); 926 free(path, M_TEMP);
925 927
926 return (error); 928 return (error);
927} 929}
928 930
929/*ARGSUSED*/ 931/*ARGSUSED*/
930int 932int
931procfs_setattr(void *v) 933procfs_setattr(void *v)
932{ 934{
933 /* 935 /*
934 * just fake out attribute setting 936 * just fake out attribute setting
935 * it's not good to generate an error 937 * it's not good to generate an error
936 * return, otherwise things like creat() 938 * return, otherwise things like creat()
937 * will fail when they try to set the 939 * will fail when they try to set the
938 * file length to 0. worse, this means 940 * file length to 0. worse, this means
939 * that echo $note > /proc/$pid/note will fail. 941 * that echo $note > /proc/$pid/note will fail.
940 */ 942 */
941 943
942 return (0); 944 return (0);
943} 945}
944 946
945/* 947/*
946 * implement access checking. 948 * implement access checking.
947 * 949 *
948 * actually, the check for super-user is slightly 950 * actually, the check for super-user is slightly
949 * broken since it will allow read access to write-only 951 * broken since it will allow read access to write-only
950 * objects. this doesn't cause any particular trouble 952 * objects. this doesn't cause any particular trouble
951 * but does mean that the i/o entry points need to check 953 * but does mean that the i/o entry points need to check
952 * that the operation really does make sense. 954 * that the operation really does make sense.
953 */ 955 */
954int 956int
955procfs_access(void *v) 957procfs_access(void *v)
956{ 958{
957 struct vop_access_args /* { 959 struct vop_access_args /* {
958 struct vnode *a_vp; 960 struct vnode *a_vp;
959 int a_mode; 961 int a_mode;
960 kauth_cred_t a_cred; 962 kauth_cred_t a_cred;
961 } */ *ap = v; 963 } */ *ap = v;
962 struct vattr va; 964 struct vattr va;
963 int error; 965 int error;
964 966
965 if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred)) != 0) 967 if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred)) != 0)
966 return (error); 968 return (error);
967 969
968 return kauth_authorize_vnode(ap->a_cred, 970 return kauth_authorize_vnode(ap->a_cred,
969 KAUTH_ACCESS_ACTION(ap->a_mode, ap->a_vp->v_type, va.va_mode), 971 KAUTH_ACCESS_ACTION(ap->a_mode, ap->a_vp->v_type, va.va_mode),
970 ap->a_vp, NULL, genfs_can_access(va.va_type, va.va_mode, 972 ap->a_vp, NULL, genfs_can_access(va.va_type, va.va_mode,
971 va.va_uid, va.va_gid, ap->a_mode, ap->a_cred)); 973 va.va_uid, va.va_gid, ap->a_mode, ap->a_cred));
972} 974}
973 975
974/* 976/*
975 * lookup. this is incredibly complicated in the 977 * lookup. this is incredibly complicated in the
976 * general case, however for most pseudo-filesystems 978 * general case, however for most pseudo-filesystems
977 * very little needs to be done. 979 * very little needs to be done.
978 * 980 *
979 * Locking isn't hard here, just poorly documented. 981 * Locking isn't hard here, just poorly documented.
980 * 982 *
981 * If we're looking up ".", just vref the parent & return it. 983 * If we're looking up ".", just vref the parent & return it.
982 * 984 *
983 * If we're looking up "..", unlock the parent, and lock "..". If everything 985 * If we're looking up "..", unlock the parent, and lock "..". If everything
984 * went ok, and we're on the last component and the caller requested the 986 * went ok, and we're on the last component and the caller requested the
985 * parent locked, try to re-lock the parent. We do this to prevent lock 987 * parent locked, try to re-lock the parent. We do this to prevent lock
986 * races. 988 * races.
987 * 989 *
988 * For anything else, get the needed node. Then unlock the parent if not 990 * For anything else, get the needed node. Then unlock the parent if not
989 * the last component or not LOCKPARENT (i.e. if we wouldn't re-lock the 991 * the last component or not LOCKPARENT (i.e. if we wouldn't re-lock the
990 * parent in the .. case). 992 * parent in the .. case).
991 * 993 *
992 * We try to exit with the parent locked in error cases. 994 * We try to exit with the parent locked in error cases.
993 */ 995 */
994int 996int
995procfs_lookup(void *v) 997procfs_lookup(void *v)
996{ 998{
997 struct vop_lookup_v2_args /* { 999 struct vop_lookup_v2_args /* {
998 struct vnode * a_dvp; 1000 struct vnode * a_dvp;
999 struct vnode ** a_vpp; 1001 struct vnode ** a_vpp;
1000 struct componentname * a_cnp; 1002 struct componentname * a_cnp;
1001 } */ *ap = v; 1003 } */ *ap = v;
1002 struct componentname *cnp = ap->a_cnp; 1004 struct componentname *cnp = ap->a_cnp;
1003 struct vnode **vpp = ap->a_vpp; 1005 struct vnode **vpp = ap->a_vpp;
1004 struct vnode *dvp = ap->a_dvp; 1006 struct vnode *dvp = ap->a_dvp;
1005 const char *pname = cnp->cn_nameptr; 1007 const char *pname = cnp->cn_nameptr;
1006 const struct proc_target *pt = NULL; 1008 const struct proc_target *pt = NULL;
1007 struct vnode *fvp; 1009 struct vnode *fvp;
1008 pid_t pid, vnpid; 1010 pid_t pid, vnpid;
1009 struct pfsnode *pfs; 1011 struct pfsnode *pfs;
1010 struct proc *p = NULL; 1012 struct proc *p = NULL;
1011 struct lwp *plwp; 1013 struct lwp *plwp;
1012 int i, error; 1014 int i, error;
1013 pfstype type; 1015 pfstype type;
1014 1016
1015 *vpp = NULL; 1017 *vpp = NULL;
1016 1018
1017 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) 1019 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
1018 return (EROFS); 1020 return (EROFS);
1019 1021
1020 if (cnp->cn_namelen == 1 && *pname == '.') { 1022 if (cnp->cn_namelen == 1 && *pname == '.') {
1021 *vpp = dvp; 1023 *vpp = dvp;
1022 vref(dvp); 1024 vref(dvp);
1023 return (0); 1025 return (0);
1024 } 1026 }
1025 1027
1026 pfs = VTOPFS(dvp); 1028 pfs = VTOPFS(dvp);
1027 switch (pfs->pfs_type) { 1029 switch (pfs->pfs_type) {
1028 case PFSroot: 1030 case PFSroot:
1029 /* 1031 /*
1030 * Shouldn't get here with .. in the root node. 1032 * Shouldn't get here with .. in the root node.
1031 */ 1033 */
1032 if (cnp->cn_flags & ISDOTDOT) 1034 if (cnp->cn_flags & ISDOTDOT)
1033 return (EIO); 1035 return (EIO);
1034 1036
1035 for (i = 0; i < nproc_root_targets; i++) { 1037 for (i = 0; i < nproc_root_targets; i++) {
1036 pt = &proc_root_targets[i]; 1038 pt = &proc_root_targets[i];
1037 /* 1039 /*
1038 * check for node match. proc is always NULL here, 1040 * check for node match. proc is always NULL here,
1039 * so call pt_valid with constant NULL lwp. 1041 * so call pt_valid with constant NULL lwp.
1040 */ 1042 */
1041 if (cnp->cn_namelen == pt->pt_namlen && 1043 if (cnp->cn_namelen == pt->pt_namlen &&
1042 memcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 && 1044 memcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 &&
1043 (pt->pt_valid == NULL || 1045 (pt->pt_valid == NULL ||
1044 (*pt->pt_valid)(NULL, dvp->v_mount))) 1046 (*pt->pt_valid)(NULL, dvp->v_mount)))
1045 break; 1047 break;
1046 } 1048 }
1047 1049
1048 if (i != nproc_root_targets) { 1050 if (i != nproc_root_targets) {
1049 error = procfs_allocvp(dvp->v_mount, vpp, 0, 1051 error = procfs_allocvp(dvp->v_mount, vpp, 0,
1050 pt->pt_pfstype, -1); 1052 pt->pt_pfstype, -1);
1051 return (error); 1053 return (error);
1052 } 1054 }
1053 1055
1054 if (CNEQ(cnp, "curproc", 7)) { 1056 if (CNEQ(cnp, "curproc", 7)) {
1055 pid = curproc->p_pid; 1057 pid = curproc->p_pid;
1056 vnpid = 0; 1058 vnpid = 0;
1057 type = PFScurproc; 1059 type = PFScurproc;
1058 } else if (CNEQ(cnp, "self", 4)) { 1060 } else if (CNEQ(cnp, "self", 4)) {
1059 pid = curproc->p_pid; 1061 pid = curproc->p_pid;
1060 vnpid = 0; 1062 vnpid = 0;
1061 type = PFSself; 1063 type = PFSself;
1062 } else { 1064 } else {
1063 pid = (pid_t)atoi(pname, cnp->cn_namelen); 1065 pid = (pid_t)atoi(pname, cnp->cn_namelen);
1064 vnpid = pid; 1066 vnpid = pid;
1065 type = PFSproc; 1067 type = PFSproc;
1066 } 1068 }
1067 1069
1068 if (procfs_proc_lock(pid, &p, ESRCH) != 0) 1070 if (procfs_proc_lock(pid, &p, ESRCH) != 0)
1069 break; 1071 break;
1070 error = procfs_allocvp(dvp->v_mount, vpp, vnpid, type, -1); 1072 error = procfs_allocvp(dvp->v_mount, vpp, vnpid, type, -1);
1071 procfs_proc_unlock(p); 1073 procfs_proc_unlock(p);
1072 return (error); 1074 return (error);
1073 1075
1074 case PFSproc: 1076 case PFSproc:
1075 if (cnp->cn_flags & ISDOTDOT) { 1077 if (cnp->cn_flags & ISDOTDOT) {
1076 error = procfs_allocvp(dvp->v_mount, vpp, 0, PFSroot, 1078 error = procfs_allocvp(dvp->v_mount, vpp, 0, PFSroot,
1077 -1); 1079 -1);
1078 return (error); 1080 return (error);
1079 } 1081 }
1080 1082
1081 if (procfs_proc_lock(pfs->pfs_pid, &p, ESRCH) != 0) 1083 if (procfs_proc_lock(pfs->pfs_pid, &p, ESRCH) != 0)
1082 break; 1084 break;
1083 1085
1084 mutex_enter(p->p_lock); 1086 mutex_enter(p->p_lock);
1085 LIST_FOREACH(plwp, &p->p_lwps, l_sibling) { 1087 LIST_FOREACH(plwp, &p->p_lwps, l_sibling) {
1086 if (plwp->l_stat != LSZOMB) 1088 if (plwp->l_stat != LSZOMB)
1087 break; 1089 break;
1088 } 1090 }
1089 /* Process is exiting if no-LWPS or all LWPs are LSZOMB */ 1091 /* Process is exiting if no-LWPS or all LWPs are LSZOMB */
1090 if (plwp == NULL) { 1092 if (plwp == NULL) {
1091 mutex_exit(p->p_lock); 1093 mutex_exit(p->p_lock);
1092 procfs_proc_unlock(p); 1094 procfs_proc_unlock(p);
1093 return ESRCH; 1095 return ESRCH;
1094 } 1096 }
1095 1097
1096 lwp_addref(plwp); 1098 lwp_addref(plwp);
1097 mutex_exit(p->p_lock); 1099 mutex_exit(p->p_lock);
1098 1100
1099 for (pt = proc_targets, i = 0; i < nproc_targets; pt++, i++) { 1101 for (pt = proc_targets, i = 0; i < nproc_targets; pt++, i++) {
1100 int found; 1102 int found;
1101 1103
1102 found = cnp->cn_namelen == pt->pt_namlen && 1104 found = cnp->cn_namelen == pt->pt_namlen &&
1103 memcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 && 1105 memcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 &&
1104 (pt->pt_valid == NULL 1106 (pt->pt_valid == NULL
1105 || (*pt->pt_valid)(plwp, dvp->v_mount)); 1107 || (*pt->pt_valid)(plwp, dvp->v_mount));
1106 if (found) 1108 if (found)
1107 break; 1109 break;
1108 } 1110 }
1109 lwp_delref(plwp); 1111 lwp_delref(plwp);
1110 1112
1111 if (i == nproc_targets) { 1113 if (i == nproc_targets) {
1112 procfs_proc_unlock(p); 1114 procfs_proc_unlock(p);
1113 break; 1115 break;
1114 } 1116 }
1115 if (pt->pt_pfstype == PFSfile) { 1117 if (pt->pt_pfstype == PFSfile) {
1116 fvp = p->p_textvp; 1118 fvp = p->p_textvp;
1117 /* We already checked that it exists. */ 1119 /* We already checked that it exists. */
1118 vref(fvp); 1120 vref(fvp);
1119 procfs_proc_unlock(p); 1121 procfs_proc_unlock(p);
1120 *vpp = fvp; 1122 *vpp = fvp;
1121 return (0); 1123 return (0);
1122 } 1124 }
1123 1125
1124 error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, 1126 error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
1125 pt->pt_pfstype, -1); 1127 pt->pt_pfstype, -1);
1126 procfs_proc_unlock(p); 1128 procfs_proc_unlock(p);
1127 return (error); 1129 return (error);
1128 1130
1129 case PFSfd: { 1131 case PFSfd: {
1130 int fd; 1132 int fd;
1131 file_t *fp; 1133 file_t *fp;
1132 1134
1133 if ((error = procfs_proc_lock(pfs->pfs_pid, &p, ENOENT)) != 0) 1135 if ((error = procfs_proc_lock(pfs->pfs_pid, &p, ENOENT)) != 0)
1134 return error; 1136 return error;
1135 1137
1136 if (cnp->cn_flags & ISDOTDOT) { 1138 if (cnp->cn_flags & ISDOTDOT) {
1137 error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, 1139 error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
1138 PFSproc, -1); 1140 PFSproc, -1);
1139 procfs_proc_unlock(p); 1141 procfs_proc_unlock(p);
1140 return (error); 1142 return (error);
1141 } 1143 }
1142 fd = atoi(pname, cnp->cn_namelen); 1144 fd = atoi(pname, cnp->cn_namelen);
1143 1145
1144 fp = fd_getfile2(p, fd); 1146 fp = fd_getfile2(p, fd);
1145 if (fp == NULL) { 1147 if (fp == NULL) {
1146 procfs_proc_unlock(p); 1148 procfs_proc_unlock(p);
1147 return ENOENT; 1149 return ENOENT;
1148 } 1150 }
1149 fvp = fp->f_data; 1151 fvp = fp->f_data;
1150 1152
1151 /* Don't show directories */ 1153 /* Don't show directories */
1152 if (fp->f_type == DTYPE_VNODE && fvp->v_type != VDIR) { 1154 if (fp->f_type == DTYPE_VNODE && fvp->v_type != VDIR) {
1153 vref(fvp); 1155 vref(fvp);
1154 closef(fp); 1156 closef(fp);
1155 procfs_proc_unlock(p); 1157 procfs_proc_unlock(p);
1156 *vpp = fvp; 1158 *vpp = fvp;
1157 return 0; 1159 return 0;
1158 } 1160 }
1159 1161
1160 closef(fp); 1162 closef(fp);
1161 error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, 1163 error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
1162 PFSfd, fd); 1164 PFSfd, fd);
1163 procfs_proc_unlock(p); 1165 procfs_proc_unlock(p);
1164 return error; 1166 return error;
1165 } 1167 }
1166 case PFStask: { 1168 case PFStask: {
1167 int xpid; 1169 int xpid;
1168 1170
1169 if ((error = procfs_proc_lock(pfs->pfs_pid, &p, ENOENT)) != 0) 1171 if ((error = procfs_proc_lock(pfs->pfs_pid, &p, ENOENT)) != 0)
1170 return error; 1172 return error;
1171 1173
1172 if (cnp->cn_flags & ISDOTDOT) { 1174 if (cnp->cn_flags & ISDOTDOT) {
1173 error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, 1175 error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
1174 PFSproc, -1); 1176 PFSproc, -1);
1175 procfs_proc_unlock(p); 1177 procfs_proc_unlock(p);
1176 return (error); 1178 return (error);
1177 } 1179 }
1178 xpid = atoi(pname, cnp->cn_namelen); 1180 xpid = atoi(pname, cnp->cn_namelen);
1179 1181
1180 if (xpid != pfs->pfs_pid) { 1182 if (xpid != pfs->pfs_pid) {
1181 procfs_proc_unlock(p); 1183 procfs_proc_unlock(p);
1182 return ENOENT; 1184 return ENOENT;
1183 } 1185 }
1184 error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid, 1186 error = procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
1185 PFStask, 0); 1187 PFStask, 0);
1186 procfs_proc_unlock(p); 1188 procfs_proc_unlock(p);
1187 return error; 1189 return error;
1188 } 1190 }
1189 default: 1191 default:
1190 return (ENOTDIR); 1192 return (ENOTDIR);
1191 } 1193 }
1192 1194
1193 return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS); 1195 return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
1194} 1196}
1195 1197
1196int 1198int
1197procfs_validfile(struct lwp *l, struct mount *mp) 1199procfs_validfile(struct lwp *l, struct mount *mp)
1198{ 1200{
1199 return l != NULL && l->l_proc != NULL && l->l_proc->p_textvp != NULL; 1201 return l != NULL && l->l_proc != NULL && l->l_proc->p_textvp != NULL;
1200} 1202}
1201 1203
1202static int 1204static int
1203procfs_validfile_linux(struct lwp *l, struct mount *mp) 1205procfs_validfile_linux(struct lwp *l, struct mount *mp)
1204{ 1206{
1205 int flags; 1207 int flags;
1206 1208
1207 flags = VFSTOPROC(mp)->pmnt_flags; 1209 flags = VFSTOPROC(mp)->pmnt_flags;
1208 return (flags & PROCFSMNT_LINUXCOMPAT) && 1210 return (flags & PROCFSMNT_LINUXCOMPAT) &&
1209 (l == NULL || l->l_proc == NULL || procfs_validfile(l, mp)); 1211 (l == NULL || l->l_proc == NULL || procfs_validfile(l, mp));
1210} 1212}
1211 1213
1212struct procfs_root_readdir_ctx { 1214struct procfs_root_readdir_ctx {
1213 struct uio *uiop; 1215 struct uio *uiop;
1214 off_t *cookies; 1216 off_t *cookies;
1215 int ncookies; 1217 int ncookies;
1216 off_t off; 1218 off_t off;
1217 off_t startoff; 1219 off_t startoff;
1218 int error; 1220 int error;
1219}; 1221};
1220 1222
1221static int 1223static int
1222procfs_root_readdir_callback(struct proc *p, void *arg) 1224procfs_root_readdir_callback(struct proc *p, void *arg)
1223{ 1225{
1224 struct procfs_root_readdir_ctx *ctxp = arg; 1226 struct procfs_root_readdir_ctx *ctxp = arg;
1225 struct dirent d; 1227 struct dirent d;
1226 struct uio *uiop; 1228 struct uio *uiop;
1227 int error; 1229 int error;
1228 1230
1229 uiop = ctxp->uiop; 1231 uiop = ctxp->uiop;
1230 if (uiop->uio_resid < UIO_MX) 1232 if (uiop->uio_resid < UIO_MX)
1231 return -1; /* no space */ 1233 return -1; /* no space */
1232 1234
1233 if (ctxp->off < ctxp->startoff) { 1235 if (ctxp->off < ctxp->startoff) {
1234 ctxp->off++; 1236 ctxp->off++;
1235 return 0; 1237 return 0;
1236 } 1238 }
1237 1239
1238 if (kauth_authorize_process(kauth_cred_get(), 1240 if (kauth_authorize_process(kauth_cred_get(),
1239 KAUTH_PROCESS_CANSEE, p, 1241 KAUTH_PROCESS_CANSEE, p,
1240 KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL) != 0) 1242 KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL) != 0)
1241 return 0; 1243 return 0;
1242 1244
1243 memset(&d, 0, UIO_MX); 1245 memset(&d, 0, UIO_MX);
1244 d.d_reclen = UIO_MX; 1246 d.d_reclen = UIO_MX;
1245 d.d_fileno = PROCFS_FILENO(p->p_pid, PFSproc, -1); 1247 d.d_fileno = PROCFS_FILENO(p->p_pid, PFSproc, -1);
1246 d.d_namlen = snprintf(d.d_name, 1248 d.d_namlen = snprintf(d.d_name,
1247 UIO_MX - offsetof(struct dirent, d_name), "%ld", (long)p->p_pid); 1249 UIO_MX - offsetof(struct dirent, d_name), "%ld", (long)p->p_pid);
1248 d.d_type = DT_DIR; 1250 d.d_type = DT_DIR;
1249 1251
1250 mutex_exit(proc_lock); 1252 mutex_exit(proc_lock);
1251 error = uiomove(&d, UIO_MX, uiop); 1253 error = uiomove(&d, UIO_MX, uiop);
1252 mutex_enter(proc_lock); 1254 mutex_enter(proc_lock);
1253 if (error) { 1255 if (error) {
1254 ctxp->error = error; 1256 ctxp->error = error;
1255 return -1; 1257 return -1;
1256 } 1258 }
1257 1259
1258 ctxp->ncookies++; 1260 ctxp->ncookies++;
1259 if (ctxp->cookies) 1261 if (ctxp->cookies)
1260 *(ctxp->cookies)++ = ctxp->off + 1; 1262 *(ctxp->cookies)++ = ctxp->off + 1;
1261 ctxp->off++; 1263 ctxp->off++;
1262 1264
1263 return 0; 1265 return 0;
1264} 1266}
1265 1267
1266/* 1268/*
1267 * readdir returns directory entries from pfsnode (vp). 1269 * readdir returns directory entries from pfsnode (vp).
1268 * 1270 *
1269 * the strategy here with procfs is to generate a single 1271 * the strategy here with procfs is to generate a single
1270 * directory entry at a time (struct dirent) and then 1272 * directory entry at a time (struct dirent) and then
1271 * copy that out to userland using uiomove. a more efficent 1273 * copy that out to userland using uiomove. a more efficent
1272 * though more complex implementation, would try to minimize 1274 * though more complex implementation, would try to minimize
1273 * the number of calls to uiomove(). for procfs, this is 1275 * the number of calls to uiomove(). for procfs, this is
1274 * hardly worth the added code complexity. 1276 * hardly worth the added code complexity.
1275 * 1277 *
1276 * this should just be done through read() 1278 * this should just be done through read()
1277 */ 1279 */
1278int 1280int
1279procfs_readdir(void *v) 1281procfs_readdir(void *v)
1280{ 1282{
1281 struct vop_readdir_args /* { 1283 struct vop_readdir_args /* {
1282 struct vnode *a_vp; 1284 struct vnode *a_vp;
1283 struct uio *a_uio; 1285 struct uio *a_uio;
1284 kauth_cred_t a_cred; 1286 kauth_cred_t a_cred;
1285 int *a_eofflag; 1287 int *a_eofflag;
1286 off_t **a_cookies; 1288 off_t **a_cookies;
1287 int *a_ncookies; 1289 int *a_ncookies;
1288 } */ *ap = v; 1290 } */ *ap = v;
1289 struct uio *uio = ap->a_uio; 1291 struct uio *uio = ap->a_uio;
1290 struct dirent d; 1292 struct dirent d;
1291 struct pfsnode *pfs; 1293 struct pfsnode *pfs;
1292 off_t i; 1294 off_t i;
1293 int error; 1295 int error;
1294 off_t *cookies = NULL; 1296 off_t *cookies = NULL;
1295 int ncookies; 1297 int ncookies;
1296 struct vnode *vp; 1298 struct vnode *vp;
1297 const struct proc_target *pt; 1299 const struct proc_target *pt;
1298 struct procfs_root_readdir_ctx ctx; 1300 struct procfs_root_readdir_ctx ctx;
1299 struct lwp *l; 1301 struct lwp *l;
1300 int nfd; 1302 int nfd;
1301 1303
1302 vp = ap->a_vp; 1304 vp = ap->a_vp;
1303 pfs = VTOPFS(vp); 1305 pfs = VTOPFS(vp);
1304 1306
1305 if (uio->uio_resid < UIO_MX) 1307 if (uio->uio_resid < UIO_MX)
1306 return (EINVAL); 1308 return (EINVAL);
1307 if (uio->uio_offset < 0) 1309 if (uio->uio_offset < 0)
1308 return (EINVAL); 1310 return (EINVAL);
1309 1311
1310 error = 0; 1312 error = 0;
1311 i = uio->uio_offset; 1313 i = uio->uio_offset;
1312 memset(&d, 0, UIO_MX); 1314 memset(&d, 0, UIO_MX);
1313 d.d_reclen = UIO_MX; 1315 d.d_reclen = UIO_MX;
1314 ncookies = uio->uio_resid / UIO_MX; 1316 ncookies = uio->uio_resid / UIO_MX;
1315 1317
1316 switch (pfs->pfs_type) { 1318 switch (pfs->pfs_type) {
1317 /* 1319 /*
1318 * this is for the process-specific sub-directories. 1320 * this is for the process-specific sub-directories.
1319 * all that is needed to is copy out all the entries 1321 * all that is needed to is copy out all the entries
1320 * from the procent[] table (top of this file). 1322 * from the procent[] table (top of this file).
1321 */ 1323 */
1322 case PFSproc: { 1324 case PFSproc: {
1323 struct proc *p; 1325 struct proc *p;
1324 1326
1325 if (i >= nproc_targets) 1327 if (i >= nproc_targets)
1326 return 0; 1328 return 0;
1327 1329
1328 if (procfs_proc_lock(pfs->pfs_pid, &p, ESRCH) != 0) 1330 if (procfs_proc_lock(pfs->pfs_pid, &p, ESRCH) != 0)
1329 break; 1331 break;
1330 1332
1331 if (ap->a_ncookies) { 1333 if (ap->a_ncookies) {
1332 ncookies = min(ncookies, (nproc_targets - i)); 1334 ncookies = min(ncookies, (nproc_targets - i));
1333 cookies = malloc(ncookies * sizeof (off_t), 1335 cookies = malloc(ncookies * sizeof (off_t),
1334 M_TEMP, M_WAITOK); 1336 M_TEMP, M_WAITOK);
1335 *ap->a_cookies = cookies; 1337 *ap->a_cookies = cookies;
1336 } 1338 }
1337 1339
1338 for (pt = &proc_targets[i]; 1340 for (pt = &proc_targets[i];
1339 uio->uio_resid >= UIO_MX && i < nproc_targets; pt++, i++) { 1341 uio->uio_resid >= UIO_MX && i < nproc_targets; pt++, i++) {
1340 if (pt->pt_valid) { 1342 if (pt->pt_valid) {
1341 /* XXXSMP LWP can disappear */ 1343 /* XXXSMP LWP can disappear */
1342 mutex_enter(p->p_lock); 1344 mutex_enter(p->p_lock);
1343 l = LIST_FIRST(&p->p_lwps); 1345 l = LIST_FIRST(&p->p_lwps);
1344 KASSERT(l != NULL); 1346 KASSERT(l != NULL);
1345 mutex_exit(p->p_lock); 1347 mutex_exit(p->p_lock);
1346 if ((*pt->pt_valid)(l, vp->v_mount) == 0) 1348 if ((*pt->pt_valid)(l, vp->v_mount) == 0)
1347 continue; 1349 continue;
1348 } 1350 }
1349 1351
1350 d.d_fileno = PROCFS_FILENO(pfs->pfs_pid, 1352 d.d_fileno = PROCFS_FILENO(pfs->pfs_pid,
1351 pt->pt_pfstype, -1); 1353 pt->pt_pfstype, -1);
1352 d.d_namlen = pt->pt_namlen; 1354 d.d_namlen = pt->pt_namlen;
1353 memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1); 1355 memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1);
1354 d.d_type = pt->pt_type; 1356 d.d_type = pt->pt_type;
1355 1357
1356 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 1358 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1357 break; 1359 break;
1358 if (cookies) 1360 if (cookies)
1359 *cookies++ = i + 1; 1361 *cookies++ = i + 1;
1360 } 1362 }
1361 1363
1362 procfs_proc_unlock(p); 1364 procfs_proc_unlock(p);
1363 break; 1365 break;
1364 } 1366 }
1365 case PFSfd: { 1367 case PFSfd: {
1366 struct proc *p; 1368 struct proc *p;
1367 file_t *fp; 1369 file_t *fp;
1368 int lim, nc = 0; 1370 int lim, nc = 0;
1369 1371
1370 if ((error = procfs_proc_lock(pfs->pfs_pid, &p, ESRCH)) != 0) 1372 if ((error = procfs_proc_lock(pfs->pfs_pid, &p, ESRCH)) != 0)
1371 return error; 1373 return error;
1372 1374
1373 /* XXX Should this be by file as well? */ 1375 /* XXX Should this be by file as well? */
1374 if (kauth_authorize_process(kauth_cred_get(), 1376 if (kauth_authorize_process(kauth_cred_get(),
1375 KAUTH_PROCESS_CANSEE, p, 1377 KAUTH_PROCESS_CANSEE, p,
1376 KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_OPENFILES), NULL, 1378 KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_OPENFILES), NULL,
1377 NULL) != 0) { 1379 NULL) != 0) {
1378 procfs_proc_unlock(p); 1380 procfs_proc_unlock(p);
1379 return ESRCH; 1381 return ESRCH;
1380 } 1382 }
1381 1383
1382 nfd = p->p_fd->fd_dt->dt_nfiles; 1384 nfd = p->p_fd->fd_dt->dt_nfiles;
1383 1385
1384 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles); 1386 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
1385 if (i >= lim) { 1387 if (i >= lim) {
1386 procfs_proc_unlock(p); 1388 procfs_proc_unlock(p);
1387 return 0; 1389 return 0;
1388 } 1390 }
1389 1391
1390 if (ap->a_ncookies) { 1392 if (ap->a_ncookies) {
1391 ncookies = min(ncookies, (nfd + 2 - i)); 1393 ncookies = min(ncookies, (nfd + 2 - i));
1392 cookies = malloc(ncookies * sizeof (off_t), 1394 cookies = malloc(ncookies * sizeof (off_t),
1393 M_TEMP, M_WAITOK); 1395 M_TEMP, M_WAITOK);
1394 *ap->a_cookies = cookies; 1396 *ap->a_cookies = cookies;
1395 } 1397 }
1396 1398
1397 for (; i < 2 && uio->uio_resid >= UIO_MX; i++) { 1399 for (; i < 2 && uio->uio_resid >= UIO_MX; i++) {
1398 pt = &proc_targets[i]; 1400 pt = &proc_targets[i];
1399 d.d_namlen = pt->pt_namlen; 1401 d.d_namlen = pt->pt_namlen;
1400 d.d_fileno = PROCFS_FILENO(pfs->pfs_pid, 1402 d.d_fileno = PROCFS_FILENO(pfs->pfs_pid,
1401 pt->pt_pfstype, -1); 1403 pt->pt_pfstype, -1);
1402 (void)memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1); 1404 (void)memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1);
1403 d.d_type = pt->pt_type; 1405 d.d_type = pt->pt_type;
1404 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 1406 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1405 break; 1407 break;
1406 if (cookies) 1408 if (cookies)
1407 *cookies++ = i + 1; 1409 *cookies++ = i + 1;
1408 nc++; 1410 nc++;
1409 } 1411 }
1410 if (error) { 1412 if (error) {
1411 ncookies = nc; 1413 ncookies = nc;
1412 break; 1414 break;
1413 } 1415 }
1414 for (; uio->uio_resid >= UIO_MX && i < nfd; i++) { 1416 for (; uio->uio_resid >= UIO_MX && i < nfd; i++) {
1415 /* check the descriptor exists */ 1417 /* check the descriptor exists */
1416 if ((fp = fd_getfile2(p, i - 2)) == NULL) 1418 if ((fp = fd_getfile2(p, i - 2)) == NULL)
1417 continue; 1419 continue;
1418 closef(fp); 1420 closef(fp);
1419 1421
1420 d.d_fileno = PROCFS_FILENO(pfs->pfs_pid, PFSfd, i - 2); 1422 d.d_fileno = PROCFS_FILENO(pfs->pfs_pid, PFSfd, i - 2);
1421 d.d_namlen = snprintf(d.d_name, sizeof(d.d_name), 1423 d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
1422 "%lld", (long long)(i - 2)); 1424 "%lld", (long long)(i - 2));
1423 d.d_type = VREG; 1425 d.d_type = VREG;
1424 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 1426 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1425 break; 1427 break;
1426 if (cookies) 1428 if (cookies)
1427 *cookies++ = i + 1; 1429 *cookies++ = i + 1;
1428 nc++; 1430 nc++;
1429 } 1431 }
1430 ncookies = nc; 1432 ncookies = nc;
1431 procfs_proc_unlock(p); 1433 procfs_proc_unlock(p);
1432 break; 1434 break;
1433 } 1435 }
1434 case PFStask: { 1436 case PFStask: {
1435 struct proc *p; 1437 struct proc *p;
1436 int nc = 0; 1438 int nc = 0;
1437 1439
1438 if ((error = procfs_proc_lock(pfs->pfs_pid, &p, ESRCH)) != 0) 1440 if ((error = procfs_proc_lock(pfs->pfs_pid, &p, ESRCH)) != 0)
1439 return error; 1441 return error;
1440 1442
1441 nfd = 3; /* ., .., pid */ 1443 nfd = 3; /* ., .., pid */
1442 1444
1443 if (ap->a_ncookies) { 1445 if (ap->a_ncookies) {
1444 ncookies = min(ncookies, (nfd + 2 - i)); 1446 ncookies = min(ncookies, (nfd + 2 - i));
1445 cookies = malloc(ncookies * sizeof (off_t), 1447 cookies = malloc(ncookies * sizeof (off_t),
1446 M_TEMP, M_WAITOK); 1448 M_TEMP, M_WAITOK);
1447 *ap->a_cookies = cookies; 1449 *ap->a_cookies = cookies;
1448 } 1450 }
1449 1451
1450 for (; i < 2 && uio->uio_resid >= UIO_MX; i++) { 1452 for (; i < 2 && uio->uio_resid >= UIO_MX; i++) {
1451 pt = &proc_targets[i]; 1453 pt = &proc_targets[i];
1452 d.d_namlen = pt->pt_namlen; 1454 d.d_namlen = pt->pt_namlen;
1453 d.d_fileno = PROCFS_FILENO(pfs->pfs_pid, 1455 d.d_fileno = PROCFS_FILENO(pfs->pfs_pid,
1454 pt->pt_pfstype, -1); 1456 pt->pt_pfstype, -1);
1455 (void)memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1); 1457 (void)memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1);
1456 d.d_type = pt->pt_type; 1458 d.d_type = pt->pt_type;
1457 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 1459 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1458 break; 1460 break;
1459 if (cookies) 1461 if (cookies)
1460 *cookies++ = i + 1; 1462 *cookies++ = i + 1;
1461 nc++; 1463 nc++;
1462 } 1464 }
1463 if (error) { 1465 if (error) {
1464 ncookies = nc; 1466 ncookies = nc;
1465 break; 1467 break;
1466 } 1468 }
1467 for (; uio->uio_resid >= UIO_MX && i < nfd; i++) { 1469 for (; uio->uio_resid >= UIO_MX && i < nfd; i++) {
1468 /* check the descriptor exists */ 1470 /* check the descriptor exists */
1469 d.d_fileno = PROCFS_FILENO(pfs->pfs_pid, PFStask, 1471 d.d_fileno = PROCFS_FILENO(pfs->pfs_pid, PFStask,
1470 i - 2); 1472 i - 2);
1471 d.d_namlen = snprintf(d.d_name, sizeof(d.d_name), 1473 d.d_namlen = snprintf(d.d_name, sizeof(d.d_name),
1472 "%ld", (long)pfs->pfs_pid); 1474 "%ld", (long)pfs->pfs_pid);
1473 d.d_type = DT_LNK; 1475 d.d_type = DT_LNK;
1474 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 1476 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1475 break; 1477 break;
1476 if (cookies) 1478 if (cookies)
1477 *cookies++ = i + 1; 1479 *cookies++ = i + 1;
1478 nc++; 1480 nc++;
1479 } 1481 }
1480 ncookies = nc; 1482 ncookies = nc;
1481 procfs_proc_unlock(p); 1483 procfs_proc_unlock(p);
1482 break; 1484 break;
1483 } 1485 }
1484 1486
1485 /* 1487 /*
1486 * this is for the root of the procfs filesystem 1488 * this is for the root of the procfs filesystem
1487 * what is needed are special entries for "curproc" 1489 * what is needed are special entries for "curproc"
1488 * and "self" followed by an entry for each process 1490 * and "self" followed by an entry for each process
1489 * on allproc. 1491 * on allproc.
1490 */ 1492 */
1491 1493
1492 case PFSroot: { 1494 case PFSroot: {
1493 int nc = 0; 1495 int nc = 0;
1494 1496
1495 if (ap->a_ncookies) { 1497 if (ap->a_ncookies) {
1496 /* 1498 /*
1497 * XXX Potentially allocating too much space here, 1499 * XXX Potentially allocating too much space here,
1498 * but I'm lazy. This loop needs some work. 1500 * but I'm lazy. This loop needs some work.
1499 */ 1501 */
1500 cookies = malloc(ncookies * sizeof (off_t), 1502 cookies = malloc(ncookies * sizeof (off_t),
1501 M_TEMP, M_WAITOK); 1503 M_TEMP, M_WAITOK);
1502 *ap->a_cookies = cookies; 1504 *ap->a_cookies = cookies;
1503 } 1505 }
1504 error = 0; 1506 error = 0;
1505 /* 0 ... 3 are static entries. */ 1507 /* 0 ... 3 are static entries. */
1506 for (; i <= 3 && uio->uio_resid >= UIO_MX; i++) { 1508 for (; i <= 3 && uio->uio_resid >= UIO_MX; i++) {
1507 switch (i) { 1509 switch (i) {
1508 case 0: /* `.' */ 1510 case 0: /* `.' */
1509 case 1: /* `..' */ 1511 case 1: /* `..' */
1510 d.d_fileno = PROCFS_FILENO(0, PFSroot, -1); 1512 d.d_fileno = PROCFS_FILENO(0, PFSroot, -1);
1511 d.d_namlen = i + 1; 1513 d.d_namlen = i + 1;
1512 memcpy(d.d_name, "..", d.d_namlen); 1514 memcpy(d.d_name, "..", d.d_namlen);
1513 d.d_name[i + 1] = '\0'; 1515 d.d_name[i + 1] = '\0';
1514 d.d_type = DT_DIR; 1516 d.d_type = DT_DIR;
1515 break; 1517 break;
1516 1518
1517 case 2: 1519 case 2:
1518 d.d_fileno = PROCFS_FILENO(0, PFScurproc, -1); 1520 d.d_fileno = PROCFS_FILENO(0, PFScurproc, -1);
1519 d.d_namlen = sizeof("curproc") - 1; 1521 d.d_namlen = sizeof("curproc") - 1;
1520 memcpy(d.d_name, "curproc", sizeof("curproc")); 1522 memcpy(d.d_name, "curproc", sizeof("curproc"));
1521 d.d_type = DT_LNK; 1523 d.d_type = DT_LNK;
1522 break; 1524 break;
1523 1525
1524 case 3: 1526 case 3:
1525 d.d_fileno = PROCFS_FILENO(0, PFSself, -1); 1527 d.d_fileno = PROCFS_FILENO(0, PFSself, -1);
1526 d.d_namlen = sizeof("self") - 1; 1528 d.d_namlen = sizeof("self") - 1;
1527 memcpy(d.d_name, "self", sizeof("self")); 1529 memcpy(d.d_name, "self", sizeof("self"));
1528 d.d_type = DT_LNK; 1530 d.d_type = DT_LNK;
1529 break; 1531 break;
1530 } 1532 }
1531 1533
1532 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 1534 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1533 break; 1535 break;
1534 nc++; 1536 nc++;
1535 if (cookies) 1537 if (cookies)
1536 *cookies++ = i + 1; 1538 *cookies++ = i + 1;
1537 } 1539 }
1538 /* 4 ... are process entries. */ 1540 /* 4 ... are process entries. */
1539 ctx.uiop = uio; 1541 ctx.uiop = uio;
1540 ctx.error = 0; 1542 ctx.error = 0;
1541 ctx.off = 4; 1543 ctx.off = 4;
1542 ctx.startoff = i; 1544 ctx.startoff = i;
1543 ctx.cookies = cookies; 1545 ctx.cookies = cookies;
1544 ctx.ncookies = nc; 1546 ctx.ncookies = nc;
1545 proclist_foreach_call(&allproc, 1547 proclist_foreach_call(&allproc,
1546 procfs_root_readdir_callback, &ctx); 1548 procfs_root_readdir_callback, &ctx);
1547 cookies = ctx.cookies; 1549 cookies = ctx.cookies;
1548 nc = ctx.ncookies; 1550 nc = ctx.ncookies;
1549 error = ctx.error; 1551 error = ctx.error;
1550 if (error) 1552 if (error)
1551 break; 1553 break;
1552 1554
1553 /* misc entries. */ 1555 /* misc entries. */
1554 if (i < ctx.off) 1556 if (i < ctx.off)
1555 i = ctx.off; 1557 i = ctx.off;
1556 if (i >= ctx.off + nproc_root_targets) 1558 if (i >= ctx.off + nproc_root_targets)
1557 break; 1559 break;
1558 for (pt = &proc_root_targets[i - ctx.off]; 1560 for (pt = &proc_root_targets[i - ctx.off];
1559 uio->uio_resid >= UIO_MX && 1561 uio->uio_resid >= UIO_MX &&
1560 pt < &proc_root_targets[nproc_root_targets]; 1562 pt < &proc_root_targets[nproc_root_targets];
1561 pt++, i++) { 1563 pt++, i++) {
1562 if (pt->pt_valid && 1564 if (pt->pt_valid &&
1563 (*pt->pt_valid)(NULL, vp->v_mount) == 0) 1565 (*pt->pt_valid)(NULL, vp->v_mount) == 0)
1564 continue; 1566 continue;
1565 d.d_fileno = PROCFS_FILENO(0, pt->pt_pfstype, -1); 1567 d.d_fileno = PROCFS_FILENO(0, pt->pt_pfstype, -1);
1566 d.d_namlen = pt->pt_namlen; 1568 d.d_namlen = pt->pt_namlen;
1567 memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1); 1569 memcpy(d.d_name, pt->pt_name, pt->pt_namlen + 1);
1568 d.d_type = pt->pt_type; 1570 d.d_type = pt->pt_type;
1569 1571
1570 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 1572 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1571 break; 1573 break;
1572 nc++; 1574 nc++;
1573 if (cookies) 1575 if (cookies)
1574 *cookies++ = i + 1; 1576 *cookies++ = i + 1;
1575 } 1577 }
1576 1578
1577 ncookies = nc; 1579 ncookies = nc;
1578 break; 1580 break;
1579 } 1581 }
1580 1582
1581 default: 1583 default:
1582 error = ENOTDIR; 1584 error = ENOTDIR;
1583 break; 1585 break;
1584 } 1586 }
1585 1587
1586 if (ap->a_ncookies) { 1588 if (ap->a_ncookies) {
1587 if (error) { 1589 if (error) {
1588 if (cookies) 1590 if (cookies)
1589 free(*ap->a_cookies, M_TEMP); 1591 free(*ap->a_cookies, M_TEMP);
1590 *ap->a_ncookies = 0; 1592 *ap->a_ncookies = 0;
1591 *ap->a_cookies = NULL; 1593 *ap->a_cookies = NULL;
1592 } else 1594 } else
1593 *ap->a_ncookies = ncookies; 1595 *ap->a_ncookies = ncookies;
1594 } 1596 }
1595 uio->uio_offset = i; 1597 uio->uio_offset = i;
1596 return (error); 1598 return (error);
1597} 1599}
1598 1600
1599/* 1601/*
1600 * readlink reads the link of `curproc' and others 1602 * readlink reads the link of `curproc' and others
1601 */ 1603 */
1602int 1604int
1603procfs_readlink(void *v) 1605procfs_readlink(void *v)
1604{ 1606{
1605 struct vop_readlink_args *ap = v; 1607 struct vop_readlink_args *ap = v;
1606 char bf[16]; /* should be enough */ 1608 char bf[16]; /* should be enough */
1607 char *bp = bf; 1609 char *bp = bf;
1608 char *path = NULL; 1610 char *path = NULL;
1609 int len = 0; 1611 int len = 0;
1610 int error = 0; 1612 int error = 0;
1611 struct pfsnode *pfs = VTOPFS(ap->a_vp); 1613 struct pfsnode *pfs = VTOPFS(ap->a_vp);
1612 struct proc *pown; 1614 struct proc *pown;
1613 1615
1614 if (pfs->pfs_fileno == PROCFS_FILENO(0, PFScurproc, -1)) 1616 if (pfs->pfs_fileno == PROCFS_FILENO(0, PFScurproc, -1))
1615 len = snprintf(bf, sizeof(bf), "%ld", (long)curproc->p_pid); 1617 len = snprintf(bf, sizeof(bf), "%ld", (long)curproc->p_pid);
1616 else if (pfs->pfs_fileno == PROCFS_FILENO(0, PFSself, -1)) 1618 else if (pfs->pfs_fileno == PROCFS_FILENO(0, PFSself, -1))
1617 len = snprintf(bf, sizeof(bf), "%s", "curproc"); 1619 len = snprintf(bf, sizeof(bf), "%s", "curproc");
1618 else if (pfs->pfs_fileno == PROCFS_FILENO(pfs->pfs_pid, PFStask, 0)) 1620 else if (pfs->pfs_fileno == PROCFS_FILENO(pfs->pfs_pid, PFStask, 0))
1619 len = snprintf(bf, sizeof(bf), ".."); 1621 len = snprintf(bf, sizeof(bf), "..");
1620 else if (pfs->pfs_fileno == PROCFS_FILENO(pfs->pfs_pid, PFScwd, -1) || 1622 else if (pfs->pfs_fileno == PROCFS_FILENO(pfs->pfs_pid, PFScwd, -1) ||
1621 pfs->pfs_fileno == PROCFS_FILENO(pfs->pfs_pid, PFSchroot, -1) || 1623 pfs->pfs_fileno == PROCFS_FILENO(pfs->pfs_pid, PFSchroot, -1) ||
1622 pfs->pfs_fileno == PROCFS_FILENO(pfs->pfs_pid, PFSexe, -1)) { 1624 pfs->pfs_fileno == PROCFS_FILENO(pfs->pfs_pid, PFSexe, -1)) {
1623 if ((error = procfs_proc_lock(pfs->pfs_pid, &pown, ESRCH)) != 0) 1625 if ((error = procfs_proc_lock(pfs->pfs_pid, &pown, ESRCH)) != 0)
1624 return error; 1626 return error;
1625 path = malloc(MAXPATHLEN + 4, M_TEMP, M_WAITOK|M_CANFAIL); 1627 path = malloc(MAXPATHLEN + 4, M_TEMP, M_WAITOK|M_CANFAIL);
1626 if (path == NULL) { 1628 if (path == NULL) {
1627 procfs_proc_unlock(pown); 1629 procfs_proc_unlock(pown);
1628 return (ENOMEM); 1630 return (ENOMEM);
1629 } 1631 }
1630 bp = path + MAXPATHLEN; 1632 bp = path + MAXPATHLEN;
1631 *--bp = '\0'; 1633 *--bp = '\0';
1632 procfs_dir(PROCFS_TYPE(pfs->pfs_fileno), curlwp, pown, 1634 procfs_dir(PROCFS_TYPE(pfs->pfs_fileno), curlwp, pown,
1633 &bp, path, MAXPATHLEN); 1635 &bp, path, MAXPATHLEN);
1634 procfs_proc_unlock(pown); 1636 procfs_proc_unlock(pown);
1635 len = strlen(bp); 1637 len = strlen(bp);
1636 } else { 1638 } else {
1637 file_t *fp; 1639 file_t *fp;
1638 struct vnode *vxp, *vp; 1640 struct vnode *vxp, *vp;
1639 1641
1640 if ((error = procfs_proc_lock(pfs->pfs_pid, &pown, ESRCH)) != 0) 1642 if ((error = procfs_proc_lock(pfs->pfs_pid, &pown, ESRCH)) != 0)
1641 return error; 1643 return error;
1642 1644
1643 fp = fd_getfile2(pown, pfs->pfs_fd); 1645 fp = fd_getfile2(pown, pfs->pfs_fd);
1644 if (fp == NULL) { 1646 if (fp == NULL) {
1645 procfs_proc_unlock(pown); 1647 procfs_proc_unlock(pown);
1646 return EBADF; 1648 return EBADF;
1647 } 1649 }
1648 1650
1649 switch (fp->f_type) { 1651 switch (fp->f_type) {
1650 case DTYPE_VNODE: 1652 case DTYPE_VNODE:
1651 vxp = (struct vnode *)fp->f_data; 1653 vxp = (struct vnode *)fp->f_data;
1652 if (vxp->v_type != VDIR) { 1654 if (vxp->v_type != VDIR) {
1653 error = EINVAL; 1655 error = EINVAL;
1654 break; 1656 break;
1655 } 1657 }
1656 if ((path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK)) 1658 if ((path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK))
1657 == NULL) { 1659 == NULL) {
1658 error = ENOMEM; 1660 error = ENOMEM;
1659 break; 1661 break;
1660 } 1662 }
1661 bp = path + MAXPATHLEN; 1663 bp = path + MAXPATHLEN;
1662 *--bp = '\0'; 1664 *--bp = '\0';
1663 1665
1664 /* 1666 /*
1665 * XXX: kludge to avoid locking against ourselves 1667 * XXX: kludge to avoid locking against ourselves
1666 * in getcwd() 1668 * in getcwd()
1667 */ 1669 */
1668 if (vxp->v_tag == VT_PROCFS) { 1670 if (vxp->v_tag == VT_PROCFS) {
1669 *--bp = '/'; 1671 *--bp = '/';
1670 } else { 1672 } else {
1671 rw_enter(&curproc->p_cwdi->cwdi_lock, 1673 rw_enter(&curproc->p_cwdi->cwdi_lock,
1672 RW_READER); 1674 RW_READER);
1673 vp = curproc->p_cwdi->cwdi_rdir; 1675 vp = curproc->p_cwdi->cwdi_rdir;
1674 if (vp == NULL) 1676 if (vp == NULL)
1675 vp = rootvnode; 1677 vp = rootvnode;
1676 error = getcwd_common(vxp, vp, &bp, path, 1678 error = getcwd_common(vxp, vp, &bp, path,
1677 MAXPATHLEN / 2, 0, curlwp); 1679 MAXPATHLEN / 2, 0, curlwp);
1678 rw_exit(&curproc->p_cwdi->cwdi_lock); 1680 rw_exit(&curproc->p_cwdi->cwdi_lock);
1679 } 1681 }
1680 if (error) 1682 if (error)
1681 break; 1683 break;
1682 len = strlen(bp); 1684 len = strlen(bp);
1683 break; 1685 break;
1684 1686
1685 case DTYPE_MISC: 1687 case DTYPE_MISC:
1686 len = snprintf(bf, sizeof(bf), "%s", "[misc]"); 1688 len = snprintf(bf, sizeof(bf), "%s", "[misc]");
1687 break; 1689 break;
1688 1690
1689 case DTYPE_KQUEUE: 1691 case DTYPE_KQUEUE:
1690 len = snprintf(bf, sizeof(bf), "%s", "[kqueue]"); 1692 len = snprintf(bf, sizeof(bf), "%s", "[kqueue]");
1691 break; 1693 break;
1692 1694
1693 case DTYPE_SEM: 1695 case DTYPE_SEM:
1694 len = snprintf(bf, sizeof(bf), "%s", "[ksem]"); 1696 len = snprintf(bf, sizeof(bf), "%s", "[ksem]");
1695 break; 1697 break;
1696 1698
1697 default: 1699 default:
1698 error = EINVAL; 1700 error = EINVAL;
1699 break; 1701 break;
1700 }  1702 }
1701 closef(fp); 1703 closef(fp);
1702 procfs_proc_unlock(pown); 1704 procfs_proc_unlock(pown);
1703 } 1705 }
1704 1706
1705 if (error == 0) 1707 if (error == 0)
1706 error = uiomove(bp, len, ap->a_uio); 1708 error = uiomove(bp, len, ap->a_uio);
1707 if (path) 1709 if (path)
1708 free(path, M_TEMP); 1710 free(path, M_TEMP);
1709 return error; 1711 return error;
1710} 1712}
1711 1713
 1714int
 1715procfs_getpages(void *v)
 1716{
 1717 struct vop_getpages_args /* {
 1718 struct vnode *a_vp;
 1719 voff_t a_offset;
 1720 struct vm_page **a_m;
 1721 int *a_count;
 1722 int a_centeridx;
 1723 vm_prot_t a_access_type;
 1724 int a_advice;
 1725 int a_flags;
 1726 } */ *ap = v;
 1727
 1728 if ((ap->a_flags & PGO_LOCKED) == 0)
 1729 mutex_exit(ap->a_vp->v_interlock);
 1730
 1731 return (EFAULT);
 1732}
 1733
1712/* 1734/*
1713 * convert decimal ascii to int 1735 * convert decimal ascii to int
1714 */ 1736 */
1715static int 1737static int
1716atoi(const char *b, size_t len) 1738atoi(const char *b, size_t len)
1717{ 1739{
1718 int p = 0; 1740 int p = 0;
1719 1741
1720 while (len--) { 1742 while (len--) {
1721 char c = *b++; 1743 char c = *b++;
1722 if (c < '0' || c > '9') 1744 if (c < '0' || c > '9')
1723 return -1; 1745 return -1;
1724 p = 10 * p + (c - '0'); 1746 p = 10 * p + (c - '0');
1725 } 1747 }
1726 1748
1727 return p; 1749 return p;
1728} 1750}