1 /*	$NetBSD: genfs_vnops.c,v 1.192 2014/03/24 13:42:40 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.192 2014/03/24 13:42:40 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/fstrans.h>
68 #include <sys/namei.h>
69 #include <sys/vnode.h>
70 #include <sys/fcntl.h>
71 #include <sys/kmem.h>
72 #include <sys/poll.h>
73 #include <sys/mman.h>
74 #include <sys/file.h>
75 #include <sys/kauth.h>
76 #include <sys/stat.h>
77 
78 #include <miscfs/genfs/genfs.h>
79 #include <miscfs/genfs/genfs_node.h>
80 #include <miscfs/specfs/specdev.h>
81 
82 #include <uvm/uvm.h>
83 #include <uvm/uvm_pager.h>
84 
85 static void filt_genfsdetach(struct knote *);
86 static int filt_genfsread(struct knote *, long);
87 static int filt_genfsvnode(struct knote *, long);
88 
89 int
genfs_poll(void * v)90 genfs_poll(void *v)
91 {
92 	struct vop_poll_args /* {
93 		struct vnode *a_vp;
94 		int a_events;
95 		struct lwp *a_l;
96 	} */ *ap = v;
97 
98 	return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
99 }
100 
101 int
genfs_seek(void * v)102 genfs_seek(void *v)
103 {
104 	struct vop_seek_args /* {
105 		struct vnode *a_vp;
106 		off_t a_oldoff;
107 		off_t a_newoff;
108 		kauth_cred_t cred;
109 	} */ *ap = v;
110 
111 	if (ap->a_newoff < 0)
112 		return (EINVAL);
113 
114 	return (0);
115 }
116 
117 int
genfs_abortop(void * v)118 genfs_abortop(void *v)
119 {
120 	struct vop_abortop_args /* {
121 		struct vnode *a_dvp;
122 		struct componentname *a_cnp;
123 	} */ *ap = v;
124 
125 	(void)ap;
126 
127 	return (0);
128 }
129 
130 int
genfs_fcntl(void * v)131 genfs_fcntl(void *v)
132 {
133 	struct vop_fcntl_args /* {
134 		struct vnode *a_vp;
135 		u_int a_command;
136 		void *a_data;
137 		int a_fflag;
138 		kauth_cred_t a_cred;
139 		struct lwp *a_l;
140 	} */ *ap = v;
141 
142 	if (ap->a_command == F_SETFL)
143 		return (0);
144 	else
145 		return (EOPNOTSUPP);
146 }
147 
148 /*ARGSUSED*/
149 int
genfs_badop(void * v)150 genfs_badop(void *v)
151 {
152 
153 	panic("genfs: bad op");
154 }
155 
156 /*ARGSUSED*/
157 int
genfs_nullop(void * v)158 genfs_nullop(void *v)
159 {
160 
161 	return (0);
162 }
163 
164 /*ARGSUSED*/
165 int
genfs_einval(void * v)166 genfs_einval(void *v)
167 {
168 
169 	return (EINVAL);
170 }
171 
172 /*
173  * Called when an fs doesn't support a particular vop.
174  * This takes care to vrele, vput, or vunlock passed in vnodes
175  * and calls VOP_ABORTOP for a componentname (in non-rename VOP).
176  */
177 int
genfs_eopnotsupp(void * v)178 genfs_eopnotsupp(void *v)
179 {
180 	struct vop_generic_args /*
181 		struct vnodeop_desc *a_desc;
182 		/ * other random data follows, presumably * /
183 	} */ *ap = v;
184 	struct vnodeop_desc *desc = ap->a_desc;
185 	struct vnode *vp, *vp_last = NULL;
186 	int flags, i, j, offset_cnp, offset_vp;
187 
188 	KASSERT(desc->vdesc_offset != VOP_LOOKUP_DESCOFFSET);
189 	KASSERT(desc->vdesc_offset != VOP_ABORTOP_DESCOFFSET);
190 
191 	/*
192 	 * Abort any componentname that lookup potentially left state in.
193 	 *
194 	 * As is logical, componentnames for VOP_RENAME are handled by
195 	 * the caller of VOP_RENAME.  Yay, rename!
196 	 */
197 	if (desc->vdesc_offset != VOP_RENAME_DESCOFFSET &&
198 	    (offset_vp = desc->vdesc_vp_offsets[0]) != VDESC_NO_OFFSET &&
199 	    (offset_cnp = desc->vdesc_componentname_offset) != VDESC_NO_OFFSET){
200 		struct componentname *cnp;
201 		struct vnode *dvp;
202 
203 		dvp = *VOPARG_OFFSETTO(struct vnode **, offset_vp, ap);
204 		cnp = *VOPARG_OFFSETTO(struct componentname **, offset_cnp, ap);
205 
206 		VOP_ABORTOP(dvp, cnp);
207 	}
208 
209 	flags = desc->vdesc_flags;
210 	for (i = 0; i < VDESC_MAX_VPS; flags >>=1, i++) {
211 		if ((offset_vp = desc->vdesc_vp_offsets[i]) == VDESC_NO_OFFSET)
212 			break;	/* stop at end of list */
213 		if ((j = flags & VDESC_VP0_WILLPUT)) {
214 			vp = *VOPARG_OFFSETTO(struct vnode **, offset_vp, ap);
215 
216 			/* Skip if NULL */
217 			if (!vp)
218 				continue;
219 
220 			switch (j) {
221 			case VDESC_VP0_WILLPUT:
222 				/* Check for dvp == vp cases */
223 				if (vp == vp_last)
224 					vrele(vp);
225 				else {
226 					vput(vp);
227 					vp_last = vp;
228 				}
229 				break;
230 			case VDESC_VP0_WILLUNLOCK:
231 				VOP_UNLOCK(vp);
232 				break;
233 			case VDESC_VP0_WILLRELE:
234 				vrele(vp);
235 				break;
236 			}
237 		}
238 	}
239 
240 	return (EOPNOTSUPP);
241 }
242 
243 /*ARGSUSED*/
244 int
genfs_ebadf(void * v)245 genfs_ebadf(void *v)
246 {
247 
248 	return (EBADF);
249 }
250 
251 /* ARGSUSED */
252 int
genfs_enoioctl(void * v)253 genfs_enoioctl(void *v)
254 {
255 
256 	return (EPASSTHROUGH);
257 }
258 
259 
260 /*
261  * Eliminate all activity associated with the requested vnode
262  * and with all vnodes aliased to the requested vnode.
263  */
264 int
genfs_revoke(void * v)265 genfs_revoke(void *v)
266 {
267 	struct vop_revoke_args /* {
268 		struct vnode *a_vp;
269 		int a_flags;
270 	} */ *ap = v;
271 
272 #ifdef DIAGNOSTIC
273 	if ((ap->a_flags & REVOKEALL) == 0)
274 		panic("genfs_revoke: not revokeall");
275 #endif
276 	vrevoke(ap->a_vp);
277 	return (0);
278 }
279 
280 /*
281  * Lock the node (for deadfs).
282  */
283 int
genfs_deadlock(void * v)284 genfs_deadlock(void *v)
285 {
286 	struct vop_lock_args /* {
287 		struct vnode *a_vp;
288 		int a_flags;
289 	} */ *ap = v;
290 	struct vnode *vp = ap->a_vp;
291 	int flags = ap->a_flags;
292 	krw_t op;
293 	int error;
294 
295 	op = (ISSET(flags, LK_EXCLUSIVE) ? RW_WRITER : RW_READER);
296 	if (ISSET(flags, LK_NOWAIT)) {
297 		if (! rw_tryenter(&vp->v_lock, op))
298 			return EBUSY;
299 		if (mutex_tryenter(vp->v_interlock)) {
300 			error = vdead_check(vp, VDEAD_NOWAIT);
301 			if (error == ENOENT && ISSET(flags, LK_RETRY))
302 				error = 0;
303 			mutex_exit(vp->v_interlock);
304 		} else
305 			error = EBUSY;
306 		if (error)
307 			rw_exit(&vp->v_lock);
308 		return error;
309 	}
310 
311 	rw_enter(&vp->v_lock, op);
312 	mutex_enter(vp->v_interlock);
313 	error = vdead_check(vp, VDEAD_NOWAIT);
314 	if (error == EBUSY) {
315 		rw_exit(&vp->v_lock);
316 		error = vdead_check(vp, 0);
317 		KASSERT(error == ENOENT);
318 		mutex_exit(vp->v_interlock);
319 		rw_enter(&vp->v_lock, op);
320 		mutex_enter(vp->v_interlock);
321 	}
322 	KASSERT(error == ENOENT);
323 	mutex_exit(vp->v_interlock);
324 	if (! ISSET(flags, LK_RETRY)) {
325 		rw_exit(&vp->v_lock);
326 		return ENOENT;
327 	}
328 	return 0;
329 }
330 
331 /*
332  * Unlock the node (for deadfs).
333  */
334 int
genfs_deadunlock(void * v)335 genfs_deadunlock(void *v)
336 {
337 	struct vop_unlock_args /* {
338 		struct vnode *a_vp;
339 	} */ *ap = v;
340 	struct vnode *vp = ap->a_vp;
341 
342 	rw_exit(&vp->v_lock);
343 
344 	return 0;
345 }
346 
347 /*
348  * Lock the node.
349  */
350 int
genfs_lock(void * v)351 genfs_lock(void *v)
352 {
353 	struct vop_lock_args /* {
354 		struct vnode *a_vp;
355 		int a_flags;
356 	} */ *ap = v;
357 	struct vnode *vp = ap->a_vp;
358 	struct mount *mp = vp->v_mount;
359 	int flags = ap->a_flags;
360 	krw_t op;
361 	int error;
362 
363 	op = (ISSET(flags, LK_EXCLUSIVE) ? RW_WRITER : RW_READER);
364 	if (ISSET(flags, LK_NOWAIT)) {
365 		if (fstrans_start_nowait(mp, FSTRANS_SHARED))
366 			return EBUSY;
367 		if (! rw_tryenter(&vp->v_lock, op)) {
368 			fstrans_done(mp);
369 			return EBUSY;
370 		}
371 		if (mutex_tryenter(vp->v_interlock)) {
372 			error = vdead_check(vp, VDEAD_NOWAIT);
373 			mutex_exit(vp->v_interlock);
374 		} else
375 			error = EBUSY;
376 		if (error) {
377 			rw_exit(&vp->v_lock);
378 			fstrans_done(mp);
379 		}
380 		return error;
381 	}
382 
383 	fstrans_start(mp, FSTRANS_SHARED);
384 	rw_enter(&vp->v_lock, op);
385 	mutex_enter(vp->v_interlock);
386 	error = vdead_check(vp, VDEAD_NOWAIT);
387 	if (error) {
388 		rw_exit(&vp->v_lock);
389 		fstrans_done(mp);
390 		error = vdead_check(vp, 0);
391 		KASSERT(error == ENOENT);
392 	}
393 	mutex_exit(vp->v_interlock);
394 	return error;
395 }
396 
397 /*
398  * Unlock the node.
399  */
400 int
genfs_unlock(void * v)401 genfs_unlock(void *v)
402 {
403 	struct vop_unlock_args /* {
404 		struct vnode *a_vp;
405 	} */ *ap = v;
406 	struct vnode *vp = ap->a_vp;
407 	struct mount *mp = vp->v_mount;
408 
409 	rw_exit(&vp->v_lock);
410 	fstrans_done(mp);
411 
412 	return 0;
413 }
414 
415 /*
416  * Return whether or not the node is locked.
417  */
418 int
genfs_islocked(void * v)419 genfs_islocked(void *v)
420 {
421 	struct vop_islocked_args /* {
422 		struct vnode *a_vp;
423 	} */ *ap = v;
424 	struct vnode *vp = ap->a_vp;
425 
426 	if (rw_write_held(&vp->v_lock))
427 		return LK_EXCLUSIVE;
428 
429 	if (rw_read_held(&vp->v_lock))
430 		return LK_SHARED;
431 
432 	return 0;
433 }
434 
435 /*
436  * Stubs to use when there is no locking to be done on the underlying object.
437  */
438 int
genfs_nolock(void * v)439 genfs_nolock(void *v)
440 {
441 
442 	return (0);
443 }
444 
445 int
genfs_nounlock(void * v)446 genfs_nounlock(void *v)
447 {
448 
449 	return (0);
450 }
451 
452 int
genfs_noislocked(void * v)453 genfs_noislocked(void *v)
454 {
455 
456 	return (0);
457 }
458 
459 int
genfs_mmap(void * v)460 genfs_mmap(void *v)
461 {
462 
463 	return (0);
464 }
465 
466 /*
467  * VOP_PUTPAGES() for vnodes which never have pages.
468  */
469 
470 int
genfs_null_putpages(void * v)471 genfs_null_putpages(void *v)
472 {
473 	struct vop_putpages_args /* {
474 		struct vnode *a_vp;
475 		voff_t a_offlo;
476 		voff_t a_offhi;
477 		int a_flags;
478 	} */ *ap = v;
479 	struct vnode *vp = ap->a_vp;
480 
481 	KASSERT(vp->v_uobj.uo_npages == 0);
482 	mutex_exit(vp->v_interlock);
483 	return (0);
484 }
485 
486 void
genfs_node_init(struct vnode * vp,const struct genfs_ops * ops)487 genfs_node_init(struct vnode *vp, const struct genfs_ops *ops)
488 {
489 	struct genfs_node *gp = VTOG(vp);
490 
491 	rw_init(&gp->g_glock);
492 	gp->g_op = ops;
493 }
494 
495 void
genfs_node_destroy(struct vnode * vp)496 genfs_node_destroy(struct vnode *vp)
497 {
498 	struct genfs_node *gp = VTOG(vp);
499 
500 	rw_destroy(&gp->g_glock);
501 }
502 
503 void
genfs_size(struct vnode * vp,off_t size,off_t * eobp,int flags)504 genfs_size(struct vnode *vp, off_t size, off_t *eobp, int flags)
505 {
506 	int bsize;
507 
508 	bsize = 1 << vp->v_mount->mnt_fs_bshift;
509 	*eobp = (size + bsize - 1) & ~(bsize - 1);
510 }
511 
512 static void
filt_genfsdetach(struct knote * kn)513 filt_genfsdetach(struct knote *kn)
514 {
515 	struct vnode *vp = (struct vnode *)kn->kn_hook;
516 
517 	mutex_enter(vp->v_interlock);
518 	SLIST_REMOVE(&vp->v_klist, kn, knote, kn_selnext);
519 	mutex_exit(vp->v_interlock);
520 }
521 
522 static int
filt_genfsread(struct knote * kn,long hint)523 filt_genfsread(struct knote *kn, long hint)
524 {
525 	struct vnode *vp = (struct vnode *)kn->kn_hook;
526 	int rv;
527 
528 	/*
529 	 * filesystem is gone, so set the EOF flag and schedule
530 	 * the knote for deletion.
531 	 */
532 	switch (hint) {
533 	case NOTE_REVOKE:
534 		KASSERT(mutex_owned(vp->v_interlock));
535 		kn->kn_flags |= (EV_EOF | EV_ONESHOT);
536 		return (1);
537 	case 0:
538 		mutex_enter(vp->v_interlock);
539 		kn->kn_data = vp->v_size - ((file_t *)kn->kn_obj)->f_offset;
540 		rv = (kn->kn_data != 0);
541 		mutex_exit(vp->v_interlock);
542 		return rv;
543 	default:
544 		KASSERT(mutex_owned(vp->v_interlock));
545 		kn->kn_data = vp->v_size - ((file_t *)kn->kn_obj)->f_offset;
546 		return (kn->kn_data != 0);
547 	}
548 }
549 
550 static int
filt_genfsvnode(struct knote * kn,long hint)551 filt_genfsvnode(struct knote *kn, long hint)
552 {
553 	struct vnode *vp = (struct vnode *)kn->kn_hook;
554 	int fflags;
555 
556 	switch (hint) {
557 	case NOTE_REVOKE:
558 		KASSERT(mutex_owned(vp->v_interlock));
559 		kn->kn_flags |= EV_EOF;
560 		if ((kn->kn_sfflags & hint) != 0)
561 			kn->kn_fflags |= hint;
562 		return (1);
563 	case 0:
564 		mutex_enter(vp->v_interlock);
565 		fflags = kn->kn_fflags;
566 		mutex_exit(vp->v_interlock);
567 		break;
568 	default:
569 		KASSERT(mutex_owned(vp->v_interlock));
570 		if ((kn->kn_sfflags & hint) != 0)
571 			kn->kn_fflags |= hint;
572 		fflags = kn->kn_fflags;
573 		break;
574 	}
575 
576 	return (fflags != 0);
577 }
578 
579 static const struct filterops genfsread_filtops =
580 	{ 1, NULL, filt_genfsdetach, filt_genfsread };
581 static const struct filterops genfsvnode_filtops =
582 	{ 1, NULL, filt_genfsdetach, filt_genfsvnode };
583 
584 int
genfs_kqfilter(void * v)585 genfs_kqfilter(void *v)
586 {
587 	struct vop_kqfilter_args /* {
588 		struct vnode	*a_vp;
589 		struct knote	*a_kn;
590 	} */ *ap = v;
591 	struct vnode *vp;
592 	struct knote *kn;
593 
594 	vp = ap->a_vp;
595 	kn = ap->a_kn;
596 	switch (kn->kn_filter) {
597 	case EVFILT_READ:
598 		kn->kn_fop = &genfsread_filtops;
599 		break;
600 	case EVFILT_VNODE:
601 		kn->kn_fop = &genfsvnode_filtops;
602 		break;
603 	default:
604 		return (EINVAL);
605 	}
606 
607 	kn->kn_hook = vp;
608 
609 	mutex_enter(vp->v_interlock);
610 	SLIST_INSERT_HEAD(&vp->v_klist, kn, kn_selnext);
611 	mutex_exit(vp->v_interlock);
612 
613 	return (0);
614 }
615 
616 void
genfs_node_wrlock(struct vnode * vp)617 genfs_node_wrlock(struct vnode *vp)
618 {
619 	struct genfs_node *gp = VTOG(vp);
620 
621 	rw_enter(&gp->g_glock, RW_WRITER);
622 }
623 
624 void
genfs_node_rdlock(struct vnode * vp)625 genfs_node_rdlock(struct vnode *vp)
626 {
627 	struct genfs_node *gp = VTOG(vp);
628 
629 	rw_enter(&gp->g_glock, RW_READER);
630 }
631 
632 int
genfs_node_rdtrylock(struct vnode * vp)633 genfs_node_rdtrylock(struct vnode *vp)
634 {
635 	struct genfs_node *gp = VTOG(vp);
636 
637 	return rw_tryenter(&gp->g_glock, RW_READER);
638 }
639 
640 void
genfs_node_unlock(struct vnode * vp)641 genfs_node_unlock(struct vnode *vp)
642 {
643 	struct genfs_node *gp = VTOG(vp);
644 
645 	rw_exit(&gp->g_glock);
646 }
647 
648 int
genfs_node_wrlocked(struct vnode * vp)649 genfs_node_wrlocked(struct vnode *vp)
650 {
651 	struct genfs_node *gp = VTOG(vp);
652 
653 	return rw_write_held(&gp->g_glock);
654 }
655 
656 /*
657  * Do the usual access checking.
658  * file_mode, uid and gid are from the vnode in question,
659  * while acc_mode and cred are from the VOP_ACCESS parameter list
660  */
661 int
genfs_can_access(enum vtype type,mode_t file_mode,uid_t uid,gid_t gid,mode_t acc_mode,kauth_cred_t cred)662 genfs_can_access(enum vtype type, mode_t file_mode, uid_t uid, gid_t gid,
663     mode_t acc_mode, kauth_cred_t cred)
664 {
665 	mode_t mask;
666 	int error, ismember;
667 
668 	mask = 0;
669 
670 	/* Otherwise, check the owner. */
671 	if (kauth_cred_geteuid(cred) == uid) {
672 		if (acc_mode & VEXEC)
673 			mask |= S_IXUSR;
674 		if (acc_mode & VREAD)
675 			mask |= S_IRUSR;
676 		if (acc_mode & VWRITE)
677 			mask |= S_IWUSR;
678 		return ((file_mode & mask) == mask ? 0 : EACCES);
679 	}
680 
681 	/* Otherwise, check the groups. */
682 	error = kauth_cred_ismember_gid(cred, gid, &ismember);
683 	if (error)
684 		return (error);
685 	if (kauth_cred_getegid(cred) == gid || ismember) {
686 		if (acc_mode & VEXEC)
687 			mask |= S_IXGRP;
688 		if (acc_mode & VREAD)
689 			mask |= S_IRGRP;
690 		if (acc_mode & VWRITE)
691 			mask |= S_IWGRP;
692 		return ((file_mode & mask) == mask ? 0 : EACCES);
693 	}
694 
695 	/* Otherwise, check everyone else. */
696 	if (acc_mode & VEXEC)
697 		mask |= S_IXOTH;
698 	if (acc_mode & VREAD)
699 		mask |= S_IROTH;
700 	if (acc_mode & VWRITE)
701 		mask |= S_IWOTH;
702 	return ((file_mode & mask) == mask ? 0 : EACCES);
703 }
704 
705 /*
706  * Common routine to check if chmod() is allowed.
707  *
708  * Policy:
709  *   - You must own the file, and
710  *     - You must not set the "sticky" bit (meaningless, see chmod(2))
711  *     - You must be a member of the group if you're trying to set the
712  *       SGIDf bit
713  *
714  * cred - credentials of the invoker
715  * vp - vnode of the file-system object
716  * cur_uid, cur_gid - current uid/gid of the file-system object
717  * new_mode - new mode for the file-system object
718  *
719  * Returns 0 if the change is allowed, or an error value otherwise.
720  */
721 int
genfs_can_chmod(enum vtype type,kauth_cred_t cred,uid_t cur_uid,gid_t cur_gid,mode_t new_mode)722 genfs_can_chmod(enum vtype type, kauth_cred_t cred, uid_t cur_uid,
723     gid_t cur_gid, mode_t new_mode)
724 {
725 	int error;
726 
727 	/* The user must own the file. */
728 	if (kauth_cred_geteuid(cred) != cur_uid)
729 		return (EPERM);
730 
731 	/*
732 	 * Unprivileged users can't set the sticky bit on files.
733 	 */
734 	if ((type != VDIR) && (new_mode & S_ISTXT))
735 		return (EFTYPE);
736 
737 	/*
738 	 * If the invoker is trying to set the SGID bit on the file,
739 	 * check group membership.
740 	 */
741 	if (new_mode & S_ISGID) {
742 		int ismember;
743 
744 		error = kauth_cred_ismember_gid(cred, cur_gid,
745 		    &ismember);
746 		if (error || !ismember)
747 			return (EPERM);
748 	}
749 
750 	return (0);
751 }
752 
753 /*
754  * Common routine to check if chown() is allowed.
755  *
756  * Policy:
757  *   - You must own the file, and
758  *     - You must not try to change ownership, and
759  *     - You must be member of the new group
760  *
761  * cred - credentials of the invoker
762  * cur_uid, cur_gid - current uid/gid of the file-system object
763  * new_uid, new_gid - target uid/gid of the file-system object
764  *
765  * Returns 0 if the change is allowed, or an error value otherwise.
766  */
767 int
genfs_can_chown(kauth_cred_t cred,uid_t cur_uid,gid_t cur_gid,uid_t new_uid,gid_t new_gid)768 genfs_can_chown(kauth_cred_t cred, uid_t cur_uid,
769     gid_t cur_gid, uid_t new_uid, gid_t new_gid)
770 {
771 	int error, ismember;
772 
773 	/*
774 	 * You can only change ownership of a file if:
775 	 * You own the file and...
776 	 */
777 	if (kauth_cred_geteuid(cred) == cur_uid) {
778 		/*
779 		 * You don't try to change ownership, and...
780 		 */
781 		if (new_uid != cur_uid)
782 			return (EPERM);
783 
784 		/*
785 		 * You don't try to change group (no-op), or...
786 		 */
787 		if (new_gid == cur_gid)
788 			return (0);
789 
790 		/*
791 		 * Your effective gid is the new gid, or...
792 		 */
793 		if (kauth_cred_getegid(cred) == new_gid)
794 			return (0);
795 
796 		/*
797 		 * The new gid is one you're a member of.
798 		 */
799 		ismember = 0;
800 		error = kauth_cred_ismember_gid(cred, new_gid,
801 		    &ismember);
802 		if (!error && ismember)
803 			return (0);
804 	}
805 
806 	return (EPERM);
807 }
808 
809 int
genfs_can_chtimes(vnode_t * vp,u_int vaflags,uid_t owner_uid,kauth_cred_t cred)810 genfs_can_chtimes(vnode_t *vp, u_int vaflags, uid_t owner_uid,
811     kauth_cred_t cred)
812 {
813 	int error;
814 
815 	/* Must be owner, or... */
816 	if (kauth_cred_geteuid(cred) == owner_uid)
817 		return (0);
818 
819 	/* set the times to the current time, and... */
820 	if ((vaflags & VA_UTIMES_NULL) == 0)
821 		return (EPERM);
822 
823 	/* have write access. */
824 	error = VOP_ACCESS(vp, VWRITE, cred);
825 	if (error)
826 		return (error);
827 
828 	return (0);
829 }
830 
831 /*
832  * Common routine to check if chflags() is allowed.
833  *
834  * Policy:
835  *   - You must own the file, and
836  *   - You must not change system flags, and
837  *   - You must not change flags on character/block devices.
838  *
839  * cred - credentials of the invoker
840  * owner_uid - uid of the file-system object
841  * changing_sysflags - true if the invoker wants to change system flags
842  */
843 int
genfs_can_chflags(kauth_cred_t cred,enum vtype type,uid_t owner_uid,bool changing_sysflags)844 genfs_can_chflags(kauth_cred_t cred, enum vtype type, uid_t owner_uid,
845     bool changing_sysflags)
846 {
847 
848 	/* The user must own the file. */
849 	if (kauth_cred_geteuid(cred) != owner_uid) {
850 		return EPERM;
851 	}
852 
853 	if (changing_sysflags) {
854 		return EPERM;
855 	}
856 
857 	/*
858 	 * Unprivileged users cannot change the flags on devices, even if they
859 	 * own them.
860 	 */
861 	if (type == VCHR || type == VBLK) {
862 		return EPERM;
863 	}
864 
865 	return 0;
866 }
867 
868 /*
869  * Common "sticky" policy.
870  *
871  * When a directory is "sticky" (as determined by the caller), this
872  * function may help implementing the following policy:
873  * - Renaming a file in it is only possible if the user owns the directory
874  *   or the file being renamed.
875  * - Deleting a file from it is only possible if the user owns the
876  *   directory or the file being deleted.
877  */
878 int
genfs_can_sticky(kauth_cred_t cred,uid_t dir_uid,uid_t file_uid)879 genfs_can_sticky(kauth_cred_t cred, uid_t dir_uid, uid_t file_uid)
880 {
881 	if (kauth_cred_geteuid(cred) != dir_uid &&
882 	    kauth_cred_geteuid(cred) != file_uid)
883 		return EPERM;
884 
885 	return 0;
886 }
887 
888 int
genfs_can_extattr(kauth_cred_t cred,int access_mode,vnode_t * vp,const char * attr)889 genfs_can_extattr(kauth_cred_t cred, int access_mode, vnode_t *vp,
890     const char *attr)
891 {
892 	/* We can't allow privileged namespaces. */
893 	if (strncasecmp(attr, "system", 6) == 0)
894 		return EPERM;
895 
896 	return VOP_ACCESS(vp, access_mode, cred);
897 }
898