Thu Aug 29 06:43:13 2019 UTC ()
Add missing operation VOP_GETPAGES() returning EFAULT.

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

Observed by maxv@


(hannken)
diff -r1.160 -r1.161 src/sys/miscfs/kernfs/kernfs_vnops.c
diff -r1.206 -r1.207 src/sys/miscfs/procfs/procfs_vnops.c

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

--- src/sys/miscfs/kernfs/kernfs_vnops.c 2018/09/03 16:29:35 1.160
+++ src/sys/miscfs/kernfs/kernfs_vnops.c 2019/08/29 06:43:13 1.161
@@ -1,1171 +1,1193 @@ @@ -1,1171 +1,1193 @@
1/* $NetBSD: kernfs_vnops.c,v 1.160 2018/09/03 16:29:35 riastradh Exp $ */ 1/* $NetBSD: kernfs_vnops.c,v 1.161 2019/08/29 06:43:13 hannken 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.160 2018/09/03 16:29:35 riastradh Exp $"); 42__KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.161 2019/08/29 06:43:13 hannken 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 (!logenabled(msgbufp)) { 386 if (!logenabled(msgbufp)) {
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 = uimin(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off); 407 len = uimin(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 = uimin(uio->uio_resid, KSTRING-1); 782 xlen = uimin(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 = uimin(ncookies, (nkern_targets - i)); 912 ncookies = uimin(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 (!logenabled(msgbufp)) { 947 if (!logenabled(msgbufp)) {
946 continue; 948 continue;
947 } 949 }
948 } 950 }
949 d.d_namlen = kt->kt_namlen; 951 d.d_namlen = kt->kt_namlen;
950 if ((error = kernfs_setdirentfileno(&d, i, kfs, 952 if ((error = kernfs_setdirentfileno(&d, i, kfs,
951 &kern_targets[0], kt, ap)) != 0) 953 &kern_targets[0], kt, ap)) != 0)
952 break; 954 break;
953 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); 955 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
954 d.d_type = kt->kt_type; 956 d.d_type = kt->kt_type;
955 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 957 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
956 break; 958 break;
957 if (cookies) 959 if (cookies)
958 *cookies++ = i + 1; 960 *cookies++ = i + 1;
959 n++; 961 n++;
960 } 962 }
961 ncookies = n; 963 ncookies = n;
962 break; 964 break;
963 965
964 case KFSroot: 966 case KFSroot:
965 if (i >= 2) 967 if (i >= 2)
966 return 0; 968 return 0;
967 969
968 if (ap->a_ncookies) { 970 if (ap->a_ncookies) {
969 ncookies = uimin(ncookies, (2 - i)); 971 ncookies = uimin(ncookies, (2 - i));
970 cookies = malloc(ncookies * sizeof(off_t), M_TEMP, 972 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
971 M_WAITOK); 973 M_WAITOK);
972 *ap->a_cookies = cookies; 974 *ap->a_cookies = cookies;
973 } 975 }
974 976
975 n = 0; 977 n = 0;
976 for (; i < 2 && uio->uio_resid >= UIO_MX; i++) { 978 for (; i < 2 && uio->uio_resid >= UIO_MX; i++) {
977 kt = &kern_targets[i]; 979 kt = &kern_targets[i];
978 d.d_namlen = kt->kt_namlen; 980 d.d_namlen = kt->kt_namlen;
979 d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0); 981 d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0);
980 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); 982 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
981 d.d_type = kt->kt_type; 983 d.d_type = kt->kt_type;
982 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 984 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
983 break; 985 break;
984 if (cookies) 986 if (cookies)
985 *cookies++ = i + 1; 987 *cookies++ = i + 1;
986 n++; 988 n++;
987 } 989 }
988 ncookies = n; 990 ncookies = n;
989 break; 991 break;
990 992
991 case KFSsubdir: 993 case KFSsubdir:
992 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data; 994 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data;
993 if (i >= ks->ks_nentries) 995 if (i >= ks->ks_nentries)
994 return (0); 996 return (0);
995 997
996 if (ap->a_ncookies) { 998 if (ap->a_ncookies) {
997 ncookies = uimin(ncookies, (ks->ks_nentries - i)); 999 ncookies = uimin(ncookies, (ks->ks_nentries - i));
998 cookies = malloc(ncookies * sizeof(off_t), M_TEMP, 1000 cookies = malloc(ncookies * sizeof(off_t), M_TEMP,
999 M_WAITOK); 1001 M_WAITOK);
1000 *ap->a_cookies = cookies; 1002 *ap->a_cookies = cookies;
1001 } 1003 }
1002 1004
1003 dkt = SIMPLEQ_FIRST(&ks->ks_entries); 1005 dkt = SIMPLEQ_FIRST(&ks->ks_entries);
1004 for (j = 0; j < i && dkt != NULL; j++) 1006 for (j = 0; j < i && dkt != NULL; j++)
1005 dkt = SIMPLEQ_NEXT(dkt, dkt_queue); 1007 dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1006 n = 0; 1008 n = 0;
1007 for (; i < ks->ks_nentries && uio->uio_resid >= UIO_MX; i++) { 1009 for (; i < ks->ks_nentries && uio->uio_resid >= UIO_MX; i++) {
1008 if (i < 2) 1010 if (i < 2)
1009 kt = &subdir_targets[i]; 1011 kt = &subdir_targets[i];
1010 else { 1012 else {
1011 /* check if ks_nentries lied to us */ 1013 /* check if ks_nentries lied to us */
1012 if (dkt == NULL) 1014 if (dkt == NULL)
1013 break; 1015 break;
1014 kt = &dkt->dkt_kt; 1016 kt = &dkt->dkt_kt;
1015 dkt = SIMPLEQ_NEXT(dkt, dkt_queue); 1017 dkt = SIMPLEQ_NEXT(dkt, dkt_queue);
1016 } 1018 }
1017 if (kt->kt_tag == KFSdevice) { 1019 if (kt->kt_tag == KFSdevice) {
1018 dev_t *dp = kt->kt_data; 1020 dev_t *dp = kt->kt_data;
1019 struct vnode *fvp; 1021 struct vnode *fvp;
1020 1022
1021 if (*dp == NODEV || 1023 if (*dp == NODEV ||
1022 !vfinddev(*dp, kt->kt_vtype, &fvp)) 1024 !vfinddev(*dp, kt->kt_vtype, &fvp))
1023 continue; 1025 continue;
1024 vrele(fvp); 1026 vrele(fvp);
1025 } 1027 }
1026 d.d_namlen = kt->kt_namlen; 1028 d.d_namlen = kt->kt_namlen;
1027 if ((error = kernfs_setdirentfileno(&d, i, kfs, 1029 if ((error = kernfs_setdirentfileno(&d, i, kfs,
1028 ks->ks_parent, kt, ap)) != 0) 1030 ks->ks_parent, kt, ap)) != 0)
1029 break; 1031 break;
1030 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); 1032 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1);
1031 d.d_type = kt->kt_type; 1033 d.d_type = kt->kt_type;
1032 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 1034 if ((error = uiomove(&d, UIO_MX, uio)) != 0)
1033 break; 1035 break;
1034 if (cookies) 1036 if (cookies)
1035 *cookies++ = i + 1; 1037 *cookies++ = i + 1;
1036 n++; 1038 n++;
1037 } 1039 }
1038 ncookies = n; 1040 ncookies = n;
1039 break; 1041 break;
1040 1042
1041 default: 1043 default:
1042 error = ENOTDIR; 1044 error = ENOTDIR;
1043 break; 1045 break;
1044 } 1046 }
1045 1047
1046 if (ap->a_ncookies) { 1048 if (ap->a_ncookies) {
1047 if (error) { 1049 if (error) {
1048 if (cookies) 1050 if (cookies)
1049 free(*ap->a_cookies, M_TEMP); 1051 free(*ap->a_cookies, M_TEMP);
1050 *ap->a_ncookies = 0; 1052 *ap->a_ncookies = 0;
1051 *ap->a_cookies = NULL; 1053 *ap->a_cookies = NULL;
1052 } else 1054 } else
1053 *ap->a_ncookies = ncookies; 1055 *ap->a_ncookies = ncookies;
1054 } 1056 }
1055 1057
1056 uio->uio_offset = i; 1058 uio->uio_offset = i;
1057 return (error); 1059 return (error);
1058} 1060}
1059 1061
1060int 1062int
1061kernfs_inactive(void *v) 1063kernfs_inactive(void *v)
1062{ 1064{
1063 struct vop_inactive_v2_args /* { 1065 struct vop_inactive_v2_args /* {
1064 struct vnode *a_vp; 1066 struct vnode *a_vp;
1065 bool *a_recycle; 1067 bool *a_recycle;
1066 } */ *ap = v; 1068 } */ *ap = v;
1067 1069
1068 *ap->a_recycle = false; 1070 *ap->a_recycle = false;
1069 1071
1070 return (0); 1072 return (0);
1071} 1073}
1072 1074
1073int 1075int
1074kernfs_reclaim(void *v) 1076kernfs_reclaim(void *v)
1075{ 1077{
1076 struct vop_reclaim_v2_args /* { 1078 struct vop_reclaim_v2_args /* {
1077 struct vnode *a_vp; 1079 struct vnode *a_vp;
1078 } */ *ap = v; 1080 } */ *ap = v;
1079 struct vnode *vp = ap->a_vp; 1081 struct vnode *vp = ap->a_vp;
1080 struct kernfs_node *kfs = VTOKERN(vp); 1082 struct kernfs_node *kfs = VTOKERN(vp);
1081 1083
1082 VOP_UNLOCK(vp); 1084 VOP_UNLOCK(vp);
1083 1085
1084 vp->v_data = NULL; 1086 vp->v_data = NULL;
1085 mutex_enter(&kfs_lock); 1087 mutex_enter(&kfs_lock);
1086 TAILQ_REMOVE(&VFSTOKERNFS(vp->v_mount)->nodelist, kfs, kfs_list); 1088 TAILQ_REMOVE(&VFSTOKERNFS(vp->v_mount)->nodelist, kfs, kfs_list);
1087 mutex_exit(&kfs_lock); 1089 mutex_exit(&kfs_lock);
1088 kmem_free(kfs, sizeof(struct kernfs_node)); 1090 kmem_free(kfs, sizeof(struct kernfs_node));
1089 1091
1090 return 0; 1092 return 0;
1091} 1093}
1092 1094
1093/* 1095/*
1094 * Return POSIX pathconf information applicable to special devices. 1096 * Return POSIX pathconf information applicable to special devices.
1095 */ 1097 */
1096int 1098int
1097kernfs_pathconf(void *v) 1099kernfs_pathconf(void *v)
1098{ 1100{
1099 struct vop_pathconf_args /* { 1101 struct vop_pathconf_args /* {
1100 struct vnode *a_vp; 1102 struct vnode *a_vp;
1101 int a_name; 1103 int a_name;
1102 register_t *a_retval; 1104 register_t *a_retval;
1103 } */ *ap = v; 1105 } */ *ap = v;
1104 1106
1105 switch (ap->a_name) { 1107 switch (ap->a_name) {
1106 case _PC_LINK_MAX: 1108 case _PC_LINK_MAX:
1107 *ap->a_retval = LINK_MAX; 1109 *ap->a_retval = LINK_MAX;
1108 return (0); 1110 return (0);
1109 case _PC_MAX_CANON: 1111 case _PC_MAX_CANON:
1110 *ap->a_retval = MAX_CANON; 1112 *ap->a_retval = MAX_CANON;
1111 return (0); 1113 return (0);
1112 case _PC_MAX_INPUT: 1114 case _PC_MAX_INPUT:
1113 *ap->a_retval = MAX_INPUT; 1115 *ap->a_retval = MAX_INPUT;
1114 return (0); 1116 return (0);
1115 case _PC_PIPE_BUF: 1117 case _PC_PIPE_BUF:
1116 *ap->a_retval = PIPE_BUF; 1118 *ap->a_retval = PIPE_BUF;
1117 return (0); 1119 return (0);
1118 case _PC_CHOWN_RESTRICTED: 1120 case _PC_CHOWN_RESTRICTED:
1119 *ap->a_retval = 1; 1121 *ap->a_retval = 1;
1120 return (0); 1122 return (0);
1121 case _PC_VDISABLE: 1123 case _PC_VDISABLE:
1122 *ap->a_retval = _POSIX_VDISABLE; 1124 *ap->a_retval = _POSIX_VDISABLE;
1123 return (0); 1125 return (0);
1124 case _PC_SYNC_IO: 1126 case _PC_SYNC_IO:
1125 *ap->a_retval = 1; 1127 *ap->a_retval = 1;
1126 return (0); 1128 return (0);
1127 default: 1129 default:
1128 return (EINVAL); 1130 return (EINVAL);
1129 } 1131 }
1130 /* NOTREACHED */ 1132 /* NOTREACHED */
1131} 1133}
1132 1134
1133/* 1135/*
1134 * Print out the contents of a /dev/fd vnode. 1136 * Print out the contents of a /dev/fd vnode.
1135 */ 1137 */
1136/* ARGSUSED */ 1138/* ARGSUSED */
1137int 1139int
1138kernfs_print(void *v) 1140kernfs_print(void *v)
1139{ 1141{
1140 1142
1141 printf("tag VT_KERNFS, kernfs vnode\n"); 1143 printf("tag VT_KERNFS, kernfs vnode\n");
1142 return (0); 1144 return (0);
1143} 1145}
1144 1146
1145int 1147int
1146kernfs_link(void *v) 1148kernfs_link(void *v)
1147{ 1149{
1148 struct vop_link_v2_args /* { 1150 struct vop_link_v2_args /* {
1149 struct vnode *a_dvp; 1151 struct vnode *a_dvp;
1150 struct vnode *a_vp; 1152 struct vnode *a_vp;
1151 struct componentname *a_cnp; 1153 struct componentname *a_cnp;
1152 } */ *ap = v; 1154 } */ *ap = v;
1153 1155
1154 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 1156 VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
1155 return (EROFS); 1157 return (EROFS);
1156} 1158}
1157 1159
1158int 1160int
1159kernfs_symlink(void *v) 1161kernfs_symlink(void *v)
1160{ 1162{
1161 struct vop_symlink_v3_args /* { 1163 struct vop_symlink_v3_args /* {
1162 struct vnode *a_dvp; 1164 struct vnode *a_dvp;
1163 struct vnode **a_vpp; 1165 struct vnode **a_vpp;
1164 struct componentname *a_cnp; 1166 struct componentname *a_cnp;
1165 struct vattr *a_vap; 1167 struct vattr *a_vap;
1166 char *a_target; 1168 char *a_target;
1167 } */ *ap = v; 1169 } */ *ap = v;
1168 1170
1169 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 1171 VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
1170 return (EROFS); 1172 return (EROFS);
1171} 1173}
 1174
 1175int
 1176kernfs_getpages(void *v)
 1177{
 1178 struct vop_getpages_args /* {
 1179 struct vnode *a_vp;
 1180 voff_t a_offset;
 1181 struct vm_page **a_m;
 1182 int *a_count;
 1183 int a_centeridx;
 1184 vm_prot_t a_access_type;
 1185 int a_advice;
 1186 int a_flags;
 1187 } */ *ap = v;
 1188
 1189 if ((ap->a_flags & PGO_LOCKED) == 0)
 1190 mutex_exit(ap->a_vp->v_interlock);
 1191
 1192 return (EFAULT);
 1193}

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

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