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