genfs_vnops.c revision 1.181 1 /* $NetBSD: genfs_vnops.c,v 1.181 2010/06/24 13:03:16 hannken Exp $ */
2
3 /*-
4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /*
30 * Copyright (c) 1982, 1986, 1989, 1993
31 * The Regents of the University of California. All rights reserved.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
44 *
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
56 *
57 */
58
59 #include <sys/cdefs.h>
60 __KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.181 2010/06/24 13:03:16 hannken Exp $");
61
62 #include <sys/param.h>
63 #include <sys/systm.h>
64 #include <sys/proc.h>
65 #include <sys/kernel.h>
66 #include <sys/mount.h>
67 #include <sys/namei.h>
68 #include <sys/vnode.h>
69 #include <sys/fcntl.h>
70 #include <sys/kmem.h>
71 #include <sys/poll.h>
72 #include <sys/mman.h>
73 #include <sys/file.h>
74 #include <sys/kauth.h>
75 #include <sys/stat.h>
76
77 #include <miscfs/genfs/genfs.h>
78 #include <miscfs/genfs/genfs_node.h>
79 #include <miscfs/specfs/specdev.h>
80
81 #include <uvm/uvm.h>
82 #include <uvm/uvm_pager.h>
83
84 static void filt_genfsdetach(struct knote *);
85 static int filt_genfsread(struct knote *, long);
86 static int filt_genfsvnode(struct knote *, long);
87
88 int
89 genfs_poll(void *v)
90 {
91 struct vop_poll_args /* {
92 struct vnode *a_vp;
93 int a_events;
94 struct lwp *a_l;
95 } */ *ap = v;
96
97 return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
98 }
99
100 int
101 genfs_seek(void *v)
102 {
103 struct vop_seek_args /* {
104 struct vnode *a_vp;
105 off_t a_oldoff;
106 off_t a_newoff;
107 kauth_cred_t cred;
108 } */ *ap = v;
109
110 if (ap->a_newoff < 0)
111 return (EINVAL);
112
113 return (0);
114 }
115
116 int
117 genfs_abortop(void *v)
118 {
119 struct vop_abortop_args /* {
120 struct vnode *a_dvp;
121 struct componentname *a_cnp;
122 } */ *ap = v;
123
124 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
125 PNBUF_PUT(ap->a_cnp->cn_pnbuf);
126 return (0);
127 }
128
129 int
130 genfs_fcntl(void *v)
131 {
132 struct vop_fcntl_args /* {
133 struct vnode *a_vp;
134 u_int a_command;
135 void *a_data;
136 int a_fflag;
137 kauth_cred_t a_cred;
138 struct lwp *a_l;
139 } */ *ap = v;
140
141 if (ap->a_command == F_SETFL)
142 return (0);
143 else
144 return (EOPNOTSUPP);
145 }
146
147 /*ARGSUSED*/
148 int
149 genfs_badop(void *v)
150 {
151
152 panic("genfs: bad op");
153 }
154
155 /*ARGSUSED*/
156 int
157 genfs_nullop(void *v)
158 {
159
160 return (0);
161 }
162
163 /*ARGSUSED*/
164 int
165 genfs_einval(void *v)
166 {
167
168 return (EINVAL);
169 }
170
171 /*
172 * Called when an fs doesn't support a particular vop.
173 * This takes care to vrele, vput, or vunlock passed in vnodes
174 * and calls VOP_ABORTOP for a componentname (in non-rename VOP).
175 */
176 int
177 genfs_eopnotsupp(void *v)
178 {
179 struct vop_generic_args /*
180 struct vnodeop_desc *a_desc;
181 / * other random data follows, presumably * /
182 } */ *ap = v;
183 struct vnodeop_desc *desc = ap->a_desc;
184 struct vnode *vp, *vp_last = NULL;
185 int flags, i, j, offset_cnp, offset_vp;
186
187 KASSERT(desc->vdesc_offset != VOP_LOOKUP_DESCOFFSET);
188 KASSERT(desc->vdesc_offset != VOP_ABORTOP_DESCOFFSET);
189
190 /*
191 * Free componentname that lookup potentially SAVENAMEd.
192 *
193 * As is logical, componentnames for VOP_RENAME are handled by
194 * the caller of VOP_RENAME. Yay, rename!
195 */
196 if (desc->vdesc_offset != VOP_RENAME_DESCOFFSET &&
197 (offset_vp = desc->vdesc_vp_offsets[0]) != VDESC_NO_OFFSET &&
198 (offset_cnp = desc->vdesc_componentname_offset) != VDESC_NO_OFFSET){
199 struct componentname *cnp;
200 struct vnode *dvp;
201
202 dvp = *VOPARG_OFFSETTO(struct vnode **, offset_vp, ap);
203 cnp = *VOPARG_OFFSETTO(struct componentname **, offset_cnp, ap);
204
205 VOP_ABORTOP(dvp, cnp);
206 }
207
208 flags = desc->vdesc_flags;
209 for (i = 0; i < VDESC_MAX_VPS; flags >>=1, i++) {
210 if ((offset_vp = desc->vdesc_vp_offsets[i]) == VDESC_NO_OFFSET)
211 break; /* stop at end of list */
212 if ((j = flags & VDESC_VP0_WILLPUT)) {
213 vp = *VOPARG_OFFSETTO(struct vnode **, offset_vp, ap);
214
215 /* Skip if NULL */
216 if (!vp)
217 continue;
218
219 switch (j) {
220 case VDESC_VP0_WILLPUT:
221 /* Check for dvp == vp cases */
222 if (vp == vp_last)
223 vrele(vp);
224 else {
225 vput(vp);
226 vp_last = vp;
227 }
228 break;
229 case VDESC_VP0_WILLUNLOCK:
230 VOP_UNLOCK(vp);
231 break;
232 case VDESC_VP0_WILLRELE:
233 vrele(vp);
234 break;
235 }
236 }
237 }
238
239 return (EOPNOTSUPP);
240 }
241
242 /*ARGSUSED*/
243 int
244 genfs_ebadf(void *v)
245 {
246
247 return (EBADF);
248 }
249
250 /* ARGSUSED */
251 int
252 genfs_enoioctl(void *v)
253 {
254
255 return (EPASSTHROUGH);
256 }
257
258
259 /*
260 * Eliminate all activity associated with the requested vnode
261 * and with all vnodes aliased to the requested vnode.
262 */
263 int
264 genfs_revoke(void *v)
265 {
266 struct vop_revoke_args /* {
267 struct vnode *a_vp;
268 int a_flags;
269 } */ *ap = v;
270
271 #ifdef DIAGNOSTIC
272 if ((ap->a_flags & REVOKEALL) == 0)
273 panic("genfs_revoke: not revokeall");
274 #endif
275 vrevoke(ap->a_vp);
276 return (0);
277 }
278
279 /*
280 * Lock the node.
281 */
282 int
283 genfs_lock(void *v)
284 {
285 struct vop_lock_args /* {
286 struct vnode *a_vp;
287 int a_flags;
288 } */ *ap = v;
289 struct vnode *vp = ap->a_vp;
290 int flags = ap->a_flags;
291
292 return (vlockmgr(&vp->v_lock, flags));
293 }
294
295 /*
296 * Unlock the node.
297 */
298 int
299 genfs_unlock(void *v)
300 {
301 struct vop_unlock_args /* {
302 struct vnode *a_vp;
303 } */ *ap = v;
304 struct vnode *vp = ap->a_vp;
305
306 return (vlockmgr(&vp->v_lock, LK_RELEASE));
307 }
308
309 /*
310 * Return whether or not the node is locked.
311 */
312 int
313 genfs_islocked(void *v)
314 {
315 struct vop_islocked_args /* {
316 struct vnode *a_vp;
317 } */ *ap = v;
318 struct vnode *vp = ap->a_vp;
319
320 return (vlockstatus(&vp->v_lock));
321 }
322
323 /*
324 * Stubs to use when there is no locking to be done on the underlying object.
325 */
326 int
327 genfs_nolock(void *v)
328 {
329
330 return (0);
331 }
332
333 int
334 genfs_nounlock(void *v)
335 {
336
337 return (0);
338 }
339
340 int
341 genfs_noislocked(void *v)
342 {
343
344 return (0);
345 }
346
347 int
348 genfs_mmap(void *v)
349 {
350
351 return (0);
352 }
353
354 /*
355 * VOP_PUTPAGES() for vnodes which never have pages.
356 */
357
358 int
359 genfs_null_putpages(void *v)
360 {
361 struct vop_putpages_args /* {
362 struct vnode *a_vp;
363 voff_t a_offlo;
364 voff_t a_offhi;
365 int a_flags;
366 } */ *ap = v;
367 struct vnode *vp = ap->a_vp;
368
369 KASSERT(vp->v_uobj.uo_npages == 0);
370 mutex_exit(&vp->v_interlock);
371 return (0);
372 }
373
374 void
375 genfs_node_init(struct vnode *vp, const struct genfs_ops *ops)
376 {
377 struct genfs_node *gp = VTOG(vp);
378
379 rw_init(&gp->g_glock);
380 gp->g_op = ops;
381 }
382
383 void
384 genfs_node_destroy(struct vnode *vp)
385 {
386 struct genfs_node *gp = VTOG(vp);
387
388 rw_destroy(&gp->g_glock);
389 }
390
391 void
392 genfs_size(struct vnode *vp, off_t size, off_t *eobp, int flags)
393 {
394 int bsize;
395
396 bsize = 1 << vp->v_mount->mnt_fs_bshift;
397 *eobp = (size + bsize - 1) & ~(bsize - 1);
398 }
399
400 static void
401 filt_genfsdetach(struct knote *kn)
402 {
403 struct vnode *vp = (struct vnode *)kn->kn_hook;
404
405 mutex_enter(&vp->v_interlock);
406 SLIST_REMOVE(&vp->v_klist, kn, knote, kn_selnext);
407 mutex_exit(&vp->v_interlock);
408 }
409
410 static int
411 filt_genfsread(struct knote *kn, long hint)
412 {
413 struct vnode *vp = (struct vnode *)kn->kn_hook;
414 int rv;
415
416 /*
417 * filesystem is gone, so set the EOF flag and schedule
418 * the knote for deletion.
419 */
420 switch (hint) {
421 case NOTE_REVOKE:
422 KASSERT(mutex_owned(&vp->v_interlock));
423 kn->kn_flags |= (EV_EOF | EV_ONESHOT);
424 return (1);
425 case 0:
426 mutex_enter(&vp->v_interlock);
427 kn->kn_data = vp->v_size - ((file_t *)kn->kn_obj)->f_offset;
428 rv = (kn->kn_data != 0);
429 mutex_exit(&vp->v_interlock);
430 return rv;
431 default:
432 KASSERT(mutex_owned(&vp->v_interlock));
433 kn->kn_data = vp->v_size - ((file_t *)kn->kn_obj)->f_offset;
434 return (kn->kn_data != 0);
435 }
436 }
437
438 static int
439 filt_genfsvnode(struct knote *kn, long hint)
440 {
441 struct vnode *vp = (struct vnode *)kn->kn_hook;
442 int fflags;
443
444 switch (hint) {
445 case NOTE_REVOKE:
446 KASSERT(mutex_owned(&vp->v_interlock));
447 kn->kn_flags |= EV_EOF;
448 if ((kn->kn_sfflags & hint) != 0)
449 kn->kn_fflags |= hint;
450 return (1);
451 case 0:
452 mutex_enter(&vp->v_interlock);
453 fflags = kn->kn_fflags;
454 mutex_exit(&vp->v_interlock);
455 break;
456 default:
457 KASSERT(mutex_owned(&vp->v_interlock));
458 if ((kn->kn_sfflags & hint) != 0)
459 kn->kn_fflags |= hint;
460 fflags = kn->kn_fflags;
461 break;
462 }
463
464 return (fflags != 0);
465 }
466
467 static const struct filterops genfsread_filtops =
468 { 1, NULL, filt_genfsdetach, filt_genfsread };
469 static const struct filterops genfsvnode_filtops =
470 { 1, NULL, filt_genfsdetach, filt_genfsvnode };
471
472 int
473 genfs_kqfilter(void *v)
474 {
475 struct vop_kqfilter_args /* {
476 struct vnode *a_vp;
477 struct knote *a_kn;
478 } */ *ap = v;
479 struct vnode *vp;
480 struct knote *kn;
481
482 vp = ap->a_vp;
483 kn = ap->a_kn;
484 switch (kn->kn_filter) {
485 case EVFILT_READ:
486 kn->kn_fop = &genfsread_filtops;
487 break;
488 case EVFILT_VNODE:
489 kn->kn_fop = &genfsvnode_filtops;
490 break;
491 default:
492 return (EINVAL);
493 }
494
495 kn->kn_hook = vp;
496
497 mutex_enter(&vp->v_interlock);
498 SLIST_INSERT_HEAD(&vp->v_klist, kn, kn_selnext);
499 mutex_exit(&vp->v_interlock);
500
501 return (0);
502 }
503
504 void
505 genfs_node_wrlock(struct vnode *vp)
506 {
507 struct genfs_node *gp = VTOG(vp);
508
509 rw_enter(&gp->g_glock, RW_WRITER);
510 }
511
512 void
513 genfs_node_rdlock(struct vnode *vp)
514 {
515 struct genfs_node *gp = VTOG(vp);
516
517 rw_enter(&gp->g_glock, RW_READER);
518 }
519
520 int
521 genfs_node_rdtrylock(struct vnode *vp)
522 {
523 struct genfs_node *gp = VTOG(vp);
524
525 return rw_tryenter(&gp->g_glock, RW_READER);
526 }
527
528 void
529 genfs_node_unlock(struct vnode *vp)
530 {
531 struct genfs_node *gp = VTOG(vp);
532
533 rw_exit(&gp->g_glock);
534 }
535
536 /*
537 * Do the usual access checking.
538 * file_mode, uid and gid are from the vnode in question,
539 * while acc_mode and cred are from the VOP_ACCESS parameter list
540 */
541 int
542 genfs_can_access(enum vtype type, mode_t file_mode, uid_t uid, gid_t gid,
543 mode_t acc_mode, kauth_cred_t cred)
544 {
545 mode_t mask;
546 int error, ismember;
547
548 /*
549 * Super-user always gets read/write access, but execute access depends
550 * on at least one execute bit being set.
551 */
552 if (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL) == 0) {
553 if ((acc_mode & VEXEC) && type != VDIR &&
554 (file_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0)
555 return (EACCES);
556 return (0);
557 }
558
559 mask = 0;
560
561 /* Otherwise, check the owner. */
562 if (kauth_cred_geteuid(cred) == uid) {
563 if (acc_mode & VEXEC)
564 mask |= S_IXUSR;
565 if (acc_mode & VREAD)
566 mask |= S_IRUSR;
567 if (acc_mode & VWRITE)
568 mask |= S_IWUSR;
569 return ((file_mode & mask) == mask ? 0 : EACCES);
570 }
571
572 /* Otherwise, check the groups. */
573 error = kauth_cred_ismember_gid(cred, gid, &ismember);
574 if (error)
575 return (error);
576 if (kauth_cred_getegid(cred) == gid || ismember) {
577 if (acc_mode & VEXEC)
578 mask |= S_IXGRP;
579 if (acc_mode & VREAD)
580 mask |= S_IRGRP;
581 if (acc_mode & VWRITE)
582 mask |= S_IWGRP;
583 return ((file_mode & mask) == mask ? 0 : EACCES);
584 }
585
586 /* Otherwise, check everyone else. */
587 if (acc_mode & VEXEC)
588 mask |= S_IXOTH;
589 if (acc_mode & VREAD)
590 mask |= S_IROTH;
591 if (acc_mode & VWRITE)
592 mask |= S_IWOTH;
593 return ((file_mode & mask) == mask ? 0 : EACCES);
594 }
595
596 /*
597 * Common routine to check if chmod() is allowed.
598 *
599 * Policy:
600 * - You must be root, or
601 * - You must own the file, and
602 * - You must not set the "sticky" bit (meaningless, see chmod(2))
603 * - You must be a member of the group if you're trying to set the
604 * SGIDf bit
605 *
606 * cred - credentials of the invoker
607 * vp - vnode of the file-system object
608 * cur_uid, cur_gid - current uid/gid of the file-system object
609 * new_mode - new mode for the file-system object
610 *
611 * Returns 0 if the change is allowed, or an error value otherwise.
612 */
613 int
614 genfs_can_chmod(vnode_t *vp, kauth_cred_t cred, uid_t cur_uid,
615 gid_t cur_gid, mode_t new_mode)
616 {
617 int error;
618
619 /* Superuser can always change mode. */
620 error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
621 NULL);
622 if (!error)
623 return (0);
624
625 /* Otherwise, user must own the file. */
626 if (kauth_cred_geteuid(cred) != cur_uid)
627 return (EPERM);
628
629 /*
630 * Non-root users can't set the sticky bit on files.
631 */
632 if ((vp->v_type != VDIR) && (new_mode & S_ISTXT))
633 return (EFTYPE);
634
635 /*
636 * If the invoker is trying to set the SGID bit on the file,
637 * check group membership.
638 */
639 if (new_mode & S_ISGID) {
640 int ismember;
641
642 error = kauth_cred_ismember_gid(cred, cur_gid,
643 &ismember);
644 if (error || !ismember)
645 return (EPERM);
646 }
647
648 return (0);
649 }
650
651 /*
652 * Common routine to check if chown() is allowed.
653 *
654 * Policy:
655 * - You must be root, or
656 * - You must own the file, and
657 * - You must not try to change ownership, and
658 * - You must be member of the new group
659 *
660 * cred - credentials of the invoker
661 * cur_uid, cur_gid - current uid/gid of the file-system object
662 * new_uid, new_gid - target uid/gid of the file-system object
663 *
664 * Returns 0 if the change is allowed, or an error value otherwise.
665 */
666 int
667 genfs_can_chown(vnode_t *vp, kauth_cred_t cred, uid_t cur_uid,
668 gid_t cur_gid, uid_t new_uid, gid_t new_gid)
669 {
670 int error, ismember;
671
672 /*
673 * You can only change ownership of a file if:
674 * You are the superuser, or...
675 */
676 error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
677 NULL);
678 if (!error)
679 return (0);
680
681 /*
682 * You own the file and...
683 */
684 if (kauth_cred_geteuid(cred) == cur_uid) {
685 /*
686 * You don't try to change ownership, and...
687 */
688 if (new_uid != cur_uid)
689 return (EPERM);
690
691 /*
692 * You don't try to change group (no-op), or...
693 */
694 if (new_gid == cur_gid)
695 return (0);
696
697 /*
698 * Your effective gid is the new gid, or...
699 */
700 if (kauth_cred_getegid(cred) == new_gid)
701 return (0);
702
703 /*
704 * The new gid is one you're a member of.
705 */
706 ismember = 0;
707 error = kauth_cred_ismember_gid(cred, new_gid,
708 &ismember);
709 if (!error && ismember)
710 return (0);
711 }
712
713 return (EPERM);
714 }
715
716 /*
717 * Common routine to check if the device can be mounted.
718 *
719 * devvp - the locked vnode of the device
720 * cred - credentials of the invoker
721 * accessmode - the accessmode (VREAD, VWRITE)
722 *
723 * Returns 0 if the mount is allowed, or an error value otherwise.
724 */
725 int
726 genfs_can_mount(vnode_t *devvp, mode_t accessmode, kauth_cred_t cred)
727 {
728 int error;
729
730 /* Always allow for root. */
731 error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
732 if (!error)
733 return (0);
734
735 error = VOP_ACCESS(devvp, accessmode, cred);
736
737 return (error);
738 }
739
740 int
741 genfs_can_chtimes(vnode_t *vp, u_int vaflags, uid_t owner_uid,
742 kauth_cred_t cred)
743 {
744 int error;
745
746 /* Must be root, or... */
747 error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL);
748 if (!error)
749 return (0);
750
751 /* must be owner, or... */
752 if (kauth_cred_geteuid(cred) == owner_uid)
753 return (0);
754
755 /* set the times to the current time, and... */
756 if ((vaflags & VA_UTIMES_NULL) == 0)
757 return (EPERM);
758
759 /* have write access. */
760 error = VOP_ACCESS(vp, VWRITE, cred);
761 if (error)
762 return (error);
763
764 return (0);
765 }
766
767