Home | History | Annotate | Line # | Download | only in genfs
      1 /*	$NetBSD: genfs_rename.c,v 1.7 2021/10/20 13:29:06 thorpej Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2012 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Taylor R Campbell.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 /*
     33  * Generic rename abstraction.
     34  *
     35  * Rename is unbelievably hairy.  Try to use this if you can --
     36  * otherwise you are practically guaranteed to get it wrong.
     37  */
     38 
     39 #include <sys/cdefs.h>
     40 __KERNEL_RCSID(0, "$NetBSD: genfs_rename.c,v 1.7 2021/10/20 13:29:06 thorpej Exp $");
     41 
     42 #include <sys/param.h>
     43 #include <sys/kauth.h>
     44 #include <sys/mount.h>
     45 #include <sys/namei.h>
     46 #include <sys/stat.h>
     47 #include <sys/vnode.h>
     48 #include <sys/types.h>
     49 
     50 #include <miscfs/genfs/genfs.h>
     51 
     52 /*
     53  * Sample copypasta for implementing VOP_RENAME via genfs_rename.
     54  * Don't change this template without carefully considering whether
     55  * every other file system that already uses it needs to change too.
     56  * That way, once we have changed all the file systems to use it, we
     57  * can easily replace mumblefs_rename by mumblefs_sane_rename and
     58  * eliminate the insane API altogether.
     59  */
     60 
     61 /* begin sample copypasta */
     62 #if 0
     63 
     64 static const struct genfs_rename_ops mumblefs_genfs_rename_ops;
     65 
     66 /*
     67  * mumblefs_sane_rename: The hairiest vop, with the saner API.
     68  *
     69  * Arguments:
     70  *
     71  * . fdvp (from directory vnode),
     72  * . fcnp (from component name),
     73  * . tdvp (to directory vnode),
     74  * . tcnp (to component name),
     75  * . cred (credentials structure), and
     76  * . posixly_correct (flag for behaviour if target & source link same file).
     77  *
     78  * fdvp and tdvp may be the same, and must be referenced and unlocked.
     79  */
     80 static int
     81 mumblefs_sane_rename(
     82     struct vnode *fdvp, struct componentname *fcnp,
     83     struct vnode *tdvp, struct componentname *tcnp,
     84     kauth_cred_t cred, bool posixly_correct)
     85 {
     86 	struct mumblefs_lookup_results fulr, tulr;
     87 
     88 	return genfs_sane_rename(&mumblefs_genfs_rename_ops,
     89 	    fdvp, fcnp, &fulr, tdvp, tcnp, &tulr,
     90 	    cred, posixly_correct);
     91 }
     92 
     93 /*
     94  * mumblefs_rename: The hairiest vop, with the insanest API.  Defer to
     95  * genfs_insane_rename immediately.
     96  */
     97 int
     98 mumblefs_rename(void *v)
     99 {
    100 
    101 	return genfs_insane_rename(v, &mumblefs_sane_rename);
    102 }
    103 
    104 #endif
    105 /* end sample copypasta */
    106 
    107 /*
    108  * Forward declarations
    109  */
    110 
    111 static int genfs_rename_enter(const struct genfs_rename_ops *, struct mount *,
    112     kauth_cred_t,
    113     struct vnode *, struct componentname *, void *, struct vnode **,
    114     struct vnode *, struct componentname *, void *, struct vnode **);
    115 static int genfs_rename_enter_common(const struct genfs_rename_ops *,
    116     struct mount *, kauth_cred_t, struct vnode *,
    117     struct componentname *, void *, struct vnode **,
    118     struct componentname *, void *, struct vnode **);
    119 static int genfs_rename_enter_separate(const struct genfs_rename_ops *,
    120     struct mount *, kauth_cred_t,
    121     struct vnode *, struct componentname *, void *, struct vnode **,
    122     struct vnode *, struct componentname *, void *, struct vnode **);
    123 static int genfs_rename_lock(const struct genfs_rename_ops *, struct mount *,
    124     kauth_cred_t, int, int, int,
    125     struct vnode *, struct componentname *, bool, void *, struct vnode **,
    126     struct vnode *, struct componentname *, bool, void *, struct vnode **);
    127 static void genfs_rename_exit(const struct genfs_rename_ops *, struct mount *,
    128     struct vnode *, struct vnode *,
    129     struct vnode *, struct vnode *);
    130 static int genfs_rename_remove(const struct genfs_rename_ops *, struct mount *,
    131     kauth_cred_t,
    132     struct vnode *, struct componentname *, void *, struct vnode *, nlink_t *);
    133 
    134 /*
    135  * genfs_insane_rename: Generic implementation of the insane API for
    136  * the rename vop.
    137  *
    138  * Arguments:
    139  *
    140  * . fdvp (from directory vnode),
    141  * . fvp (from vnode),
    142  * . fcnp (from component name),
    143  * . tdvp (to directory vnode),
    144  * . tvp (to vnode, or NULL), and
    145  * . tcnp (to component name).
    146  *
    147  * Any pair of vnode parameters may have the same vnode.
    148  *
    149  * On entry,
    150  *
    151  * . fdvp, fvp, tdvp, and tvp are referenced,
    152  * . fdvp and fvp are unlocked, and
    153  * . tdvp and tvp (if nonnull) are locked.
    154  *
    155  * On exit,
    156  *
    157  * . fdvp, fvp, tdvp, and tvp (if nonnull) are unreferenced, and
    158  * . tdvp and tvp (if nonnull) are unlocked.
    159  */
    160 int
    161 genfs_insane_rename(void *v,
    162     int (*sane_rename)(struct vnode *fdvp, struct componentname *fcnp,
    163 	struct vnode *tdvp, struct componentname *tcnp,
    164 	kauth_cred_t cred, bool posixly_correct))
    165 {
    166 	struct vop_rename_args /* {
    167 		struct vnode *a_fdvp;
    168 		struct vnode *a_fvp;
    169 		struct componentname *a_fcnp;
    170 		struct vnode *a_tdvp;
    171 		struct vnode *a_tvp;
    172 		struct componentname *a_tcnp;
    173 	} */ *ap = v;
    174 	struct vnode *fdvp = ap->a_fdvp;
    175 	struct vnode *fvp = ap->a_fvp;
    176 	struct componentname *fcnp = ap->a_fcnp;
    177 	struct vnode *tdvp = ap->a_tdvp;
    178 	struct vnode *tvp = ap->a_tvp;
    179 	struct componentname *tcnp = ap->a_tcnp;
    180 	kauth_cred_t cred;
    181 	int error;
    182 
    183 	KASSERT(fdvp != NULL);
    184 	KASSERT(fvp != NULL);
    185 	KASSERT(fcnp != NULL);
    186 	KASSERT(fcnp->cn_nameptr != NULL);
    187 	KASSERT(tdvp != NULL);
    188 	KASSERT(tcnp != NULL);
    189 	KASSERT(fcnp->cn_nameptr != NULL);
    190 	/* KASSERT(VOP_ISLOCKED(fdvp) != LK_EXCLUSIVE); */
    191 	/* KASSERT(VOP_ISLOCKED(fvp) != LK_EXCLUSIVE); */
    192 	KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
    193 	KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
    194 	KASSERT(fdvp->v_type == VDIR);
    195 	KASSERT(tdvp->v_type == VDIR);
    196 
    197 	cred = fcnp->cn_cred;
    198 
    199 	/*
    200 	 * XXX Want a better equality test.  `tcnp->cn_cred == cred'
    201 	 * hoses p2k because puffs transmits the creds separately and
    202 	 * allocates distinct but equivalent structures for them.
    203 	 */
    204 	KASSERT(kauth_cred_uidmatch(cred, tcnp->cn_cred));
    205 
    206 	/*
    207 	 * Sanitize our world from the VFS insanity.  Unlock the target
    208 	 * directory and node, which are locked.  Release the children,
    209 	 * which are referenced, since we'll be looking them up again
    210 	 * later.
    211 	 */
    212 
    213 	VOP_UNLOCK(tdvp);
    214 	if ((tvp != NULL) && (tvp != tdvp))
    215 		VOP_UNLOCK(tvp);
    216 
    217 	vrele(fvp);
    218 	if (tvp != NULL)
    219 		vrele(tvp);
    220 
    221 	error = (*sane_rename)(fdvp, fcnp, tdvp, tcnp, cred, false);
    222 
    223 	/*
    224 	 * All done, whether with success or failure.  Release the
    225 	 * directory nodes now, as the caller expects from the VFS
    226 	 * protocol.
    227 	 */
    228 	vrele(fdvp);
    229 	vrele(tdvp);
    230 
    231 	return error;
    232 }
    233 
    234 /*
    235  * genfs_sane_rename: Generic implementation of the saner API for the
    236  * rename vop.  Handles ancestry checks, locking, and permissions
    237  * checks.  Caller is responsible for implementing the genfs rename
    238  * operations.
    239  *
    240  * fdvp and tdvp must be referenced and unlocked.
    241  */
    242 int
    243 genfs_sane_rename(const struct genfs_rename_ops *ops,
    244     struct vnode *fdvp, struct componentname *fcnp, void *fde,
    245     struct vnode *tdvp, struct componentname *tcnp, void *tde,
    246     kauth_cred_t cred, bool posixly_correct)
    247 {
    248 	struct mount *mp;
    249 	struct vnode *fvp = NULL, *tvp = NULL;
    250 	nlink_t tvp_new_nlink = 0;
    251 	int error;
    252 
    253 	KASSERT(ops != NULL);
    254 	KASSERT(fdvp != NULL);
    255 	KASSERT(fcnp != NULL);
    256 	KASSERT(tdvp != NULL);
    257 	KASSERT(tcnp != NULL);
    258 	/* KASSERT(VOP_ISLOCKED(fdvp) != LK_EXCLUSIVE); */
    259 	/* KASSERT(VOP_ISLOCKED(tdvp) != LK_EXCLUSIVE); */
    260 	KASSERT(fdvp->v_type == VDIR);
    261 	KASSERT(tdvp->v_type == VDIR);
    262 	KASSERT(fdvp->v_mount == tdvp->v_mount);
    263 	KASSERT(fcnp != tcnp);
    264 	KASSERT(fcnp->cn_nameiop == DELETE);
    265 	KASSERT(tcnp->cn_nameiop == RENAME);
    266 
    267         /* XXX Want a better equality test.  */
    268 	KASSERT(kauth_cred_uidmatch(cred, fcnp->cn_cred));
    269 	KASSERT(kauth_cred_uidmatch(cred, tcnp->cn_cred));
    270 
    271 	mp = fdvp->v_mount;
    272 	KASSERT(mp != NULL);
    273 	KASSERT(mp == tdvp->v_mount);
    274 	/* XXX How can we be sure this stays true?  */
    275 	KASSERT((mp->mnt_flag & MNT_RDONLY) == 0);
    276 
    277 	/* Reject rename("x/..", ...) and rename(..., "x/..") early.  */
    278 	if ((fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT)
    279 		return EINVAL;	/* XXX EISDIR?  */
    280 
    281 	error = genfs_rename_enter(ops, mp, cred,
    282 	    fdvp, fcnp, fde, &fvp,
    283 	    tdvp, tcnp, tde, &tvp);
    284 	if (error)
    285 		return error;
    286 
    287 	/*
    288 	 * Check that everything is locked and looks right.
    289 	 */
    290 	KASSERT(fvp != NULL);
    291 	KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
    292 	KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
    293 	KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
    294 	KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
    295 
    296 	/*
    297 	 * If the source and destination are the same object, we need
    298 	 * only at most delete the source entry.  We are guaranteed at
    299 	 * this point that the entries are distinct.
    300 	 */
    301 	if (fvp == tvp) {
    302 		KASSERT(tvp != NULL);
    303 		if (fvp->v_type == VDIR)
    304 			/* XXX This shouldn't be possible.  */
    305 			error = EINVAL;
    306 		else if (posixly_correct)
    307 			/* POSIX sez to leave them alone.  */
    308 			error = 0;
    309 		else if ((fdvp == tdvp) &&
    310 		    (fcnp->cn_namelen == tcnp->cn_namelen) &&
    311 		    (memcmp(fcnp->cn_nameptr, tcnp->cn_nameptr,
    312 			fcnp->cn_namelen) == 0))
    313 			/* Renaming an entry over itself does nothing.  */
    314 			error = 0;
    315 		else {
    316 			/* XXX Can't use VOP_REMOVE because of locking.  */
    317 			error = genfs_rename_remove(ops, mp, cred,
    318 			    fdvp, fcnp, fde, fvp, &tvp_new_nlink);
    319 			VN_KNOTE(fdvp, NOTE_WRITE);
    320 			VN_KNOTE(fvp,
    321 			    tvp_new_nlink == 0 ? NOTE_DELETE : NOTE_LINK);
    322 		}
    323 		goto out;
    324 	}
    325 	KASSERT(fvp != tvp);
    326 	KASSERT((fdvp != tdvp) ||
    327 	    (fcnp->cn_namelen != tcnp->cn_namelen) ||
    328 	    (memcmp(fcnp->cn_nameptr, tcnp->cn_nameptr, fcnp->cn_namelen)
    329 		!= 0));
    330 
    331 	/*
    332 	 * If the target exists, refuse to rename a directory over a
    333 	 * non-directory or vice versa, or to clobber a non-empty
    334 	 * directory.
    335 	 */
    336 	if (tvp != NULL) {
    337 		if (fvp->v_type == VDIR && tvp->v_type == VDIR)
    338 			error =
    339 			    (ops->gro_directory_empty_p(mp, cred, tvp, tdvp)?
    340 				0 : ENOTEMPTY);
    341 		else if (fvp->v_type == VDIR && tvp->v_type != VDIR)
    342 			error = ENOTDIR;
    343 		else if (fvp->v_type != VDIR && tvp->v_type == VDIR)
    344 			error = EISDIR;
    345 		else
    346 			error = 0;
    347 		if (error)
    348 			goto out;
    349 		KASSERT((fvp->v_type == VDIR) == (tvp->v_type == VDIR));
    350 	}
    351 
    352 	/*
    353 	 * Authorize the rename.
    354 	 */
    355 	error = ops->gro_rename_check_possible(mp, fdvp, fvp, tdvp, tvp);
    356 	if (error)
    357 		goto out;
    358 	error = ops->gro_rename_check_permitted(mp, cred, fdvp, fvp, tdvp, tvp);
    359 	error = kauth_authorize_vnode(cred, KAUTH_VNODE_DELETE, fvp, fdvp,
    360 	    error);
    361 	error = kauth_authorize_vnode(cred, KAUTH_VNODE_RENAME, tvp, tdvp,
    362 	    error);
    363 	if (error)
    364 		goto out;
    365 
    366 	/*
    367 	 * Everything is hunky-dory.  Shuffle the directory entries.
    368 	 */
    369 	error = ops->gro_rename(mp, cred,
    370 	    fdvp, fcnp, fde, fvp,
    371 	    tdvp, tcnp, tde, tvp,
    372 	    &tvp_new_nlink);
    373 	if (error)
    374 		goto out;
    375 
    376 	/* Success!  */
    377 	genfs_rename_knote(fdvp, fvp, tdvp, tvp, tvp_new_nlink);
    378 
    379 out:
    380 	genfs_rename_exit(ops, mp, fdvp, fvp, tdvp, tvp);
    381 	return error;
    382 }
    383 
    384 /*
    385  * genfs_rename_knote: Note events about the various vnodes in a
    386  * rename.  To be called by gro_rename on success.  The only pair of
    387  * vnodes that may be identical is {fdvp, tdvp}.  tvp_new_nlink is
    388  * the resulting link count of tvp.
    389  */
    390 void
    391 genfs_rename_knote(struct vnode *fdvp, struct vnode *fvp,
    392     struct vnode *tdvp, struct vnode *tvp, nlink_t tvp_new_nlink)
    393 {
    394 	long fdvp_events, tdvp_events;
    395 	bool directory_p, reparent_p, replaced_p;
    396 
    397 	KASSERT(fdvp != NULL);
    398 	KASSERT(fvp != NULL);
    399 	KASSERT(tdvp != NULL);
    400 	KASSERT(fdvp != fvp);
    401 	KASSERT(fdvp != tvp);
    402 	KASSERT(tdvp != fvp);
    403 	KASSERT(tdvp != tvp);
    404 	KASSERT(fvp != tvp);
    405 	KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
    406 	KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
    407 	KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
    408 	KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
    409 
    410 	directory_p = (fvp->v_type == VDIR);
    411 	reparent_p = (fdvp != tdvp);
    412 	replaced_p = (tvp != NULL);
    413 
    414 	KASSERT((tvp == NULL) || (directory_p == (tvp->v_type == VDIR)));
    415 
    416 	fdvp_events = NOTE_WRITE;
    417 	if (directory_p && reparent_p)
    418 		fdvp_events |= NOTE_LINK;
    419 	VN_KNOTE(fdvp, fdvp_events);
    420 
    421 	VN_KNOTE(fvp, NOTE_RENAME);
    422 
    423 	if (reparent_p) {
    424 		tdvp_events = NOTE_WRITE;
    425 		if (!replaced_p) {
    426 			tdvp_events |= NOTE_EXTEND;
    427 			if (directory_p)
    428 				tdvp_events |= NOTE_LINK;
    429 		}
    430 		VN_KNOTE(tdvp, tdvp_events);
    431 	}
    432 
    433 	if (replaced_p)
    434 		VN_KNOTE(tvp, (tvp_new_nlink == 0 ? NOTE_DELETE : NOTE_LINK));
    435 }
    436 
    437 /*
    438  * genfs_rename_cache_purge: Purge the name cache.  To be called by
    439  * gro_rename on success.  The only pair of vnodes that may be
    440  * identical is {fdvp, tdvp}.
    441  */
    442 void
    443 genfs_rename_cache_purge(struct vnode *fdvp, struct vnode *fvp,
    444     struct vnode *tdvp, struct vnode *tvp)
    445 {
    446 
    447 	KASSERT(fdvp != NULL);
    448 	KASSERT(fvp != NULL);
    449 	KASSERT(tdvp != NULL);
    450 	KASSERT(fdvp != fvp);
    451 	KASSERT(fdvp != tvp);
    452 	KASSERT(tdvp != fvp);
    453 	KASSERT(tdvp != tvp);
    454 	KASSERT(fvp != tvp);
    455 	KASSERT(fdvp->v_type == VDIR);
    456 	KASSERT(tdvp->v_type == VDIR);
    457 
    458 	/*
    459 	 * XXX What actually needs to be purged?
    460 	 */
    461 
    462 	cache_purge(fdvp);
    463 
    464 	if (fvp->v_type == VDIR)
    465 		cache_purge(fvp);
    466 
    467 	if (tdvp != fdvp)
    468 		cache_purge(tdvp);
    469 
    470 	if ((tvp != NULL) && (tvp->v_type == VDIR))
    471 		cache_purge(tvp);
    472 }
    473 
    474 /*
    475  * genfs_rename_enter: Look up fcnp in fdvp, and store the lookup
    476  * results in *fde_ret and the associated vnode in *fvp_ret; fail if
    477  * not found.  Look up tcnp in tdvp, and store the lookup results in
    478  * *tde_ret and the associated vnode in *tvp_ret; store null instead if
    479  * not found.  Fail if anything has been mounted on any of the nodes
    480  * involved.
    481  *
    482  * fdvp and tdvp must be referenced.
    483  *
    484  * On entry, nothing is locked.
    485  *
    486  * On success, everything is locked, and *fvp_ret, and *tvp_ret if
    487  * nonnull, are referenced.  The only pairs of vnodes that may be
    488  * identical are {fdvp, tdvp} and {fvp, tvp}.
    489  *
    490  * On failure, everything remains as was.
    491  *
    492  * Locking everything including the source and target nodes is
    493  * necessary to make sure that, e.g., link count updates are OK.  The
    494  * locking order is, in general, ancestor-first, matching the order you
    495  * need to use to look up a descendant anyway.
    496  */
    497 static int
    498 genfs_rename_enter(const struct genfs_rename_ops *ops,
    499     struct mount *mp, kauth_cred_t cred,
    500     struct vnode *fdvp, struct componentname *fcnp,
    501     void *fde_ret, struct vnode **fvp_ret,
    502     struct vnode *tdvp, struct componentname *tcnp,
    503     void *tde_ret, struct vnode **tvp_ret)
    504 {
    505 	int error;
    506 
    507 	KASSERT(mp != NULL);
    508 	KASSERT(fdvp != NULL);
    509 	KASSERT(fcnp != NULL);
    510 	KASSERT(fvp_ret != NULL);
    511 	KASSERT(tdvp != NULL);
    512 	KASSERT(tcnp != NULL);
    513 	KASSERT(tvp_ret != NULL);
    514 	KASSERT(fvp_ret != tvp_ret);
    515 	KASSERT(fdvp->v_type == VDIR);
    516 	KASSERT(tdvp->v_type == VDIR);
    517 	KASSERT(fdvp->v_mount == mp);
    518 	KASSERT(tdvp->v_mount == mp);
    519 
    520 	if (fdvp == tdvp)
    521 		error = genfs_rename_enter_common(ops, mp, cred, fdvp,
    522 		    fcnp, fde_ret, fvp_ret,
    523 		    tcnp, tde_ret, tvp_ret);
    524 	else
    525 		error = genfs_rename_enter_separate(ops, mp, cred,
    526 		    fdvp, fcnp, fde_ret, fvp_ret,
    527 		    tdvp, tcnp, tde_ret, tvp_ret);
    528 
    529 	if (error)
    530 		return error;
    531 
    532 	KASSERT(*fvp_ret != NULL);
    533 	KASSERT(VOP_ISLOCKED(*fvp_ret) == LK_EXCLUSIVE);
    534 	KASSERT((*tvp_ret == NULL) || (VOP_ISLOCKED(*tvp_ret) == LK_EXCLUSIVE));
    535 	KASSERT(*fvp_ret != fdvp);
    536 	KASSERT(*fvp_ret != tdvp);
    537 	KASSERT(*tvp_ret != fdvp);
    538 	KASSERT(*tvp_ret != tdvp);
    539 	return 0;
    540 }
    541 
    542 /*
    543  * genfs_rename_enter_common: Lock and look up with a common
    544  * source/target directory.
    545  */
    546 static int
    547 genfs_rename_enter_common(const struct genfs_rename_ops *ops,
    548     struct mount *mp, kauth_cred_t cred, struct vnode *dvp,
    549     struct componentname *fcnp,
    550     void *fde_ret, struct vnode **fvp_ret,
    551     struct componentname *tcnp,
    552     void *tde_ret, struct vnode **tvp_ret)
    553 {
    554 	struct vnode *fvp, *tvp;
    555 	int error;
    556 
    557 	KASSERT(ops != NULL);
    558 	KASSERT(mp != NULL);
    559 	KASSERT(dvp != NULL);
    560 	KASSERT(fcnp != NULL);
    561 	KASSERT(fvp_ret != NULL);
    562 	KASSERT(tcnp != NULL);
    563 	KASSERT(tvp_ret != NULL);
    564 	KASSERT(dvp->v_type == VDIR);
    565 	KASSERT(dvp->v_mount == mp);
    566 
    567 	error = ops->gro_lock_directory(mp, dvp);
    568 	if (error)
    569 		goto fail0;
    570 
    571 	/* Did we lose a race with mount?  */
    572 	if (dvp->v_mountedhere != NULL) {
    573 		error = EBUSY;
    574 		goto fail1;
    575 	}
    576 
    577 	KASSERT(fcnp->cn_nameiop == DELETE);
    578 	error = ops->gro_lookup(mp, dvp, fcnp, fde_ret, &fvp);
    579 	if (error)
    580 		goto fail1;
    581 
    582 	KASSERT(fvp != NULL);
    583 
    584 	/* Refuse to rename `.'.  */
    585 	if (fvp == dvp) {
    586 		error = EINVAL;
    587 		goto fail2;
    588 	}
    589 	KASSERT(fvp != dvp);
    590 
    591 	KASSERT(tcnp->cn_nameiop == RENAME);
    592 	error = ops->gro_lookup(mp, dvp, tcnp, tde_ret, &tvp);
    593 	if (error == ENOENT) {
    594 		tvp = NULL;
    595 	} else if (error) {
    596 		goto fail2;
    597 	} else {
    598 		KASSERT(tvp != NULL);
    599 
    600 		/* Refuse to rename over `.'.  */
    601 		if (tvp == dvp) {
    602 			error = EISDIR; /* XXX EINVAL?  */
    603 			goto fail2;
    604 		}
    605 	}
    606 	KASSERT(tvp != dvp);
    607 
    608 	/*
    609 	 * We've looked up both nodes.  Now lock them and check them.
    610 	 */
    611 
    612 	vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY);
    613 	KASSERT(fvp->v_mount == mp);
    614 	/* Refuse to rename a mount point.  */
    615 	if ((fvp->v_type == VDIR) && (fvp->v_mountedhere != NULL)) {
    616 		error = EBUSY;
    617 		goto fail3;
    618 	}
    619 
    620 	if ((tvp != NULL) && (tvp != fvp)) {
    621 		vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY);
    622 		KASSERT(tvp->v_mount == mp);
    623 		/* Refuse to rename over a mount point.  */
    624 		if ((tvp->v_type == VDIR) && (tvp->v_mountedhere != NULL)) {
    625 			error = EBUSY;
    626 			goto fail4;
    627 		}
    628 	}
    629 
    630 	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
    631 	KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
    632 	KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
    633 
    634 	*fvp_ret = fvp;
    635 	*tvp_ret = tvp;
    636 	return 0;
    637 
    638 fail4:	if ((tvp != NULL) && (tvp != fvp))
    639 		VOP_UNLOCK(tvp);
    640 fail3:	VOP_UNLOCK(fvp);
    641 	if (tvp != NULL)
    642 		vrele(tvp);
    643 fail2:	vrele(fvp);
    644 fail1:	VOP_UNLOCK(dvp);
    645 fail0:	return error;
    646 }
    647 
    648 /*
    649  * genfs_rename_enter_separate: Lock and look up with separate source
    650  * and target directories.
    651  */
    652 static int
    653 genfs_rename_enter_separate(const struct genfs_rename_ops *ops,
    654     struct mount *mp, kauth_cred_t cred,
    655     struct vnode *fdvp, struct componentname *fcnp,
    656     void *fde_ret, struct vnode **fvp_ret,
    657     struct vnode *tdvp, struct componentname *tcnp,
    658     void *tde_ret, struct vnode **tvp_ret)
    659 {
    660 	struct vnode *intermediate_node;
    661 	struct vnode *fvp, *tvp;
    662 	int error;
    663 
    664 	KASSERT(ops != NULL);
    665 	KASSERT(mp != NULL);
    666 	KASSERT(fdvp != NULL);
    667 	KASSERT(fcnp != NULL);
    668 	KASSERT(fvp_ret != NULL);
    669 	KASSERT(tdvp != NULL);
    670 	KASSERT(tcnp != NULL);
    671 	KASSERT(tvp_ret != NULL);
    672 	KASSERT(fdvp != tdvp);
    673 	KASSERT(fcnp != tcnp);
    674 	KASSERT(fcnp->cn_nameiop == DELETE);
    675 	KASSERT(tcnp->cn_nameiop == RENAME);
    676 	KASSERT(fvp_ret != tvp_ret);
    677 	KASSERT(fdvp->v_type == VDIR);
    678 	KASSERT(tdvp->v_type == VDIR);
    679 	KASSERT(fdvp->v_mount == mp);
    680 	KASSERT(tdvp->v_mount == mp);
    681 
    682 	error = ops->gro_genealogy(mp, cred, fdvp, tdvp, &intermediate_node);
    683 	if (error)
    684 		return error;
    685 
    686 	/*
    687 	 * intermediate_node == NULL means fdvp is not an ancestor of tdvp.
    688 	 */
    689 	if (intermediate_node == NULL)
    690 		error = genfs_rename_lock(ops, mp, cred,
    691 		    ENOTEMPTY, EISDIR, EINVAL,
    692 		    tdvp, tcnp, true, tde_ret, &tvp,
    693 		    fdvp, fcnp, false, fde_ret, &fvp);
    694 	else
    695 		error = genfs_rename_lock(ops, mp, cred,
    696 		    EINVAL, EISDIR, EINVAL,
    697 		    fdvp, fcnp, false, fde_ret, &fvp,
    698 		    tdvp, tcnp, true, tde_ret, &tvp);
    699 	if (error)
    700 		goto out;
    701 
    702 	KASSERT(fvp != NULL);
    703 
    704 	/*
    705 	 * Reject rename("foo/bar", "foo/bar/baz/quux/zot").
    706 	 */
    707 	if (fvp == intermediate_node) {
    708 		genfs_rename_exit(ops, mp, fdvp, fvp, tdvp, tvp);
    709 		error = EINVAL;
    710 		goto out;
    711 	}
    712 
    713 	*fvp_ret = fvp;
    714 	*tvp_ret = tvp;
    715 	error = 0;
    716 
    717 out:	if (intermediate_node != NULL)
    718 		vrele(intermediate_node);
    719 	return error;
    720 }
    721 
    722 /*
    723  * genfs_rename_lock: Lookup and lock it all.  The lock order is:
    724  *
    725  *	a_dvp -> a_vp -> b_dvp -> b_vp,
    726  *
    727  * except if a_vp is a nondirectory in which case the lock order is:
    728  *
    729  *	a_dvp -> b_dvp -> b_vp -> a_vp,
    730  *
    731  * which can't violate ancestor->descendant because a_vp has no
    732  * descendants in this case.  This edge case is necessary because some
    733  * file systems can only lookup/lock/unlock, and we can't hold a_vp
    734  * locked when we lookup/lock/unlock b_vp if they turn out to be the
    735  * same, and we can't find out that they're the same until after the
    736  * lookup.
    737  *
    738  * b_dvp must not be an ancestor of a_dvp, although a_dvp may be an
    739  * ancestor of b_dvp.
    740  *
    741  * Fail with overlap_error if node a is directory b.  Neither
    742  * componentname may be `.' or `..'.
    743  *
    744  * a_dvp and b_dvp must be referenced.
    745  *
    746  * On entry, a_dvp and b_dvp are unlocked.
    747  *
    748  * On success,
    749  * . a_dvp and b_dvp are locked,
    750  * . *a_dirent_ret is filled with a directory entry whose node is
    751  *     locked and referenced,
    752  * . *b_vp_ret is filled with the corresponding vnode,
    753  * . *b_dirent_ret is filled either with null or with a directory entry
    754  *     whose node is locked and referenced,
    755  * . *b_vp is filled either with null or with the corresponding vnode,
    756  *     and
    757  * . the only pair of vnodes that may be identical is a_vp and b_vp.
    758  *
    759  * On failure, a_dvp and b_dvp are left unlocked, and *a_dirent_ret,
    760  * *a_vp, *b_dirent_ret, and *b_vp are left alone.
    761  */
    762 static int
    763 genfs_rename_lock(const struct genfs_rename_ops *ops,
    764     struct mount *mp, kauth_cred_t cred,
    765     int overlap_error, int a_dot_error, int b_dot_error,
    766     struct vnode *a_dvp, struct componentname *a_cnp, bool a_missing_ok,
    767     void *a_de_ret, struct vnode **a_vp_ret,
    768     struct vnode *b_dvp, struct componentname *b_cnp, bool b_missing_ok,
    769     void *b_de_ret, struct vnode **b_vp_ret)
    770 {
    771 	struct vnode *a_vp, *b_vp;
    772 	int error;
    773 
    774 	KASSERT(ops != NULL);
    775 	KASSERT(mp != NULL);
    776 	KASSERT(a_dvp != NULL);
    777 	KASSERT(a_cnp != NULL);
    778 	KASSERT(a_vp_ret != NULL);
    779 	KASSERT(b_dvp != NULL);
    780 	KASSERT(b_cnp != NULL);
    781 	KASSERT(b_vp_ret != NULL);
    782 	KASSERT(a_dvp != b_dvp);
    783 	KASSERT(a_vp_ret != b_vp_ret);
    784 	KASSERT(a_dvp->v_type == VDIR);
    785 	KASSERT(b_dvp->v_type == VDIR);
    786 	KASSERT(a_dvp->v_mount == mp);
    787 	KASSERT(b_dvp->v_mount == mp);
    788 	KASSERT(a_missing_ok != b_missing_ok);
    789 
    790 	/*
    791 	 * 1. Lock a_dvp.
    792 	 */
    793 	error = ops->gro_lock_directory(mp, a_dvp);
    794 	if (error)
    795 		goto fail0;
    796 
    797 	/* Did we lose a race with mount?  */
    798 	if (a_dvp->v_mountedhere != NULL) {
    799 		error = EBUSY;
    800 		goto fail1;
    801 	}
    802 
    803 	/*
    804 	 * 2. Lookup a_vp.  May lock/unlock a_vp.
    805 	 */
    806 	error = ops->gro_lookup(mp, a_dvp, a_cnp, a_de_ret, &a_vp);
    807 	if (error) {
    808 		if (a_missing_ok && (error == ENOENT))
    809 			a_vp = NULL;
    810 		else
    811 			goto fail1;
    812 	} else {
    813 		KASSERT(a_vp != NULL);
    814 
    815 		/* Refuse to rename (over) `.'.  */
    816 		if (a_vp == a_dvp) {
    817 			error = a_dot_error;
    818 			goto fail2;
    819 		}
    820 
    821 		/* Reject rename("x", "x/y") or rename("x/y", "x").  */
    822 		if (a_vp == b_dvp) {
    823 			error = overlap_error;
    824 			goto fail2;
    825 		}
    826 	}
    827 
    828 	KASSERT(a_vp != a_dvp);
    829 	KASSERT(a_vp != b_dvp);
    830 
    831 	/*
    832 	 * 3. Lock a_vp, if it is a directory.
    833 	 *
    834 	 * We already ruled out a_vp == a_dvp (i.e., a_cnp is `.'), so
    835 	 * this is not locking against self, and we already ruled out
    836 	 * a_vp == b_dvp, so this won't cause subsequent locking of
    837 	 * b_dvp to lock against self.
    838 	 *
    839 	 * If a_vp is a nondirectory, we can't hold it when we lookup
    840 	 * b_vp in case (a) the file system can only lookup/lock/unlock
    841 	 * and (b) b_vp turns out to be the same file as a_vp due to
    842 	 * hard links -- and we can't even detect that case until after
    843 	 * we've looked up b_vp.  Fortunately, if a_vp is a
    844 	 * nondirectory, then it is a leaf, so we can safely lock it
    845 	 * last.
    846 	 */
    847 	if (a_vp != NULL && a_vp->v_type == VDIR) {
    848 		vn_lock(a_vp, LK_EXCLUSIVE | LK_RETRY);
    849 		KASSERT(a_vp->v_mount == mp);
    850 		/* Refuse to rename (over) a mount point.  */
    851 		if (a_vp->v_mountedhere != NULL) {
    852 			error = EBUSY;
    853 			goto fail3;
    854 		}
    855 	}
    856 
    857 	/*
    858 	 * 4. Lock b_dvp.
    859 	 */
    860 	error = ops->gro_lock_directory(mp, b_dvp);
    861 	if (error)
    862 		goto fail3;
    863 
    864 	/* Did we lose a race with mount?  */
    865 	if (b_dvp->v_mountedhere != NULL) {
    866 		error = EBUSY;
    867 		goto fail4;
    868 	}
    869 
    870 	/*
    871 	 * 5. Lookup b_vp.  May lock/unlock b_vp.
    872 	 */
    873 	error = ops->gro_lookup(mp, b_dvp, b_cnp, b_de_ret, &b_vp);
    874 	if (error) {
    875 		if (b_missing_ok && (error == ENOENT))
    876 			b_vp = NULL;
    877 		else
    878 			goto fail4;
    879 	} else {
    880 		KASSERT(b_vp != NULL);
    881 
    882 		/* Refuse to rename (over) `.'.  */
    883 		if (b_vp == b_dvp) {
    884 			error = b_dot_error;
    885 			goto fail5;
    886 		}
    887 
    888 		/*
    889 		 * b_dvp must not be an ancestor of a_dvp, so if we
    890 		 * find b_dvp/b_vp=a_dvp/a_vp something is wrong.
    891 		 */
    892 		if (b_vp == a_dvp) {
    893 			/*
    894 			 * We have a directory hard link before us.
    895 			 * XXX What error should this return?  EDEADLK?
    896 			 * Panic?
    897 			 */
    898 			error = EIO;
    899 			goto fail5;
    900 		}
    901 	}
    902 	KASSERT(b_vp != b_dvp);
    903 	KASSERT(b_vp != a_dvp);
    904 
    905 	/*
    906 	 * 6. Lock a_vp, if it is a nondirectory.
    907 	 *
    908 	 * In this case a_vp is a leaf, so it is either equal to or
    909 	 * incommensurate with b_vp, and so we can safely lock it at
    910 	 * any point now.
    911 	 */
    912 	if (a_vp != NULL && a_vp->v_type != VDIR) {
    913 		vn_lock(a_vp, LK_EXCLUSIVE | LK_RETRY);
    914 		KASSERT(a_vp->v_mount == mp);
    915 		/* (not a directory so can't have anything mounted here) */
    916 	}
    917 
    918 	/*
    919 	 * 7. Lock b_vp, if it is not a_vp.
    920 	 *
    921 	 * b_vp and a_vp may the same inode if they are hard links to
    922 	 * one another.
    923 	 */
    924 	if ((b_vp != NULL) && (b_vp != a_vp)) {
    925 		vn_lock(b_vp, LK_EXCLUSIVE | LK_RETRY);
    926 		KASSERT(b_vp->v_mount == mp);
    927 		/* Refuse to rename (over) a mount point.  */
    928 		if ((b_vp->v_type == VDIR) && (b_vp->v_mountedhere != NULL)) {
    929 			error = EBUSY;
    930 			goto fail6;
    931 		}
    932 	}
    933 
    934 	KASSERT(VOP_ISLOCKED(a_dvp) == LK_EXCLUSIVE);
    935 	KASSERT(VOP_ISLOCKED(b_dvp) == LK_EXCLUSIVE);
    936 	KASSERT(a_missing_ok || (a_vp != NULL));
    937 	KASSERT(b_missing_ok || (b_vp != NULL));
    938 	KASSERT((a_vp == NULL) || (VOP_ISLOCKED(a_vp) == LK_EXCLUSIVE));
    939 	KASSERT((b_vp == NULL) || (VOP_ISLOCKED(b_vp) == LK_EXCLUSIVE));
    940 
    941 	*a_vp_ret = a_vp;
    942 	*b_vp_ret = b_vp;
    943 	return 0;
    944 
    945 fail6:	if ((b_vp != NULL) && (b_vp != a_vp))
    946 		VOP_UNLOCK(b_vp);
    947 	if (a_vp != NULL && a_vp->v_type != VDIR)
    948 		VOP_UNLOCK(a_vp);
    949 fail5:	if (b_vp != NULL)
    950 		vrele(b_vp);
    951 fail4:	VOP_UNLOCK(b_dvp);
    952 fail3:	if (a_vp != NULL && a_vp->v_type == VDIR)
    953 		VOP_UNLOCK(a_vp);
    954 fail2:	if (a_vp != NULL)
    955 		vrele(a_vp);
    956 fail1:	VOP_UNLOCK(a_dvp);
    957 fail0:	return error;
    958 }
    959 
    960 /*
    961  * genfs_rename_exit: Unlock everything we locked for rename.
    962  *
    963  * fdvp and tdvp must be referenced.
    964  *
    965  * On entry, everything is locked, and fvp and tvp referenced.
    966  *
    967  * On exit, everything is unlocked, and fvp and tvp are released.
    968  */
    969 static void
    970 genfs_rename_exit(const struct genfs_rename_ops *ops,
    971     struct mount *mp,
    972     struct vnode *fdvp, struct vnode *fvp,
    973     struct vnode *tdvp, struct vnode *tvp)
    974 {
    975 
    976 	(void)ops;
    977 	KASSERT(ops != NULL);
    978 	KASSERT(mp != NULL);
    979 	KASSERT(fdvp != NULL);
    980 	KASSERT(fvp != NULL);
    981 	KASSERT(fdvp != fvp);
    982 	KASSERT(fdvp != tvp);
    983 	KASSERT(tdvp != tvp);
    984 	KASSERT(tdvp != fvp);
    985 	KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
    986 	KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
    987 	KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
    988 	KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
    989 
    990 	if ((tvp != NULL) && (tvp != fvp))
    991 		VOP_UNLOCK(tvp);
    992 	VOP_UNLOCK(fvp);
    993 	if (tvp != NULL)
    994 		vrele(tvp);
    995 	if (tdvp != fdvp)
    996 		VOP_UNLOCK(tdvp);
    997 	vrele(fvp);
    998 	VOP_UNLOCK(fdvp);
    999 }
   1000 
   1001 /*
   1002  * genfs_rename_remove: Remove the entry for the non-directory vp with
   1003  * componentname cnp from the directory dvp, using the lookup results
   1004  * de.  It is the responsibility of gro_remove to purge the name cache.
   1005  *
   1006  * Everything must be locked and referenced.
   1007  */
   1008 static int
   1009 genfs_rename_remove(const struct genfs_rename_ops *ops,
   1010     struct mount *mp, kauth_cred_t cred,
   1011     struct vnode *dvp, struct componentname *cnp, void *de, struct vnode *vp,
   1012     nlink_t *tvp_nlinkp)
   1013 {
   1014 	int error;
   1015 
   1016 	KASSERT(ops != NULL);
   1017 	KASSERT(mp != NULL);
   1018 	KASSERT(dvp != NULL);
   1019 	KASSERT(cnp != NULL);
   1020 	KASSERT(vp != NULL);
   1021 	KASSERT(dvp != vp);
   1022 	KASSERT(dvp->v_type == VDIR);
   1023 	KASSERT(vp->v_type != VDIR);
   1024 	KASSERT(dvp->v_mount == mp);
   1025 	KASSERT(vp->v_mount == mp);
   1026 	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
   1027 	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
   1028 
   1029 	error = ops->gro_remove_check_possible(mp, dvp, vp);
   1030 	if (error)
   1031 		return error;
   1032 
   1033 	error = ops->gro_remove_check_permitted(mp, cred, dvp, vp);
   1034 	error = kauth_authorize_vnode(cred, KAUTH_VNODE_DELETE, vp, dvp,
   1035 	    error);
   1036 	if (error)
   1037 		return error;
   1038 
   1039 	error = ops->gro_remove(mp, cred, dvp, cnp, de, vp, tvp_nlinkp);
   1040 	if (error)
   1041 		return error;
   1042 
   1043 	return 0;
   1044 }
   1045 
   1046 static int
   1047 genfs_ufslike_check_sticky(kauth_cred_t, mode_t, uid_t, struct vnode *, uid_t);
   1048 
   1049 /*
   1050  * genfs_ufslike_rename_check_possible: Check whether a rename is
   1051  * possible independent of credentials, assuming UFS-like inode flag
   1052  * semantics.  clobber_p is true iff the target node already exists.
   1053  */
   1054 int
   1055 genfs_ufslike_rename_check_possible(
   1056     unsigned long fdflags, unsigned long fflags,
   1057     unsigned long tdflags, unsigned long tflags, bool clobber_p,
   1058     unsigned long immutable, unsigned long append)
   1059 {
   1060 
   1061 	if ((fdflags | fflags) & (immutable | append))
   1062 		return EPERM;
   1063 
   1064 	if (tdflags & (immutable | (clobber_p? append : 0)))
   1065 		return EPERM;
   1066 
   1067 	if (clobber_p && (tflags & (immutable | append)))
   1068 		return EPERM;
   1069 
   1070 	return 0;
   1071 }
   1072 
   1073 /*
   1074  * genfs_ufslike_rename_check_permitted: Check whether a rename is
   1075  * permitted given our credentials, assuming UFS-like permission and
   1076  * ownership semantics.
   1077  *
   1078  * The only pair of vnodes that may be identical is {fdvp, tdvp}.
   1079  *
   1080  * Everything must be locked and referenced.
   1081  */
   1082 int
   1083 genfs_ufslike_rename_check_permitted(kauth_cred_t cred,
   1084     struct vnode *fdvp, mode_t fdmode, uid_t fduid,
   1085     struct vnode *fvp, uid_t fuid,
   1086     struct vnode *tdvp, mode_t tdmode, uid_t tduid,
   1087     struct vnode *tvp, uid_t tuid)
   1088 {
   1089 	int error;
   1090 
   1091 	KASSERT(fdvp != NULL);
   1092 	KASSERT(fvp != NULL);
   1093 	KASSERT(tdvp != NULL);
   1094 	KASSERT(fdvp != fvp);
   1095 	KASSERT(fdvp != tvp);
   1096 	KASSERT(tdvp != fvp);
   1097 	KASSERT(tdvp != tvp);
   1098 	KASSERT(fvp != tvp);
   1099 	KASSERT(fdvp->v_type == VDIR);
   1100 	KASSERT(tdvp->v_type == VDIR);
   1101 	KASSERT(fdvp->v_mount == fvp->v_mount);
   1102 	KASSERT(fdvp->v_mount == tdvp->v_mount);
   1103 	KASSERT((tvp == NULL) || (fdvp->v_mount == tvp->v_mount));
   1104 	KASSERT(VOP_ISLOCKED(fdvp) == LK_EXCLUSIVE);
   1105 	KASSERT(VOP_ISLOCKED(fvp) == LK_EXCLUSIVE);
   1106 	KASSERT(VOP_ISLOCKED(tdvp) == LK_EXCLUSIVE);
   1107 	KASSERT((tvp == NULL) || (VOP_ISLOCKED(tvp) == LK_EXCLUSIVE));
   1108 
   1109 	/*
   1110 	 * We need to remove or change an entry in the source directory.
   1111 	 */
   1112 	error = VOP_ACCESS(fdvp, VWRITE, cred);
   1113 	if (error)
   1114 		return error;
   1115 
   1116 	/*
   1117 	 * If we are changing directories, then we need to write to the
   1118 	 * target directory to add or change an entry.  Also, if fvp is
   1119 	 * a directory, we need to write to it to change its `..'
   1120 	 * entry.
   1121 	 */
   1122 	if (fdvp != tdvp) {
   1123 		error = VOP_ACCESS(tdvp, VWRITE, cred);
   1124 		if (error)
   1125 			return error;
   1126 		if (fvp->v_type == VDIR) {
   1127 			error = VOP_ACCESS(fvp, VWRITE, cred);
   1128 			if (error)
   1129 				return error;
   1130 		}
   1131 	}
   1132 
   1133 	error = genfs_ufslike_check_sticky(cred, fdmode, fduid, fvp, fuid);
   1134 	if (error)
   1135 		return error;
   1136 
   1137 	error = genfs_ufslike_check_sticky(cred, tdmode, tduid, tvp, tuid);
   1138 	if (error)
   1139 		return error;
   1140 
   1141 	return 0;
   1142 }
   1143 
   1144 /*
   1145  * genfs_ufslike_remove_check_possible: Check whether a remove is
   1146  * possible independent of credentials, assuming UFS-like inode flag
   1147  * semantics.
   1148  */
   1149 int
   1150 genfs_ufslike_remove_check_possible(unsigned long dflags, unsigned long flags,
   1151     unsigned long immutable, unsigned long append)
   1152 {
   1153 
   1154 	/*
   1155 	 * We want to delete the entry.  If the directory is immutable,
   1156 	 * we can't write to it to delete the entry.  If the directory
   1157 	 * is append-only, the only change we can make is to add
   1158 	 * entries, so we can't delete entries.  If the node is
   1159 	 * immutable, we can't change the links to it, so we can't
   1160 	 * delete the entry.  If the node is append-only...well, this
   1161 	 * is what UFS does.
   1162 	 */
   1163 	if ((dflags | flags) & (immutable | append))
   1164 		return EPERM;
   1165 
   1166 	return 0;
   1167 }
   1168 
   1169 /*
   1170  * genfs_ufslike_remove_check_permitted: Check whether a remove is
   1171  * permitted given our credentials, assuming UFS-like permission and
   1172  * ownership semantics.
   1173  *
   1174  * Everything must be locked and referenced.
   1175  */
   1176 int
   1177 genfs_ufslike_remove_check_permitted(kauth_cred_t cred,
   1178     struct vnode *dvp, mode_t dmode, uid_t duid,
   1179     struct vnode *vp, uid_t uid)
   1180 {
   1181 	int error;
   1182 
   1183 	KASSERT(dvp != NULL);
   1184 	KASSERT(vp != NULL);
   1185 	KASSERT(dvp != vp);
   1186 	KASSERT(dvp->v_type == VDIR);
   1187 	KASSERT(vp->v_type != VDIR);
   1188 	KASSERT(dvp->v_mount == vp->v_mount);
   1189 	KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
   1190 	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
   1191 
   1192 	/*
   1193 	 * We need to write to the directory to remove from it.
   1194 	 */
   1195 	error = VOP_ACCESS(dvp, VWRITE, cred);
   1196 	if (error)
   1197 		return error;
   1198 
   1199 	error = genfs_ufslike_check_sticky(cred, dmode, duid, vp, uid);
   1200 	if (error)
   1201 		return error;
   1202 
   1203 	return 0;
   1204 }
   1205 
   1206 /*
   1207  * genfs_ufslike_check_sticky: Check whether a party with credentials
   1208  * cred may change an entry in a sticky directory, assuming UFS-like
   1209  * permission, ownership, and stickiness semantics: If the directory is
   1210  * sticky and the entry exists, the user must own either the directory
   1211  * or the entry's node in order to change the entry.
   1212  *
   1213  * Everything must be locked and referenced.
   1214  */
   1215 int
   1216 genfs_ufslike_check_sticky(kauth_cred_t cred, mode_t dmode, uid_t duid,
   1217     struct vnode *vp, uid_t uid)
   1218 {
   1219 
   1220 	if ((dmode & S_ISTXT) && (vp != NULL))
   1221 		return genfs_can_sticky(vp, cred, duid, uid);
   1222 
   1223 	return 0;
   1224 }
   1225