Home | History | Annotate | Line # | Download | only in genfs
genfs_vnops.c revision 1.211
      1 /*	$NetBSD: genfs_vnops.c,v 1.211 2021/06/29 22:34:08 dholland 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.211 2021/06/29 22:34:08 dholland 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_impl.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 #include <sys/extattr.h>
     78 
     79 #include <miscfs/genfs/genfs.h>
     80 #include <miscfs/genfs/genfs_node.h>
     81 #include <miscfs/specfs/specdev.h>
     82 
     83 static void filt_genfsdetach(struct knote *);
     84 static int filt_genfsread(struct knote *, long);
     85 static int filt_genfsvnode(struct knote *, long);
     86 
     87 /*
     88  * Find the end of the first path component in NAME and return its
     89  * length.
     90  */
     91 int
     92 genfs_parsepath(void *v)
     93 {
     94 	struct vop_parsepath_args /* {
     95 		struct vnode *a_dvp;
     96 		const char *a_name;
     97 		size_t *a_ret;
     98 	} */ *ap = v;
     99 	const char *name = ap->a_name;
    100 	size_t pos;
    101 
    102 	(void)ap->a_dvp;
    103 
    104 	pos = 0;
    105 	while (name[pos] != '\0' && name[pos] != '/') {
    106 		pos++;
    107 	}
    108 	*ap->a_retval = pos;
    109 	return 0;
    110 }
    111 
    112 int
    113 genfs_poll(void *v)
    114 {
    115 	struct vop_poll_args /* {
    116 		struct vnode *a_vp;
    117 		int a_events;
    118 		struct lwp *a_l;
    119 	} */ *ap = v;
    120 
    121 	return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
    122 }
    123 
    124 int
    125 genfs_seek(void *v)
    126 {
    127 	struct vop_seek_args /* {
    128 		struct vnode *a_vp;
    129 		off_t a_oldoff;
    130 		off_t a_newoff;
    131 		kauth_cred_t cred;
    132 	} */ *ap = v;
    133 
    134 	if (ap->a_newoff < 0)
    135 		return (EINVAL);
    136 
    137 	return (0);
    138 }
    139 
    140 int
    141 genfs_abortop(void *v)
    142 {
    143 	struct vop_abortop_args /* {
    144 		struct vnode *a_dvp;
    145 		struct componentname *a_cnp;
    146 	} */ *ap = v;
    147 
    148 	(void)ap;
    149 
    150 	return (0);
    151 }
    152 
    153 int
    154 genfs_fcntl(void *v)
    155 {
    156 	struct vop_fcntl_args /* {
    157 		struct vnode *a_vp;
    158 		u_int a_command;
    159 		void *a_data;
    160 		int a_fflag;
    161 		kauth_cred_t a_cred;
    162 		struct lwp *a_l;
    163 	} */ *ap = v;
    164 
    165 	if (ap->a_command == F_SETFL)
    166 		return (0);
    167 	else
    168 		return (EOPNOTSUPP);
    169 }
    170 
    171 /*ARGSUSED*/
    172 int
    173 genfs_badop(void *v)
    174 {
    175 
    176 	panic("genfs: bad op");
    177 }
    178 
    179 /*ARGSUSED*/
    180 int
    181 genfs_nullop(void *v)
    182 {
    183 
    184 	return (0);
    185 }
    186 
    187 /*ARGSUSED*/
    188 int
    189 genfs_einval(void *v)
    190 {
    191 
    192 	return (EINVAL);
    193 }
    194 
    195 /*
    196  * Called when an fs doesn't support a particular vop.
    197  * This takes care to vrele, vput, or vunlock passed in vnodes
    198  * and calls VOP_ABORTOP for a componentname (in non-rename VOP).
    199  */
    200 int
    201 genfs_eopnotsupp(void *v)
    202 {
    203 	struct vop_generic_args /*
    204 		struct vnodeop_desc *a_desc;
    205 		/ * other random data follows, presumably * /
    206 	} */ *ap = v;
    207 	struct vnodeop_desc *desc = ap->a_desc;
    208 	struct vnode *vp, *vp_last = NULL;
    209 	int flags, i, j, offset_cnp, offset_vp;
    210 
    211 	KASSERT(desc->vdesc_offset != VOP_LOOKUP_DESCOFFSET);
    212 	KASSERT(desc->vdesc_offset != VOP_ABORTOP_DESCOFFSET);
    213 
    214 	/*
    215 	 * Abort any componentname that lookup potentially left state in.
    216 	 *
    217 	 * As is logical, componentnames for VOP_RENAME are handled by
    218 	 * the caller of VOP_RENAME.  Yay, rename!
    219 	 */
    220 	if (desc->vdesc_offset != VOP_RENAME_DESCOFFSET &&
    221 	    (offset_vp = desc->vdesc_vp_offsets[0]) != VDESC_NO_OFFSET &&
    222 	    (offset_cnp = desc->vdesc_componentname_offset) != VDESC_NO_OFFSET){
    223 		struct componentname *cnp;
    224 		struct vnode *dvp;
    225 
    226 		dvp = *VOPARG_OFFSETTO(struct vnode **, offset_vp, ap);
    227 		cnp = *VOPARG_OFFSETTO(struct componentname **, offset_cnp, ap);
    228 
    229 		VOP_ABORTOP(dvp, cnp);
    230 	}
    231 
    232 	flags = desc->vdesc_flags;
    233 	for (i = 0; i < VDESC_MAX_VPS; flags >>=1, i++) {
    234 		if ((offset_vp = desc->vdesc_vp_offsets[i]) == VDESC_NO_OFFSET)
    235 			break;	/* stop at end of list */
    236 		if ((j = flags & VDESC_VP0_WILLPUT)) {
    237 			vp = *VOPARG_OFFSETTO(struct vnode **, offset_vp, ap);
    238 
    239 			/* Skip if NULL */
    240 			if (!vp)
    241 				continue;
    242 
    243 			switch (j) {
    244 			case VDESC_VP0_WILLPUT:
    245 				/* Check for dvp == vp cases */
    246 				if (vp == vp_last)
    247 					vrele(vp);
    248 				else {
    249 					vput(vp);
    250 					vp_last = vp;
    251 				}
    252 				break;
    253 			case VDESC_VP0_WILLRELE:
    254 				vrele(vp);
    255 				break;
    256 			}
    257 		}
    258 	}
    259 
    260 	return (EOPNOTSUPP);
    261 }
    262 
    263 /*ARGSUSED*/
    264 int
    265 genfs_ebadf(void *v)
    266 {
    267 
    268 	return (EBADF);
    269 }
    270 
    271 /* ARGSUSED */
    272 int
    273 genfs_enoioctl(void *v)
    274 {
    275 
    276 	return (EPASSTHROUGH);
    277 }
    278 
    279 
    280 /*
    281  * Eliminate all activity associated with the requested vnode
    282  * and with all vnodes aliased to the requested vnode.
    283  */
    284 int
    285 genfs_revoke(void *v)
    286 {
    287 	struct vop_revoke_args /* {
    288 		struct vnode *a_vp;
    289 		int a_flags;
    290 	} */ *ap = v;
    291 
    292 #ifdef DIAGNOSTIC
    293 	if ((ap->a_flags & REVOKEALL) == 0)
    294 		panic("genfs_revoke: not revokeall");
    295 #endif
    296 	vrevoke(ap->a_vp);
    297 	return (0);
    298 }
    299 
    300 /*
    301  * Lock the node (for deadfs).
    302  */
    303 int
    304 genfs_deadlock(void *v)
    305 {
    306 	struct vop_lock_args /* {
    307 		struct vnode *a_vp;
    308 		int a_flags;
    309 	} */ *ap = v;
    310 	vnode_t *vp = ap->a_vp;
    311 	vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
    312 	int flags = ap->a_flags;
    313 	krw_t op;
    314 
    315 	if (! ISSET(flags, LK_RETRY))
    316 		return ENOENT;
    317 
    318 	if (ISSET(flags, LK_DOWNGRADE)) {
    319 		rw_downgrade(&vip->vi_lock);
    320 	} else if (ISSET(flags, LK_UPGRADE)) {
    321 		KASSERT(ISSET(flags, LK_NOWAIT));
    322 		if (!rw_tryupgrade(&vip->vi_lock)) {
    323 			return EBUSY;
    324 		}
    325 	} else if ((flags & (LK_EXCLUSIVE | LK_SHARED)) != 0) {
    326 		op = (ISSET(flags, LK_EXCLUSIVE) ? RW_WRITER : RW_READER);
    327 		if (ISSET(flags, LK_NOWAIT)) {
    328 			if (!rw_tryenter(&vip->vi_lock, op))
    329 				return EBUSY;
    330 		} else {
    331 			rw_enter(&vip->vi_lock, op);
    332 		}
    333 	}
    334 	VSTATE_ASSERT_UNLOCKED(vp, VS_RECLAIMED);
    335 	return 0;
    336 }
    337 
    338 /*
    339  * Unlock the node (for deadfs).
    340  */
    341 int
    342 genfs_deadunlock(void *v)
    343 {
    344 	struct vop_unlock_args /* {
    345 		struct vnode *a_vp;
    346 	} */ *ap = v;
    347 	vnode_t *vp = ap->a_vp;
    348 	vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
    349 
    350 	rw_exit(&vip->vi_lock);
    351 
    352 	return 0;
    353 }
    354 
    355 /*
    356  * Lock the node.
    357  */
    358 int
    359 genfs_lock(void *v)
    360 {
    361 	struct vop_lock_args /* {
    362 		struct vnode *a_vp;
    363 		int a_flags;
    364 	} */ *ap = v;
    365 	vnode_t *vp = ap->a_vp;
    366 	vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
    367 	int flags = ap->a_flags;
    368 	krw_t op;
    369 
    370 	if (ISSET(flags, LK_DOWNGRADE)) {
    371 		rw_downgrade(&vip->vi_lock);
    372 	} else if (ISSET(flags, LK_UPGRADE)) {
    373 		KASSERT(ISSET(flags, LK_NOWAIT));
    374 		if (!rw_tryupgrade(&vip->vi_lock)) {
    375 			return EBUSY;
    376 		}
    377 	} else if ((flags & (LK_EXCLUSIVE | LK_SHARED)) != 0) {
    378 		op = (ISSET(flags, LK_EXCLUSIVE) ? RW_WRITER : RW_READER);
    379 		if (ISSET(flags, LK_NOWAIT)) {
    380 			if (!rw_tryenter(&vip->vi_lock, op))
    381 				return EBUSY;
    382 		} else {
    383 			rw_enter(&vip->vi_lock, op);
    384 		}
    385 	}
    386 	VSTATE_ASSERT_UNLOCKED(vp, VS_ACTIVE);
    387 	return 0;
    388 }
    389 
    390 /*
    391  * Unlock the node.
    392  */
    393 int
    394 genfs_unlock(void *v)
    395 {
    396 	struct vop_unlock_args /* {
    397 		struct vnode *a_vp;
    398 	} */ *ap = v;
    399 	vnode_t *vp = ap->a_vp;
    400 	vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
    401 
    402 	rw_exit(&vip->vi_lock);
    403 
    404 	return 0;
    405 }
    406 
    407 /*
    408  * Return whether or not the node is locked.
    409  */
    410 int
    411 genfs_islocked(void *v)
    412 {
    413 	struct vop_islocked_args /* {
    414 		struct vnode *a_vp;
    415 	} */ *ap = v;
    416 	vnode_t *vp = ap->a_vp;
    417 	vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
    418 
    419 	if (rw_write_held(&vip->vi_lock))
    420 		return LK_EXCLUSIVE;
    421 
    422 	if (rw_read_held(&vip->vi_lock))
    423 		return LK_SHARED;
    424 
    425 	return 0;
    426 }
    427 
    428 /*
    429  * Stubs to use when there is no locking to be done on the underlying object.
    430  */
    431 int
    432 genfs_nolock(void *v)
    433 {
    434 
    435 	return (0);
    436 }
    437 
    438 int
    439 genfs_nounlock(void *v)
    440 {
    441 
    442 	return (0);
    443 }
    444 
    445 int
    446 genfs_noislocked(void *v)
    447 {
    448 
    449 	return (0);
    450 }
    451 
    452 int
    453 genfs_mmap(void *v)
    454 {
    455 
    456 	return (0);
    457 }
    458 
    459 /*
    460  * VOP_PUTPAGES() for vnodes which never have pages.
    461  */
    462 
    463 int
    464 genfs_null_putpages(void *v)
    465 {
    466 	struct vop_putpages_args /* {
    467 		struct vnode *a_vp;
    468 		voff_t a_offlo;
    469 		voff_t a_offhi;
    470 		int a_flags;
    471 	} */ *ap = v;
    472 	struct vnode *vp = ap->a_vp;
    473 
    474 	KASSERT(vp->v_uobj.uo_npages == 0);
    475 	rw_exit(vp->v_uobj.vmobjlock);
    476 	return (0);
    477 }
    478 
    479 void
    480 genfs_node_init(struct vnode *vp, const struct genfs_ops *ops)
    481 {
    482 	struct genfs_node *gp = VTOG(vp);
    483 
    484 	rw_init(&gp->g_glock);
    485 	gp->g_op = ops;
    486 }
    487 
    488 void
    489 genfs_node_destroy(struct vnode *vp)
    490 {
    491 	struct genfs_node *gp = VTOG(vp);
    492 
    493 	rw_destroy(&gp->g_glock);
    494 }
    495 
    496 void
    497 genfs_size(struct vnode *vp, off_t size, off_t *eobp, int flags)
    498 {
    499 	int bsize;
    500 
    501 	bsize = 1 << vp->v_mount->mnt_fs_bshift;
    502 	*eobp = (size + bsize - 1) & ~(bsize - 1);
    503 }
    504 
    505 static void
    506 filt_genfsdetach(struct knote *kn)
    507 {
    508 	struct vnode *vp = (struct vnode *)kn->kn_hook;
    509 
    510 	mutex_enter(vp->v_interlock);
    511 	SLIST_REMOVE(&vp->v_klist, kn, knote, kn_selnext);
    512 	mutex_exit(vp->v_interlock);
    513 }
    514 
    515 static int
    516 filt_genfsread(struct knote *kn, long hint)
    517 {
    518 	struct vnode *vp = (struct vnode *)kn->kn_hook;
    519 	int rv;
    520 
    521 	/*
    522 	 * filesystem is gone, so set the EOF flag and schedule
    523 	 * the knote for deletion.
    524 	 */
    525 	switch (hint) {
    526 	case NOTE_REVOKE:
    527 		KASSERT(mutex_owned(vp->v_interlock));
    528 		kn->kn_flags |= (EV_EOF | EV_ONESHOT);
    529 		return (1);
    530 	case 0:
    531 		mutex_enter(vp->v_interlock);
    532 		kn->kn_data = vp->v_size - ((file_t *)kn->kn_obj)->f_offset;
    533 		rv = (kn->kn_data != 0);
    534 		mutex_exit(vp->v_interlock);
    535 		return rv;
    536 	default:
    537 		KASSERT(mutex_owned(vp->v_interlock));
    538 		kn->kn_data = vp->v_size - ((file_t *)kn->kn_obj)->f_offset;
    539 		return (kn->kn_data != 0);
    540 	}
    541 }
    542 
    543 static int
    544 filt_genfswrite(struct knote *kn, long hint)
    545 {
    546 	struct vnode *vp = (struct vnode *)kn->kn_hook;
    547 
    548 	/*
    549 	 * filesystem is gone, so set the EOF flag and schedule
    550 	 * the knote for deletion.
    551 	 */
    552 	switch (hint) {
    553 	case NOTE_REVOKE:
    554 		KASSERT(mutex_owned(vp->v_interlock));
    555 		kn->kn_flags |= (EV_EOF | EV_ONESHOT);
    556 		return (1);
    557 	case 0:
    558 		mutex_enter(vp->v_interlock);
    559 		kn->kn_data = 0;
    560 		mutex_exit(vp->v_interlock);
    561 		return 1;
    562 	default:
    563 		KASSERT(mutex_owned(vp->v_interlock));
    564 		kn->kn_data = 0;
    565 		return 1;
    566 	}
    567 }
    568 
    569 static int
    570 filt_genfsvnode(struct knote *kn, long hint)
    571 {
    572 	struct vnode *vp = (struct vnode *)kn->kn_hook;
    573 	int fflags;
    574 
    575 	switch (hint) {
    576 	case NOTE_REVOKE:
    577 		KASSERT(mutex_owned(vp->v_interlock));
    578 		kn->kn_flags |= EV_EOF;
    579 		if ((kn->kn_sfflags & hint) != 0)
    580 			kn->kn_fflags |= hint;
    581 		return (1);
    582 	case 0:
    583 		mutex_enter(vp->v_interlock);
    584 		fflags = kn->kn_fflags;
    585 		mutex_exit(vp->v_interlock);
    586 		break;
    587 	default:
    588 		KASSERT(mutex_owned(vp->v_interlock));
    589 		if ((kn->kn_sfflags & hint) != 0)
    590 			kn->kn_fflags |= hint;
    591 		fflags = kn->kn_fflags;
    592 		break;
    593 	}
    594 
    595 	return (fflags != 0);
    596 }
    597 
    598 static const struct filterops genfsread_filtops = {
    599 	.f_isfd = 1,
    600 	.f_attach = NULL,
    601 	.f_detach = filt_genfsdetach,
    602 	.f_event = filt_genfsread,
    603 };
    604 
    605 static const struct filterops genfswrite_filtops = {
    606 	.f_isfd = 1,
    607 	.f_attach = NULL,
    608 	.f_detach = filt_genfsdetach,
    609 	.f_event = filt_genfswrite,
    610 };
    611 
    612 static const struct filterops genfsvnode_filtops = {
    613 	.f_isfd = 1,
    614 	.f_attach = NULL,
    615 	.f_detach = filt_genfsdetach,
    616 	.f_event = filt_genfsvnode,
    617 };
    618 
    619 int
    620 genfs_kqfilter(void *v)
    621 {
    622 	struct vop_kqfilter_args /* {
    623 		struct vnode	*a_vp;
    624 		struct knote	*a_kn;
    625 	} */ *ap = v;
    626 	struct vnode *vp;
    627 	struct knote *kn;
    628 
    629 	vp = ap->a_vp;
    630 	kn = ap->a_kn;
    631 	switch (kn->kn_filter) {
    632 	case EVFILT_READ:
    633 		kn->kn_fop = &genfsread_filtops;
    634 		break;
    635 	case EVFILT_WRITE:
    636 		kn->kn_fop = &genfswrite_filtops;
    637 		break;
    638 	case EVFILT_VNODE:
    639 		kn->kn_fop = &genfsvnode_filtops;
    640 		break;
    641 	default:
    642 		return (EINVAL);
    643 	}
    644 
    645 	kn->kn_hook = vp;
    646 
    647 	mutex_enter(vp->v_interlock);
    648 	SLIST_INSERT_HEAD(&vp->v_klist, kn, kn_selnext);
    649 	mutex_exit(vp->v_interlock);
    650 
    651 	return (0);
    652 }
    653 
    654 void
    655 genfs_node_wrlock(struct vnode *vp)
    656 {
    657 	struct genfs_node *gp = VTOG(vp);
    658 
    659 	rw_enter(&gp->g_glock, RW_WRITER);
    660 }
    661 
    662 void
    663 genfs_node_rdlock(struct vnode *vp)
    664 {
    665 	struct genfs_node *gp = VTOG(vp);
    666 
    667 	rw_enter(&gp->g_glock, RW_READER);
    668 }
    669 
    670 int
    671 genfs_node_rdtrylock(struct vnode *vp)
    672 {
    673 	struct genfs_node *gp = VTOG(vp);
    674 
    675 	return rw_tryenter(&gp->g_glock, RW_READER);
    676 }
    677 
    678 void
    679 genfs_node_unlock(struct vnode *vp)
    680 {
    681 	struct genfs_node *gp = VTOG(vp);
    682 
    683 	rw_exit(&gp->g_glock);
    684 }
    685 
    686 int
    687 genfs_node_wrlocked(struct vnode *vp)
    688 {
    689 	struct genfs_node *gp = VTOG(vp);
    690 
    691 	return rw_write_held(&gp->g_glock);
    692 }
    693 
    694 static int
    695 groupmember(gid_t gid, kauth_cred_t cred)
    696 {
    697 	int ismember;
    698 	int error = kauth_cred_ismember_gid(cred, gid, &ismember);
    699 	if (error)
    700 		return error;
    701 	if (kauth_cred_getegid(cred) == gid || ismember)
    702 		return 0;
    703 	return -1;
    704 }
    705 
    706 /*
    707  * Common filesystem object access control check routine.  Accepts a
    708  * vnode, cred, uid, gid, mode, acl, requested access mode.
    709  * Returns 0 on success, or an errno on failure.
    710  */
    711 int
    712 genfs_can_access(vnode_t *vp, kauth_cred_t cred, uid_t file_uid, gid_t file_gid,
    713     mode_t file_mode, struct acl *acl, accmode_t accmode)
    714 {
    715 	accmode_t dac_granted;
    716 	int error;
    717 
    718 	KASSERT((accmode & ~(VEXEC | VWRITE | VREAD | VADMIN | VAPPEND)) == 0);
    719 	KASSERT((accmode & VAPPEND) == 0 || (accmode & VWRITE));
    720 
    721 	/*
    722 	 * Look for a normal, non-privileged way to access the file/directory
    723 	 * as requested.  If it exists, go with that.
    724 	 */
    725 
    726 	dac_granted = 0;
    727 
    728 	/* Check the owner. */
    729 	if (kauth_cred_geteuid(cred) == file_uid) {
    730 		dac_granted |= VADMIN;
    731 		if (file_mode & S_IXUSR)
    732 			dac_granted |= VEXEC;
    733 		if (file_mode & S_IRUSR)
    734 			dac_granted |= VREAD;
    735 		if (file_mode & S_IWUSR)
    736 			dac_granted |= (VWRITE | VAPPEND);
    737 
    738 		goto privchk;
    739 	}
    740 
    741 	/* Otherwise, check the groups (first match) */
    742 	/* Otherwise, check the groups. */
    743 	error = groupmember(file_gid, cred);
    744 	if (error > 0)
    745 		return error;
    746 	if (error == 0) {
    747 		if (file_mode & S_IXGRP)
    748 			dac_granted |= VEXEC;
    749 		if (file_mode & S_IRGRP)
    750 			dac_granted |= VREAD;
    751 		if (file_mode & S_IWGRP)
    752 			dac_granted |= (VWRITE | VAPPEND);
    753 
    754 		goto privchk;
    755 	}
    756 
    757 	/* Otherwise, check everyone else. */
    758 	if (file_mode & S_IXOTH)
    759 		dac_granted |= VEXEC;
    760 	if (file_mode & S_IROTH)
    761 		dac_granted |= VREAD;
    762 	if (file_mode & S_IWOTH)
    763 		dac_granted |= (VWRITE | VAPPEND);
    764 
    765 privchk:
    766 	if ((accmode & dac_granted) == accmode)
    767 		return 0;
    768 
    769 	return (accmode & VADMIN) ? EPERM : EACCES;
    770 }
    771 
    772 /*
    773  * Implement a version of genfs_can_access() that understands POSIX.1e ACL
    774  * semantics;
    775  * the access ACL has already been prepared for evaluation by the file system
    776  * and is passed via 'uid', 'gid', and 'acl'.  Return 0 on success, else an
    777  * errno value.
    778  */
    779 int
    780 genfs_can_access_acl_posix1e(vnode_t *vp, kauth_cred_t cred, uid_t file_uid,
    781     gid_t file_gid, mode_t file_mode, struct acl *acl, accmode_t accmode)
    782 {
    783 	struct acl_entry *acl_other, *acl_mask;
    784 	accmode_t dac_granted;
    785 	accmode_t acl_mask_granted;
    786 	int group_matched, i;
    787 	int error;
    788 
    789 	KASSERT((accmode & ~(VEXEC | VWRITE | VREAD | VADMIN | VAPPEND)) == 0);
    790 	KASSERT((accmode & VAPPEND) == 0 || (accmode & VWRITE));
    791 
    792 	/*
    793 	 * The owner matches if the effective uid associated with the
    794 	 * credential matches that of the ACL_USER_OBJ entry.  While we're
    795 	 * doing the first scan, also cache the location of the ACL_MASK and
    796 	 * ACL_OTHER entries, preventing some future iterations.
    797 	 */
    798 	acl_mask = acl_other = NULL;
    799 	for (i = 0; i < acl->acl_cnt; i++) {
    800 		struct acl_entry *ae = &acl->acl_entry[i];
    801 		switch (ae->ae_tag) {
    802 		case ACL_USER_OBJ:
    803 			if (kauth_cred_geteuid(cred) != file_uid)
    804 				break;
    805 			dac_granted = 0;
    806 			dac_granted |= VADMIN;
    807 			if (ae->ae_perm & ACL_EXECUTE)
    808 				dac_granted |= VEXEC;
    809 			if (ae->ae_perm & ACL_READ)
    810 				dac_granted |= VREAD;
    811 			if (ae->ae_perm & ACL_WRITE)
    812 				dac_granted |= (VWRITE | VAPPEND);
    813 			goto out;
    814 
    815 		case ACL_MASK:
    816 			acl_mask = ae;
    817 			break;
    818 
    819 		case ACL_OTHER:
    820 			acl_other = ae;
    821 			break;
    822 
    823 		default:
    824 			break;
    825 		}
    826 	}
    827 
    828 	/*
    829 	 * An ACL_OTHER entry should always exist in a valid access ACL.  If
    830 	 * it doesn't, then generate a serious failure.	 For now, this means
    831 	 * a debugging message and EPERM, but in the future should probably
    832 	 * be a panic.
    833 	 */
    834 	if (acl_other == NULL) {
    835 		/*
    836 		 * XXX This should never happen
    837 		 */
    838 		printf("%s: ACL_OTHER missing\n", __func__);
    839 		return EPERM;
    840 	}
    841 
    842 	/*
    843 	 * Checks against ACL_USER, ACL_GROUP_OBJ, and ACL_GROUP fields are
    844 	 * masked by an ACL_MASK entry, if any.	 As such, first identify the
    845 	 * ACL_MASK field, then iterate through identifying potential user
    846 	 * matches, then group matches.	 If there is no ACL_MASK, assume that
    847 	 * the mask allows all requests to succeed.
    848 	 */
    849 	if (acl_mask != NULL) {
    850 		acl_mask_granted = 0;
    851 		if (acl_mask->ae_perm & ACL_EXECUTE)
    852 			acl_mask_granted |= VEXEC;
    853 		if (acl_mask->ae_perm & ACL_READ)
    854 			acl_mask_granted |= VREAD;
    855 		if (acl_mask->ae_perm & ACL_WRITE)
    856 			acl_mask_granted |= (VWRITE | VAPPEND);
    857 	} else
    858 		acl_mask_granted = VEXEC | VREAD | VWRITE | VAPPEND;
    859 
    860 	/*
    861 	 * Check ACL_USER ACL entries.	There will either be one or no
    862 	 * matches; if there is one, we accept or rejected based on the
    863 	 * match; otherwise, we continue on to groups.
    864 	 */
    865 	for (i = 0; i < acl->acl_cnt; i++) {
    866 		struct acl_entry *ae = &acl->acl_entry[i];
    867 		switch (ae->ae_tag) {
    868 		case ACL_USER:
    869 			if (kauth_cred_geteuid(cred) != ae->ae_id)
    870 				break;
    871 			dac_granted = 0;
    872 			if (ae->ae_perm & ACL_EXECUTE)
    873 				dac_granted |= VEXEC;
    874 			if (ae->ae_perm & ACL_READ)
    875 				dac_granted |= VREAD;
    876 			if (ae->ae_perm & ACL_WRITE)
    877 				dac_granted |= (VWRITE | VAPPEND);
    878 			dac_granted &= acl_mask_granted;
    879 			goto out;
    880 		}
    881 	}
    882 
    883 	/*
    884 	 * Group match is best-match, not first-match, so find a "best"
    885 	 * match.  Iterate across, testing each potential group match.	Make
    886 	 * sure we keep track of whether we found a match or not, so that we
    887 	 * know if we should try again with any available privilege, or if we
    888 	 * should move on to ACL_OTHER.
    889 	 */
    890 	group_matched = 0;
    891 	for (i = 0; i < acl->acl_cnt; i++) {
    892 		struct acl_entry *ae = &acl->acl_entry[i];
    893 		switch (ae->ae_tag) {
    894 		case ACL_GROUP_OBJ:
    895 			error = groupmember(file_gid, cred);
    896 			if (error > 0)
    897 				return error;
    898 			if (error)
    899 				break;
    900 			dac_granted = 0;
    901 			if (ae->ae_perm & ACL_EXECUTE)
    902 				dac_granted |= VEXEC;
    903 			if (ae->ae_perm & ACL_READ)
    904 				dac_granted |= VREAD;
    905 			if (ae->ae_perm & ACL_WRITE)
    906 				dac_granted |= (VWRITE | VAPPEND);
    907 			dac_granted  &= acl_mask_granted;
    908 
    909 			if ((accmode & dac_granted) == accmode)
    910 				return 0;
    911 
    912 			group_matched = 1;
    913 			break;
    914 
    915 		case ACL_GROUP:
    916 			error = groupmember(ae->ae_id, cred);
    917 			if (error > 0)
    918 				return error;
    919 			if (error)
    920 				break;
    921 			dac_granted = 0;
    922 			if (ae->ae_perm & ACL_EXECUTE)
    923 				dac_granted |= VEXEC;
    924 			if (ae->ae_perm & ACL_READ)
    925 				dac_granted |= VREAD;
    926 			if (ae->ae_perm & ACL_WRITE)
    927 				dac_granted |= (VWRITE | VAPPEND);
    928 			dac_granted  &= acl_mask_granted;
    929 
    930 			if ((accmode & dac_granted) == accmode)
    931 				return 0;
    932 
    933 			group_matched = 1;
    934 			break;
    935 
    936 		default:
    937 			break;
    938 		}
    939 	}
    940 
    941 	if (group_matched == 1) {
    942 		/*
    943 		 * There was a match, but it did not grant rights via pure
    944 		 * DAC.	 Try again, this time with privilege.
    945 		 */
    946 		for (i = 0; i < acl->acl_cnt; i++) {
    947 			struct acl_entry *ae = &acl->acl_entry[i];
    948 			switch (ae->ae_tag) {
    949 			case ACL_GROUP_OBJ:
    950 				error = groupmember(file_gid, cred);
    951 				if (error > 0)
    952 					return error;
    953 				if (error)
    954 					break;
    955 				dac_granted = 0;
    956 				if (ae->ae_perm & ACL_EXECUTE)
    957 					dac_granted |= VEXEC;
    958 				if (ae->ae_perm & ACL_READ)
    959 					dac_granted |= VREAD;
    960 				if (ae->ae_perm & ACL_WRITE)
    961 					dac_granted |= (VWRITE | VAPPEND);
    962 				dac_granted &= acl_mask_granted;
    963 				goto out;
    964 
    965 			case ACL_GROUP:
    966 				error = groupmember(ae->ae_id, cred);
    967 				if (error > 0)
    968 					return error;
    969 				if (error)
    970 					break;
    971 				dac_granted = 0;
    972 				if (ae->ae_perm & ACL_EXECUTE)
    973 				dac_granted |= VEXEC;
    974 				if (ae->ae_perm & ACL_READ)
    975 					dac_granted |= VREAD;
    976 				if (ae->ae_perm & ACL_WRITE)
    977 					dac_granted |= (VWRITE | VAPPEND);
    978 				dac_granted &= acl_mask_granted;
    979 
    980 				goto out;
    981 			default:
    982 				break;
    983 			}
    984 		}
    985 		/*
    986 		 * Even with privilege, group membership was not sufficient.
    987 		 * Return failure.
    988 		 */
    989 		dac_granted = 0;
    990 		goto out;
    991 	}
    992 
    993 	/*
    994 	 * Fall back on ACL_OTHER.  ACL_MASK is not applied to ACL_OTHER.
    995 	 */
    996 	dac_granted = 0;
    997 	if (acl_other->ae_perm & ACL_EXECUTE)
    998 		dac_granted |= VEXEC;
    999 	if (acl_other->ae_perm & ACL_READ)
   1000 		dac_granted |= VREAD;
   1001 	if (acl_other->ae_perm & ACL_WRITE)
   1002 		dac_granted |= (VWRITE | VAPPEND);
   1003 
   1004 out:
   1005 	if ((accmode & dac_granted) == accmode)
   1006 		return 0;
   1007 	return (accmode & VADMIN) ? EPERM : EACCES;
   1008 }
   1009 
   1010 static struct {
   1011 	accmode_t accmode;
   1012 	int mask;
   1013 } accmode2mask[] = {
   1014 	{ VREAD, ACL_READ_DATA },
   1015 	{ VWRITE, ACL_WRITE_DATA },
   1016 	{ VAPPEND, ACL_APPEND_DATA },
   1017 	{ VEXEC, ACL_EXECUTE },
   1018 	{ VREAD_NAMED_ATTRS, ACL_READ_NAMED_ATTRS },
   1019 	{ VWRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS },
   1020 	{ VDELETE_CHILD, ACL_DELETE_CHILD },
   1021 	{ VREAD_ATTRIBUTES, ACL_READ_ATTRIBUTES },
   1022 	{ VWRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES },
   1023 	{ VDELETE, ACL_DELETE },
   1024 	{ VREAD_ACL, ACL_READ_ACL },
   1025 	{ VWRITE_ACL, ACL_WRITE_ACL },
   1026 	{ VWRITE_OWNER, ACL_WRITE_OWNER },
   1027 	{ VSYNCHRONIZE, ACL_SYNCHRONIZE },
   1028 	{ 0, 0 },
   1029 };
   1030 
   1031 static int
   1032 _access_mask_from_accmode(accmode_t accmode)
   1033 {
   1034 	int access_mask = 0, i;
   1035 
   1036 	for (i = 0; accmode2mask[i].accmode != 0; i++) {
   1037 		if (accmode & accmode2mask[i].accmode)
   1038 			access_mask |= accmode2mask[i].mask;
   1039 	}
   1040 
   1041 	/*
   1042 	 * VAPPEND is just a modifier for VWRITE; if the caller asked
   1043 	 * for 'VAPPEND | VWRITE', we want to check for ACL_APPEND_DATA only.
   1044 	 */
   1045 	if (access_mask & ACL_APPEND_DATA)
   1046 		access_mask &= ~ACL_WRITE_DATA;
   1047 
   1048 	return (access_mask);
   1049 }
   1050 
   1051 /*
   1052  * Return 0, iff access is allowed, 1 otherwise.
   1053  */
   1054 static int
   1055 _acl_denies(const struct acl *aclp, int access_mask, kauth_cred_t cred,
   1056     int file_uid, int file_gid, int *denied_explicitly)
   1057 {
   1058 	int i, error;
   1059 	const struct acl_entry *ae;
   1060 
   1061 	if (denied_explicitly != NULL)
   1062 		*denied_explicitly = 0;
   1063 
   1064 	KASSERT(aclp->acl_cnt <= ACL_MAX_ENTRIES);
   1065 
   1066 	for (i = 0; i < aclp->acl_cnt; i++) {
   1067 		ae = &(aclp->acl_entry[i]);
   1068 
   1069 		if (ae->ae_entry_type != ACL_ENTRY_TYPE_ALLOW &&
   1070 		    ae->ae_entry_type != ACL_ENTRY_TYPE_DENY)
   1071 			continue;
   1072 		if (ae->ae_flags & ACL_ENTRY_INHERIT_ONLY)
   1073 			continue;
   1074 		switch (ae->ae_tag) {
   1075 		case ACL_USER_OBJ:
   1076 			if (kauth_cred_geteuid(cred) != file_uid)
   1077 				continue;
   1078 			break;
   1079 		case ACL_USER:
   1080 			if (kauth_cred_geteuid(cred) != ae->ae_id)
   1081 				continue;
   1082 			break;
   1083 		case ACL_GROUP_OBJ:
   1084 			error = groupmember(file_gid, cred);
   1085 			if (error > 0)
   1086 				return error;
   1087 			if (error != 0)
   1088 				continue;
   1089 			break;
   1090 		case ACL_GROUP:
   1091 			error = groupmember(ae->ae_id, cred);
   1092 			if (error > 0)
   1093 				return error;
   1094 			if (error != 0)
   1095 				continue;
   1096 			break;
   1097 		default:
   1098 			KASSERT(ae->ae_tag == ACL_EVERYONE);
   1099 		}
   1100 
   1101 		if (ae->ae_entry_type == ACL_ENTRY_TYPE_DENY) {
   1102 			if (ae->ae_perm & access_mask) {
   1103 				if (denied_explicitly != NULL)
   1104 					*denied_explicitly = 1;
   1105 				return (1);
   1106 			}
   1107 		}
   1108 
   1109 		access_mask &= ~(ae->ae_perm);
   1110 		if (access_mask == 0)
   1111 			return (0);
   1112 	}
   1113 
   1114 	if (access_mask == 0)
   1115 		return (0);
   1116 
   1117 	return (1);
   1118 }
   1119 
   1120 int
   1121 genfs_can_access_acl_nfs4(vnode_t *vp, kauth_cred_t cred, uid_t file_uid,
   1122     gid_t file_gid, mode_t file_mode, struct acl *aclp, accmode_t accmode)
   1123 {
   1124 	int denied, explicitly_denied, access_mask, is_directory,
   1125 	    must_be_owner = 0;
   1126 	file_mode = 0;
   1127 
   1128 	KASSERT((accmode & ~(VEXEC | VWRITE | VREAD | VADMIN | VAPPEND |
   1129 	    VEXPLICIT_DENY | VREAD_NAMED_ATTRS | VWRITE_NAMED_ATTRS |
   1130 	    VDELETE_CHILD | VREAD_ATTRIBUTES | VWRITE_ATTRIBUTES | VDELETE |
   1131 	    VREAD_ACL | VWRITE_ACL | VWRITE_OWNER | VSYNCHRONIZE)) == 0);
   1132 	KASSERT((accmode & VAPPEND) == 0 || (accmode & VWRITE));
   1133 
   1134 	if (accmode & VADMIN)
   1135 		must_be_owner = 1;
   1136 
   1137 	/*
   1138 	 * Ignore VSYNCHRONIZE permission.
   1139 	 */
   1140 	accmode &= ~VSYNCHRONIZE;
   1141 
   1142 	access_mask = _access_mask_from_accmode(accmode);
   1143 
   1144 	if (vp && vp->v_type == VDIR)
   1145 		is_directory = 1;
   1146 	else
   1147 		is_directory = 0;
   1148 
   1149 	/*
   1150 	 * File owner is always allowed to read and write the ACL
   1151 	 * and basic attributes.  This is to prevent a situation
   1152 	 * where user would change ACL in a way that prevents him
   1153 	 * from undoing the change.
   1154 	 */
   1155 	if (kauth_cred_geteuid(cred) == file_uid)
   1156 		access_mask &= ~(ACL_READ_ACL | ACL_WRITE_ACL |
   1157 		    ACL_READ_ATTRIBUTES | ACL_WRITE_ATTRIBUTES);
   1158 
   1159 	/*
   1160 	 * Ignore append permission for regular files; use write
   1161 	 * permission instead.
   1162 	 */
   1163 	if (!is_directory && (access_mask & ACL_APPEND_DATA)) {
   1164 		access_mask &= ~ACL_APPEND_DATA;
   1165 		access_mask |= ACL_WRITE_DATA;
   1166 	}
   1167 
   1168 	denied = _acl_denies(aclp, access_mask, cred, file_uid, file_gid,
   1169 	    &explicitly_denied);
   1170 
   1171 	if (must_be_owner) {
   1172 		if (kauth_cred_geteuid(cred) != file_uid)
   1173 			denied = EPERM;
   1174 	}
   1175 
   1176 	/*
   1177 	 * For VEXEC, ensure that at least one execute bit is set for
   1178 	 * non-directories. We have to check the mode here to stay
   1179 	 * consistent with execve(2). See the test in
   1180 	 * exec_check_permissions().
   1181 	 */
   1182 	__acl_nfs4_sync_mode_from_acl(&file_mode, aclp);
   1183 	if (!denied && !is_directory && (accmode & VEXEC) &&
   1184 	    (file_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0)
   1185 		denied = EACCES;
   1186 
   1187 	if (!denied)
   1188 		return (0);
   1189 
   1190 	/*
   1191 	 * Access failed.  Iff it was not denied explicitly and
   1192 	 * VEXPLICIT_DENY flag was specified, allow access.
   1193 	 */
   1194 	if ((accmode & VEXPLICIT_DENY) && explicitly_denied == 0)
   1195 		return (0);
   1196 
   1197 	accmode &= ~VEXPLICIT_DENY;
   1198 
   1199 	if (accmode & (VADMIN_PERMS | VDELETE_CHILD | VDELETE))
   1200 		denied = EPERM;
   1201 	else
   1202 		denied = EACCES;
   1203 
   1204 	return (denied);
   1205 }
   1206 
   1207 /*
   1208  * Common routine to check if chmod() is allowed.
   1209  *
   1210  * Policy:
   1211  *   - You must own the file, and
   1212  *     - You must not set the "sticky" bit (meaningless, see chmod(2))
   1213  *     - You must be a member of the group if you're trying to set the
   1214  *	 SGIDf bit
   1215  *
   1216  * vp - vnode of the file-system object
   1217  * cred - credentials of the invoker
   1218  * cur_uid, cur_gid - current uid/gid of the file-system object
   1219  * new_mode - new mode for the file-system object
   1220  *
   1221  * Returns 0 if the change is allowed, or an error value otherwise.
   1222  */
   1223 int
   1224 genfs_can_chmod(vnode_t *vp, kauth_cred_t cred, uid_t cur_uid,
   1225     gid_t cur_gid, mode_t new_mode)
   1226 {
   1227 	int error;
   1228 
   1229 	/*
   1230 	 * To modify the permissions on a file, must possess VADMIN
   1231 	 * for that file.
   1232 	 */
   1233 	if ((error = VOP_ACCESSX(vp, VWRITE_ACL, cred)) != 0)
   1234 		return (error);
   1235 
   1236 	/*
   1237 	 * Unprivileged users can't set the sticky bit on files.
   1238 	 */
   1239 	if ((vp->v_type != VDIR) && (new_mode & S_ISTXT))
   1240 		return (EFTYPE);
   1241 
   1242 	/*
   1243 	 * If the invoker is trying to set the SGID bit on the file,
   1244 	 * check group membership.
   1245 	 */
   1246 	if (new_mode & S_ISGID) {
   1247 		int ismember;
   1248 
   1249 		error = kauth_cred_ismember_gid(cred, cur_gid,
   1250 		    &ismember);
   1251 		if (error || !ismember)
   1252 			return (EPERM);
   1253 	}
   1254 
   1255 	/*
   1256 	 * Deny setting setuid if we are not the file owner.
   1257 	 */
   1258 	if ((new_mode & S_ISUID) && cur_uid != kauth_cred_geteuid(cred))
   1259 		return (EPERM);
   1260 
   1261 	return (0);
   1262 }
   1263 
   1264 /*
   1265  * Common routine to check if chown() is allowed.
   1266  *
   1267  * Policy:
   1268  *   - You must own the file, and
   1269  *     - You must not try to change ownership, and
   1270  *     - You must be member of the new group
   1271  *
   1272  * vp - vnode
   1273  * cred - credentials of the invoker
   1274  * cur_uid, cur_gid - current uid/gid of the file-system object
   1275  * new_uid, new_gid - target uid/gid of the file-system object
   1276  *
   1277  * Returns 0 if the change is allowed, or an error value otherwise.
   1278  */
   1279 int
   1280 genfs_can_chown(vnode_t *vp, kauth_cred_t cred, uid_t cur_uid,
   1281     gid_t cur_gid, uid_t new_uid, gid_t new_gid)
   1282 {
   1283 	int error, ismember;
   1284 
   1285 	/*
   1286 	 * To modify the ownership of a file, must possess VADMIN for that
   1287 	 * file.
   1288 	 */
   1289 	if ((error = VOP_ACCESSX(vp, VWRITE_OWNER, cred)) != 0)
   1290 		return (error);
   1291 
   1292 	/*
   1293 	 * You can only change ownership of a file if:
   1294 	 * You own the file and...
   1295 	 */
   1296 	if (kauth_cred_geteuid(cred) == cur_uid) {
   1297 		/*
   1298 		 * You don't try to change ownership, and...
   1299 		 */
   1300 		if (new_uid != cur_uid)
   1301 			return (EPERM);
   1302 
   1303 		/*
   1304 		 * You don't try to change group (no-op), or...
   1305 		 */
   1306 		if (new_gid == cur_gid)
   1307 			return (0);
   1308 
   1309 		/*
   1310 		 * Your effective gid is the new gid, or...
   1311 		 */
   1312 		if (kauth_cred_getegid(cred) == new_gid)
   1313 			return (0);
   1314 
   1315 		/*
   1316 		 * The new gid is one you're a member of.
   1317 		 */
   1318 		ismember = 0;
   1319 		error = kauth_cred_ismember_gid(cred, new_gid,
   1320 		    &ismember);
   1321 		if (!error && ismember)
   1322 			return (0);
   1323 	}
   1324 
   1325 	return (EPERM);
   1326 }
   1327 
   1328 int
   1329 genfs_can_chtimes(vnode_t *vp, kauth_cred_t cred, uid_t owner_uid,
   1330     u_int vaflags)
   1331 {
   1332 	int error;
   1333 	/*
   1334 	 * Grant permission if the caller is the owner of the file, or
   1335 	 * the super-user, or has ACL_WRITE_ATTRIBUTES permission on
   1336 	 * on the file.	 If the time pointer is null, then write
   1337 	 * permission on the file is also sufficient.
   1338 	 *
   1339 	 * From NFSv4.1, draft 21, 6.2.1.3.1, Discussion of Mask Attributes:
   1340 	 * A user having ACL_WRITE_DATA or ACL_WRITE_ATTRIBUTES
   1341 	 * will be allowed to set the times [..] to the current
   1342 	 * server time.
   1343 	 */
   1344 	if ((error = VOP_ACCESSX(vp, VWRITE_ATTRIBUTES, cred)) != 0)
   1345 		return (vaflags & VA_UTIMES_NULL) == 0 ? EPERM : EACCES;
   1346 
   1347 	/* Must be owner, or... */
   1348 	if (kauth_cred_geteuid(cred) == owner_uid)
   1349 		return (0);
   1350 
   1351 	/* set the times to the current time, and... */
   1352 	if ((vaflags & VA_UTIMES_NULL) == 0)
   1353 		return (EPERM);
   1354 
   1355 	/* have write access. */
   1356 	error = VOP_ACCESS(vp, VWRITE, cred);
   1357 	if (error)
   1358 		return (error);
   1359 
   1360 	return (0);
   1361 }
   1362 
   1363 /*
   1364  * Common routine to check if chflags() is allowed.
   1365  *
   1366  * Policy:
   1367  *   - You must own the file, and
   1368  *   - You must not change system flags, and
   1369  *   - You must not change flags on character/block devices.
   1370  *
   1371  * vp - vnode
   1372  * cred - credentials of the invoker
   1373  * owner_uid - uid of the file-system object
   1374  * changing_sysflags - true if the invoker wants to change system flags
   1375  */
   1376 int
   1377 genfs_can_chflags(vnode_t *vp, kauth_cred_t cred,
   1378      uid_t owner_uid, bool changing_sysflags)
   1379 {
   1380 
   1381 	/* The user must own the file. */
   1382 	if (kauth_cred_geteuid(cred) != owner_uid) {
   1383 		return EPERM;
   1384 	}
   1385 
   1386 	if (changing_sysflags) {
   1387 		return EPERM;
   1388 	}
   1389 
   1390 	/*
   1391 	 * Unprivileged users cannot change the flags on devices, even if they
   1392 	 * own them.
   1393 	 */
   1394 	if (vp->v_type == VCHR || vp->v_type == VBLK) {
   1395 		return EPERM;
   1396 	}
   1397 
   1398 	return 0;
   1399 }
   1400 
   1401 /*
   1402  * Common "sticky" policy.
   1403  *
   1404  * When a directory is "sticky" (as determined by the caller), this
   1405  * function may help implementing the following policy:
   1406  * - Renaming a file in it is only possible if the user owns the directory
   1407  *   or the file being renamed.
   1408  * - Deleting a file from it is only possible if the user owns the
   1409  *   directory or the file being deleted.
   1410  */
   1411 int
   1412 genfs_can_sticky(vnode_t *vp, kauth_cred_t cred, uid_t dir_uid, uid_t file_uid)
   1413 {
   1414 	if (kauth_cred_geteuid(cred) != dir_uid &&
   1415 	    kauth_cred_geteuid(cred) != file_uid)
   1416 		return EPERM;
   1417 
   1418 	return 0;
   1419 }
   1420 
   1421 int
   1422 genfs_can_extattr(vnode_t *vp, kauth_cred_t cred, accmode_t accmode,
   1423     int attrnamespace)
   1424 {
   1425 	/*
   1426 	 * Kernel-invoked always succeeds.
   1427 	 */
   1428 	if (cred == NOCRED)
   1429 		return 0;
   1430 
   1431 	switch (attrnamespace) {
   1432 	case EXTATTR_NAMESPACE_SYSTEM:
   1433 		return kauth_authorize_system(cred, KAUTH_SYSTEM_FS_EXTATTR,
   1434 		    0, vp->v_mount, NULL, NULL);
   1435 	case EXTATTR_NAMESPACE_USER:
   1436 		return VOP_ACCESS(vp, accmode, cred);
   1437 	default:
   1438 		return EPERM;
   1439 	}
   1440 }
   1441 
   1442 int
   1443 genfs_access(void *v)
   1444 {
   1445 	struct vop_access_args *ap = v;
   1446 
   1447 	KASSERT((ap->a_accmode & ~(VEXEC | VWRITE | VREAD | VADMIN |
   1448 	    VAPPEND)) == 0);
   1449 
   1450 	return VOP_ACCESSX(ap->a_vp, ap->a_accmode, ap->a_cred);
   1451 }
   1452 
   1453 int
   1454 genfs_accessx(void *v)
   1455 {
   1456 	struct vop_accessx_args *ap = v;
   1457 	int error;
   1458 	accmode_t accmode = ap->a_accmode;
   1459 	error = vfs_unixify_accmode(&accmode);
   1460 	if (error != 0)
   1461 		return error;
   1462 
   1463 	if (accmode == 0)
   1464 		return 0;
   1465 
   1466 	return VOP_ACCESS(ap->a_vp, accmode, ap->a_cred);
   1467 }
   1468 
   1469 /*
   1470  * genfs_pathconf:
   1471  *
   1472  * Standard implementation of POSIX pathconf, to get information about limits
   1473  * for a filesystem.
   1474  * Override per filesystem for the case where the filesystem has smaller
   1475  * limits.
   1476  */
   1477 int
   1478 genfs_pathconf(void *v)
   1479 {
   1480 	struct vop_pathconf_args *ap = v;
   1481 
   1482 	switch (ap->a_name) {
   1483 	case _PC_PATH_MAX:
   1484 		*ap->a_retval = PATH_MAX;
   1485 		return 0;
   1486 	case _PC_ACL_EXTENDED:
   1487 	case _PC_ACL_NFS4:
   1488 		*ap->a_retval = 0;
   1489 		return 0;
   1490 	default:
   1491 		return EINVAL;
   1492 	}
   1493 }
   1494