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