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