]> git.saurik.com Git - apple/xnu.git/blame_incremental - bsd/vfs/vfs_lookup.c
xnu-6153.81.5.tar.gz
[apple/xnu.git] / bsd / vfs / vfs_lookup.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 2000-2015 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
29/*
30 * Copyright (c) 1982, 1986, 1989, 1993
31 * The Regents of the University of California. All rights reserved.
32 * (c) UNIX System Laboratories, Inc.
33 * All or some portions of this file are derived from material licensed
34 * to the University of California by American Telephone and Telegraph
35 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
36 * the permission of UNIX System Laboratories, Inc.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by the University of
49 * California, Berkeley and its contributors.
50 * 4. Neither the name of the University nor the names of its contributors
51 * may be used to endorse or promote products derived from this software
52 * without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * SUCH DAMAGE.
65 *
66 * @(#)vfs_lookup.c 8.10 (Berkeley) 5/27/95
67 */
68/*
69 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
70 * support for mandatory and extensible security protections. This notice
71 * is included in support of clause 2.2 (b) of the Apple Public License,
72 * Version 2.0.
73 */
74
75#include <sys/param.h>
76#include <sys/systm.h>
77#include <sys/syslimits.h>
78#include <sys/time.h>
79#include <sys/namei.h>
80#include <sys/vm.h>
81#include <sys/vnode_internal.h>
82#include <sys/mount_internal.h>
83#include <sys/errno.h>
84#include <sys/malloc.h>
85#include <sys/filedesc.h>
86#include <sys/proc_internal.h>
87#include <sys/kdebug.h>
88#include <sys/unistd.h> /* For _PC_NAME_MAX */
89#include <sys/uio_internal.h>
90#include <sys/kauth.h>
91#include <kern/kalloc.h>
92#include <security/audit/audit.h>
93#include <sys/dtrace.h> /* to get the prototype for strstr() in sys/dtrace_glue.h */
94#if CONFIG_MACF
95#include <security/mac_framework.h>
96#endif
97
98#include <sys/paths.h>
99
100#if NAMEDRSRCFORK
101#include <sys/xattr.h>
102#endif
103/*
104 * The minimum volfs-style pathname is 9.
105 * Example: "/.vol/1/2"
106 */
107#define VOLFS_MIN_PATH_LEN 9
108
109
110#if CONFIG_VOLFS
111static int vfs_getrealpath(const char * path, char * realpath, size_t bufsize, vfs_context_t ctx);
112#define MAX_VOLFS_RESTARTS 5
113#endif
114
115static int lookup_traverse_mountpoints(struct nameidata *ndp, struct componentname *cnp, vnode_t dp, int vbusyflags, vfs_context_t ctx);
116static int handle_symlink_for_namei(struct nameidata *ndp, vnode_t *new_dp, vfs_context_t ctx);
117static int lookup_authorize_search(vnode_t dp, struct componentname *cnp, int dp_authorized_in_cache, vfs_context_t ctx);
118static void lookup_consider_update_cache(vnode_t dvp, vnode_t vp, struct componentname *cnp, int nc_generation);
119static int lookup_handle_found_vnode(struct nameidata *ndp, struct componentname *cnp, int rdonly,
120 int vbusyflags, int *keep_going, int nc_generation,
121 int wantparent, int atroot, vfs_context_t ctx);
122static int lookup_handle_emptyname(struct nameidata *ndp, struct componentname *cnp, int wantparent);
123
124#if NAMEDRSRCFORK
125static int lookup_handle_rsrc_fork(vnode_t dp, struct nameidata *ndp, struct componentname *cnp, int wantparent, vfs_context_t ctx);
126#endif
127
128
129
130/*
131 * Convert a pathname into a pointer to a locked inode.
132 *
133 * The FOLLOW flag is set when symbolic links are to be followed
134 * when they occur at the end of the name translation process.
135 * Symbolic links are always followed for all other pathname
136 * components other than the last.
137 *
138 * The segflg defines whether the name is to be copied from user
139 * space or kernel space.
140 *
141 * Overall outline of namei:
142 *
143 * copy in name
144 * get starting directory
145 * while (!done && !error) {
146 * call lookup to search path.
147 * if symbolic link, massage name in buffer and continue
148 * }
149 *
150 * Returns: 0 Success
151 * ENOENT No such file or directory
152 * ELOOP Too many levels of symbolic links
153 * ENAMETOOLONG Filename too long
154 * copyinstr:EFAULT Bad address
155 * copyinstr:ENAMETOOLONG Filename too long
156 * lookup:EBADF Bad file descriptor
157 * lookup:EROFS
158 * lookup:EACCES
159 * lookup:EPERM
160 * lookup:ERECYCLE vnode was recycled from underneath us in lookup.
161 * This means we should re-drive lookup from this point.
162 * lookup: ???
163 * VNOP_READLINK:???
164 */
165int
166namei(struct nameidata *ndp)
167{
168 struct filedesc *fdp; /* pointer to file descriptor state */
169 struct vnode *dp; /* the directory we are searching */
170 struct vnode *rootdir_with_usecount = NULLVP;
171 struct vnode *startdir_with_usecount = NULLVP;
172 struct vnode *usedvp = ndp->ni_dvp; /* store pointer to vp in case we must loop due to
173 * heavy vnode pressure */
174 u_long cnpflags = ndp->ni_cnd.cn_flags; /* store in case we have to restore after loop */
175 int error;
176 struct componentname *cnp = &ndp->ni_cnd;
177 vfs_context_t ctx = cnp->cn_context;
178 proc_t p = vfs_context_proc(ctx);
179#if CONFIG_AUDIT
180/* XXX ut should be from context */
181 uthread_t ut = (struct uthread *)get_bsdthread_info(current_thread());
182#endif
183
184#if CONFIG_VOLFS
185 int volfs_restarts = 0;
186#endif
187 size_t bytes_copied = 0;
188
189 fdp = p->p_fd;
190
191#if DIAGNOSTIC
192 if (!vfs_context_ucred(ctx) || !p) {
193 panic("namei: bad cred/proc");
194 }
195 if (cnp->cn_nameiop & (~OPMASK)) {
196 panic("namei: nameiop contaminated with flags");
197 }
198 if (cnp->cn_flags & OPMASK) {
199 panic("namei: flags contaminated with nameiops");
200 }
201#endif
202
203 /*
204 * A compound VNOP found something that needs further processing:
205 * either a trigger vnode, a covered directory, or a symlink.
206 */
207 if (ndp->ni_flag & NAMEI_CONTLOOKUP) {
208 int rdonly, vbusyflags, keep_going, wantparent;
209
210 rdonly = cnp->cn_flags & RDONLY;
211 vbusyflags = ((cnp->cn_flags & CN_NBMOUNTLOOK) != 0) ? LK_NOWAIT : 0;
212 keep_going = 0;
213 wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT);
214
215 ndp->ni_flag &= ~(NAMEI_CONTLOOKUP);
216
217 error = lookup_handle_found_vnode(ndp, &ndp->ni_cnd, rdonly, vbusyflags,
218 &keep_going, ndp->ni_ncgeneration, wantparent, 0, ctx);
219 if (error) {
220 goto out_drop;
221 }
222 if (keep_going) {
223 if ((cnp->cn_flags & ISSYMLINK) == 0) {
224 panic("We need to keep going on a continued lookup, but for vp type %d (tag %d)\n", ndp->ni_vp->v_type, ndp->ni_vp->v_tag);
225 }
226 goto continue_symlink;
227 }
228
229 return 0;
230 }
231
232vnode_recycled:
233
234 /*
235 * Get a buffer for the name to be translated, and copy the
236 * name into the buffer.
237 */
238 if ((cnp->cn_flags & HASBUF) == 0) {
239 cnp->cn_pnbuf = ndp->ni_pathbuf;
240 cnp->cn_pnlen = PATHBUFLEN;
241 }
242#if LP64_DEBUG
243 if ((UIO_SEG_IS_USER_SPACE(ndp->ni_segflg) == 0)
244 && (ndp->ni_segflg != UIO_SYSSPACE)
245 && (ndp->ni_segflg != UIO_SYSSPACE32)) {
246 panic("%s :%d - invalid ni_segflg\n", __FILE__, __LINE__);
247 }
248#endif /* LP64_DEBUG */
249
250retry_copy:
251 if (UIO_SEG_IS_USER_SPACE(ndp->ni_segflg)) {
252 error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf,
253 cnp->cn_pnlen, &bytes_copied);
254 } else {
255 error = copystr(CAST_DOWN(void *, ndp->ni_dirp), cnp->cn_pnbuf,
256 cnp->cn_pnlen, &bytes_copied);
257 }
258 if (error == ENAMETOOLONG && !(cnp->cn_flags & HASBUF)) {
259 MALLOC_ZONE(cnp->cn_pnbuf, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK);
260 if (cnp->cn_pnbuf == NULL) {
261 error = ENOMEM;
262 goto error_out;
263 }
264
265 cnp->cn_flags |= HASBUF;
266 cnp->cn_pnlen = MAXPATHLEN;
267 bytes_copied = 0;
268
269 goto retry_copy;
270 }
271 if (error) {
272 goto error_out;
273 }
274 ndp->ni_pathlen = bytes_copied;
275 bytes_copied = 0;
276
277 /*
278 * Since the name cache may contain positive entries of
279 * the incorrect case, force lookup() to bypass the cache
280 * and call directly into the filesystem for each path
281 * component. Note: the FS may still consult the cache,
282 * but can apply rules to validate the results.
283 */
284 if (proc_is_forcing_hfs_case_sensitivity(p)) {
285 cnp->cn_flags |= CN_SKIPNAMECACHE;
286 }
287
288#if CONFIG_VOLFS
289 /*
290 * Check for legacy volfs style pathnames.
291 *
292 * For compatibility reasons we currently allow these paths,
293 * but future versions of the OS may not support them.
294 */
295 if (ndp->ni_pathlen >= VOLFS_MIN_PATH_LEN &&
296 cnp->cn_pnbuf[0] == '/' &&
297 cnp->cn_pnbuf[1] == '.' &&
298 cnp->cn_pnbuf[2] == 'v' &&
299 cnp->cn_pnbuf[3] == 'o' &&
300 cnp->cn_pnbuf[4] == 'l' &&
301 cnp->cn_pnbuf[5] == '/') {
302 char * realpath;
303 int realpath_err;
304 /* Attempt to resolve a legacy volfs style pathname. */
305 MALLOC_ZONE(realpath, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK);
306 if (realpath) {
307 /*
308 * We only error out on the ENAMETOOLONG cases where we know that
309 * vfs_getrealpath translation succeeded but the path could not fit into
310 * MAXPATHLEN characters. In other failure cases, we may be dealing with a path
311 * that legitimately looks like /.vol/1234/567 and is not meant to be translated
312 */
313 if ((realpath_err = vfs_getrealpath(&cnp->cn_pnbuf[6], realpath, MAXPATHLEN, ctx))) {
314 FREE_ZONE(realpath, MAXPATHLEN, M_NAMEI);
315 if (realpath_err == ENOSPC || realpath_err == ENAMETOOLONG) {
316 error = ENAMETOOLONG;
317 goto error_out;
318 }
319 } else {
320 if (cnp->cn_flags & HASBUF) {
321 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
322 }
323 cnp->cn_pnbuf = realpath;
324 cnp->cn_pnlen = MAXPATHLEN;
325 ndp->ni_pathlen = strlen(realpath) + 1;
326 cnp->cn_flags |= HASBUF | CN_VOLFSPATH;
327 }
328 }
329 }
330#endif /* CONFIG_VOLFS */
331
332#if CONFIG_AUDIT
333 /* If we are auditing the kernel pathname, save the user pathname */
334 if (cnp->cn_flags & AUDITVNPATH1) {
335 AUDIT_ARG(upath, ut->uu_cdir, cnp->cn_pnbuf, ARG_UPATH1);
336 }
337 if (cnp->cn_flags & AUDITVNPATH2) {
338 AUDIT_ARG(upath, ut->uu_cdir, cnp->cn_pnbuf, ARG_UPATH2);
339 }
340#endif /* CONFIG_AUDIT */
341
342 /*
343 * Do not allow empty pathnames
344 */
345 if (*cnp->cn_pnbuf == '\0') {
346 error = ENOENT;
347 goto error_out;
348 }
349 ndp->ni_loopcnt = 0;
350
351 /*
352 * determine the starting point for the translation.
353 *
354 * We may need to upto 2 usecounts on vnodes before starting the translation
355 * We need to have a usecount on the root directory for the process
356 * for the entire duration of the lookup. This is because symlink
357 * translation can restart translation at / if a symlink is encountered.
358 *
359 * For the duration of this lookup at rootdir for this lookup is the one
360 * we fetch now under the proc_fdlock even the if the proc rootdir changes
361 * once we let go of the proc_fdlock.
362 *
363 * In the future we may consider holding off a chroot till we complete
364 * in progress lookups.
365 *
366 * If the starting directory is not the process rootdir then we need
367 * a usecount on the starting directory as well for the duration of the
368 * lookup.
369 *
370 * Getting an addtional usecount involves first getting an iocount under
371 * the lock that ensures that a usecount is on the directory. Once we
372 * get an iocount we can release the lock and we will be free to get a
373 * usecount without the vnode getting recycled. Once we get the usecount
374 * we can release the icoount which we used to get our usecount.
375 */
376 proc_fdlock(p);
377 if (!(fdp->fd_flags & FD_CHROOT)) {
378 ndp->ni_rootdir = rootvnode;
379 } else {
380 ndp->ni_rootdir = fdp->fd_rdir;
381 }
382
383 if (!ndp->ni_rootdir) {
384 if (!(fdp->fd_flags & FD_CHROOT)) {
385 proc_fdunlock(p);
386 printf("rootvnode is not set\n");
387 } else {
388 proc_fdunlock(p);
389 /* This should be a panic */
390 printf("fdp->fd_rdir is not set\n");
391 }
392 error = ENOENT;
393 goto error_out;
394 }
395
396 /*
397 * We have the proc_fdlock here so we still have a usecount
398 * on ndp->ni_rootdir.
399 *
400 * However we need to get our own usecount on it in order to
401 * ensure that the vnode isn't recycled to something else.
402 *
403 * Note : It's fine if the vnode is force reclaimed but with
404 * a usecount it won't be reused until we release the reference.
405 *
406 * In order to get that usecount however, we need to first
407 * get non blocking iocount since we'll be doing this under
408 * the proc_fdlock.
409 */
410 if (vnode_get(ndp->ni_rootdir) != 0) {
411 proc_fdunlock(p);
412 error = ENOENT;
413 goto error_out;
414 }
415
416 proc_fdunlock(p);
417
418 /* Now we can safely get our own ref on ni_rootdir */
419 error = vnode_ref_ext(ndp->ni_rootdir, O_EVTONLY, 0);
420 vnode_put(ndp->ni_rootdir);
421 if (error) {
422 ndp->ni_rootdir = NULLVP;
423 goto error_out;
424 }
425
426 rootdir_with_usecount = ndp->ni_rootdir;
427
428 cnp->cn_nameptr = cnp->cn_pnbuf;
429
430 ndp->ni_usedvp = NULLVP;
431
432 bool dp_needs_put = false;
433 if (*(cnp->cn_nameptr) == '/') {
434 while (*(cnp->cn_nameptr) == '/') {
435 cnp->cn_nameptr++;
436 ndp->ni_pathlen--;
437 }
438 dp = ndp->ni_rootdir;
439 } else if (cnp->cn_flags & USEDVP) {
440 dp = ndp->ni_dvp;
441 ndp->ni_usedvp = dp;
442 } else {
443 dp = vfs_context_get_cwd(ctx);
444 if (dp) {
445 dp_needs_put = true;
446 }
447 }
448
449 if (dp == NULLVP || (dp->v_lflag & VL_DEAD)) {
450 if (dp_needs_put) {
451 vnode_put(dp);
452 dp_needs_put = false;
453 }
454 dp = NULLVP;
455 error = ENOENT;
456 goto error_out;
457 }
458
459 if (dp != rootdir_with_usecount) {
460 error = vnode_ref_ext(dp, O_EVTONLY, 0);
461 if (error) {
462 if (dp_needs_put) {
463 vnode_put(dp);
464 dp_needs_put = false;
465 }
466 dp = NULLVP;
467 goto error_out;
468 }
469 startdir_with_usecount = dp;
470 }
471
472 if (dp_needs_put) {
473 vnode_put(dp);
474 dp_needs_put = false;
475 }
476
477 ndp->ni_dvp = NULLVP;
478 ndp->ni_vp = NULLVP;
479
480 for (;;) {
481#if CONFIG_MACF
482 /*
483 * Give MACF policies a chance to reject the lookup
484 * before performing any filesystem operations.
485 * This hook is called before resolving the path and
486 * again each time a symlink is encountered.
487 * NB: policies receive path information as supplied
488 * by the caller and thus cannot be trusted.
489 */
490 error = mac_vnode_check_lookup_preflight(ctx, dp, cnp->cn_nameptr, cnp->cn_namelen);
491 if (error) {
492 goto error_out;
493 }
494#endif
495
496 ndp->ni_startdir = dp;
497 dp = NULLVP;
498
499 if ((error = lookup(ndp))) {
500 goto error_out;
501 }
502
503 /*
504 * Check for symbolic link
505 */
506 if ((cnp->cn_flags & ISSYMLINK) == 0) {
507 if (startdir_with_usecount) {
508 vnode_rele_ext(startdir_with_usecount, O_EVTONLY, 0);
509 startdir_with_usecount = NULLVP;
510 }
511 if (rootdir_with_usecount) {
512 vnode_rele_ext(rootdir_with_usecount, O_EVTONLY, 0);
513 rootdir_with_usecount = NULLVP;
514 }
515 return 0;
516 }
517
518continue_symlink:
519 /*
520 * Gives us a new path to process, and a starting dir (with an iocount).
521 * The iocount is needed to take a usecount on the vnode returned
522 * (if it is not a vnode we already have a usecount on).
523 */
524 error = handle_symlink_for_namei(ndp, &dp, ctx);
525 if (error != 0) {
526 break;
527 }
528
529 if (dp == ndp->ni_rootdir && startdir_with_usecount) {
530 vnode_rele_ext(startdir_with_usecount, O_EVTONLY, 0);
531 startdir_with_usecount = NULLVP;
532 } else if (dp != startdir_with_usecount) {
533 if (startdir_with_usecount) {
534 vnode_rele_ext(startdir_with_usecount, O_EVTONLY, 0);
535 startdir_with_usecount = NULLVP;
536 }
537 error = vnode_ref_ext(dp, O_EVTONLY, 0);
538 if (error) {
539 vnode_put(dp);
540 dp = NULLVP;
541 goto error_out;
542 }
543 startdir_with_usecount = dp;
544 }
545 /* iocount not required on dp anymore */
546 vnode_put(dp);
547 }
548 /*
549 * only come here if we fail to handle a SYMLINK...
550 * if either ni_dvp or ni_vp is non-NULL, then
551 * we need to drop the iocount that was picked
552 * up in the lookup routine
553 */
554out_drop:
555 if (ndp->ni_dvp) {
556 vnode_put(ndp->ni_dvp);
557 }
558 if (ndp->ni_vp) {
559 vnode_put(ndp->ni_vp);
560 }
561error_out:
562 if ((cnp->cn_flags & HASBUF)) {
563 cnp->cn_flags &= ~HASBUF;
564 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
565 }
566 cnp->cn_pnbuf = NULL;
567 ndp->ni_vp = NULLVP;
568 ndp->ni_dvp = NULLVP;
569
570 if (startdir_with_usecount) {
571 vnode_rele_ext(startdir_with_usecount, O_EVTONLY, 0);
572 startdir_with_usecount = NULLVP;
573 }
574 if (rootdir_with_usecount) {
575 vnode_rele_ext(rootdir_with_usecount, O_EVTONLY, 0);
576 rootdir_with_usecount = NULLVP;
577 }
578
579#if CONFIG_VOLFS
580 /*
581 * Deal with volfs fallout.
582 *
583 * At this point, if we were originally given a volfs path that
584 * looks like /.vol/123/456, then we would have had to convert it into
585 * a full path. Assuming that part worked properly, we will now attempt
586 * to conduct a lookup of the item in the namespace. Under normal
587 * circumstances, if a user looked up /tmp/foo and it was not there, it
588 * would be permissible to return ENOENT.
589 *
590 * However, we may not want to do that here. Specifically, the volfs path
591 * uniquely identifies a certain item in the namespace regardless of where it
592 * lives. If the item has moved in between the time we constructed the
593 * path and now, when we're trying to do a lookup/authorization on the full
594 * path, we may have gotten an ENOENT.
595 *
596 * At this point we can no longer tell if the path no longer exists
597 * or if the item in question no longer exists. It could have been renamed
598 * away, in which case the /.vol identifier is still valid.
599 *
600 * Do this dance a maximum of MAX_VOLFS_RESTARTS times.
601 */
602 if ((error == ENOENT) && (ndp->ni_cnd.cn_flags & CN_VOLFSPATH)) {
603 if (volfs_restarts < MAX_VOLFS_RESTARTS) {
604 volfs_restarts++;
605 goto vnode_recycled;
606 }
607 }
608#endif
609
610 if (error == ERECYCLE) {
611 /* vnode was recycled underneath us. re-drive lookup to start at
612 * the beginning again, since recycling invalidated last lookup*/
613 ndp->ni_cnd.cn_flags = cnpflags;
614 ndp->ni_dvp = usedvp;
615 goto vnode_recycled;
616 }
617
618
619 return error;
620}
621
622int
623namei_compound_available(vnode_t dp, struct nameidata *ndp)
624{
625 if ((ndp->ni_flag & NAMEI_COMPOUNDOPEN) != 0) {
626 return vnode_compound_open_available(dp);
627 }
628
629 return 0;
630}
631
632static int
633lookup_authorize_search(vnode_t dp, struct componentname *cnp, int dp_authorized_in_cache, vfs_context_t ctx)
634{
635#if !CONFIG_MACF
636#pragma unused(cnp)
637#endif
638
639 int error;
640
641 if (!dp_authorized_in_cache) {
642 error = vnode_authorize(dp, NULL, KAUTH_VNODE_SEARCH, ctx);
643 if (error) {
644 return error;
645 }
646 }
647#if CONFIG_MACF
648 error = mac_vnode_check_lookup(ctx, dp, cnp);
649 if (error) {
650 return error;
651 }
652#endif /* CONFIG_MACF */
653
654 return 0;
655}
656
657static void
658lookup_consider_update_cache(vnode_t dvp, vnode_t vp, struct componentname *cnp, int nc_generation)
659{
660 int isdot_or_dotdot;
661 isdot_or_dotdot = (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') || (cnp->cn_flags & ISDOTDOT);
662
663 if (vp->v_name == NULL || vp->v_parent == NULLVP) {
664 int update_flags = 0;
665
666 if (isdot_or_dotdot == 0) {
667 if (vp->v_name == NULL) {
668 update_flags |= VNODE_UPDATE_NAME;
669 }
670 if (dvp != NULLVP && vp->v_parent == NULLVP) {
671 update_flags |= VNODE_UPDATE_PARENT;
672 }
673
674 if (update_flags) {
675 vnode_update_identity(vp, dvp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_hash, update_flags);
676 }
677 }
678 }
679 if ((cnp->cn_flags & MAKEENTRY) && (vp->v_flag & VNCACHEABLE) && LIST_FIRST(&vp->v_nclinks) == NULL) {
680 /*
681 * missing from name cache, but should
682 * be in it... this can happen if volfs
683 * causes the vnode to be created or the
684 * name cache entry got recycled but the
685 * vnode didn't...
686 * check to make sure that ni_dvp is valid
687 * cache_lookup_path may return a NULL
688 * do a quick check to see if the generation of the
689 * directory matches our snapshot... this will get
690 * rechecked behind the name cache lock, but if it
691 * already fails to match, no need to go any further
692 */
693 if (dvp != NULLVP && (nc_generation == dvp->v_nc_generation) && (!isdot_or_dotdot)) {
694 cache_enter_with_gen(dvp, vp, cnp, nc_generation);
695 }
696 }
697}
698
699#if NAMEDRSRCFORK
700/*
701 * Can change ni_dvp and ni_vp. On success, returns with iocounts on stream vnode (always) and
702 * data fork if requested. On failure, returns with iocount data fork (always) and its parent directory
703 * (if one was provided).
704 */
705static int
706lookup_handle_rsrc_fork(vnode_t dp, struct nameidata *ndp, struct componentname *cnp, int wantparent, vfs_context_t ctx)
707{
708 vnode_t svp = NULLVP;
709 enum nsoperation nsop;
710 int nsflags;
711 int error;
712
713 if (dp->v_type != VREG) {
714 error = ENOENT;
715 goto out;
716 }
717 switch (cnp->cn_nameiop) {
718 case DELETE:
719 if (cnp->cn_flags & CN_ALLOWRSRCFORK) {
720 nsop = NS_DELETE;
721 } else {
722 error = EPERM;
723 goto out;
724 }
725 break;
726 case CREATE:
727 if (cnp->cn_flags & CN_ALLOWRSRCFORK) {
728 nsop = NS_CREATE;
729 } else {
730 error = EPERM;
731 goto out;
732 }
733 break;
734 case LOOKUP:
735 /* Make sure our lookup of "/..namedfork/rsrc" is allowed. */
736 if (cnp->cn_flags & CN_ALLOWRSRCFORK) {
737 nsop = NS_OPEN;
738 } else {
739 error = EPERM;
740 goto out;
741 }
742 break;
743 default:
744 error = EPERM;
745 goto out;
746 }
747
748 nsflags = 0;
749 if (cnp->cn_flags & CN_RAW_ENCRYPTED) {
750 nsflags |= NS_GETRAWENCRYPTED;
751 }
752
753 /* Ask the file system for the resource fork. */
754 error = vnode_getnamedstream(dp, &svp, XATTR_RESOURCEFORK_NAME, nsop, nsflags, ctx);
755
756 /* During a create, it OK for stream vnode to be missing. */
757 if (error == ENOATTR || error == ENOENT) {
758 error = (nsop == NS_CREATE) ? 0 : ENOENT;
759 }
760 if (error) {
761 goto out;
762 }
763 /* The "parent" of the stream is the file. */
764 if (wantparent) {
765 if (ndp->ni_dvp) {
766 vnode_put(ndp->ni_dvp);
767 }
768 ndp->ni_dvp = dp;
769 } else {
770 vnode_put(dp);
771 }
772 ndp->ni_vp = svp; /* on create this may be null */
773
774 /* Restore the truncated pathname buffer (for audits). */
775 if (ndp->ni_pathlen == 1 && ndp->ni_next[0] == '\0') {
776 /*
777 * While we replaced only '/' with '\0' and would ordinarily
778 * need to just switch that back, the buffer in which we did
779 * this may not be what the pathname buffer is now when symlinks
780 * are involved. If we just restore the "/" we will make the
781 * string not terminated anymore, so be safe and restore the
782 * entire suffix.
783 */
784 strncpy(ndp->ni_next, _PATH_RSRCFORKSPEC, sizeof(_PATH_RSRCFORKSPEC));
785 cnp->cn_nameptr = ndp->ni_next + 1;
786 cnp->cn_namelen = sizeof(_PATH_RSRCFORKSPEC) - 1;
787 ndp->ni_next += cnp->cn_namelen;
788 if (ndp->ni_next[0] != '\0') {
789 panic("Incorrect termination of path in %s", __FUNCTION__);
790 }
791 }
792 cnp->cn_flags &= ~MAKEENTRY;
793
794 return 0;
795out:
796 return error;
797}
798#endif /* NAMEDRSRCFORK */
799
800/*
801 * iocounts in:
802 * --One on ni_vp. One on ni_dvp if there is more path, or we didn't come through the
803 * cache, or we came through the cache and the caller doesn't want the parent.
804 *
805 * iocounts out:
806 * --Leaves us in the correct state for the next step, whatever that might be.
807 * --If we find a symlink, returns with iocounts on both ni_vp and ni_dvp.
808 * --If we are to look up another component, then we have an iocount on ni_vp and
809 * nothing else.
810 * --If we are done, returns an iocount on ni_vp, and possibly on ni_dvp depending on nameidata flags.
811 * --In the event of an error, may return with ni_dvp NULL'ed out (in which case, iocount
812 * was dropped).
813 */
814static int
815lookup_handle_found_vnode(struct nameidata *ndp, struct componentname *cnp, int rdonly,
816 int vbusyflags, int *keep_going, int nc_generation,
817 int wantparent, int atroot, vfs_context_t ctx)
818{
819 vnode_t dp;
820 int error;
821 char *cp;
822
823 dp = ndp->ni_vp;
824 *keep_going = 0;
825
826 if (ndp->ni_vp == NULLVP) {
827 panic("NULL ni_vp in %s\n", __FUNCTION__);
828 }
829
830 if (atroot) {
831 goto nextname;
832 }
833
834 /*
835 * Take into account any additional components consumed by
836 * the underlying filesystem.
837 */
838 if (cnp->cn_consume > 0) {
839 cnp->cn_nameptr += cnp->cn_consume;
840 ndp->ni_next += cnp->cn_consume;
841 ndp->ni_pathlen -= cnp->cn_consume;
842 cnp->cn_consume = 0;
843 } else {
844 lookup_consider_update_cache(ndp->ni_dvp, dp, cnp, nc_generation);
845 }
846
847 /*
848 * Check to see if the vnode has been mounted on...
849 * if so find the root of the mounted file system.
850 * Updates ndp->ni_vp.
851 */
852 error = lookup_traverse_mountpoints(ndp, cnp, dp, vbusyflags, ctx);
853 dp = ndp->ni_vp;
854 if (error) {
855 goto out;
856 }
857
858#if CONFIG_MACF
859 if (vfs_flags(vnode_mount(dp)) & MNT_MULTILABEL) {
860 error = vnode_label(vnode_mount(dp), NULL, dp, NULL, 0, ctx);
861 if (error) {
862 goto out;
863 }
864 }
865#endif
866
867 /*
868 * Check for symbolic link
869 */
870 if ((dp->v_type == VLNK) &&
871 ((cnp->cn_flags & FOLLOW) || (ndp->ni_flag & NAMEI_TRAILINGSLASH) || *ndp->ni_next == '/')) {
872 cnp->cn_flags |= ISSYMLINK;
873 *keep_going = 1;
874 return 0;
875 }
876
877 /*
878 * Check for bogus trailing slashes.
879 */
880 if ((ndp->ni_flag & NAMEI_TRAILINGSLASH)) {
881 if (dp->v_type != VDIR) {
882 error = ENOTDIR;
883 goto out;
884 }
885 ndp->ni_flag &= ~(NAMEI_TRAILINGSLASH);
886 }
887
888#if NAMEDSTREAMS
889 /*
890 * Deny namei/lookup requests to resolve paths that point to shadow files.
891 * Access to shadow files must be conducted by explicit calls to VNOP_LOOKUP
892 * directly, and not use lookup/namei
893 */
894 if (vnode_isshadow(dp)) {
895 error = ENOENT;
896 goto out;
897 }
898#endif
899
900nextname:
901 /*
902 * Not a symbolic link. If more pathname,
903 * continue at next component, else return.
904 *
905 * Definitely have a dvp if there's another slash
906 */
907 if (*ndp->ni_next == '/') {
908 cnp->cn_nameptr = ndp->ni_next + 1;
909 ndp->ni_pathlen--;
910 while (*cnp->cn_nameptr == '/') {
911 cnp->cn_nameptr++;
912 ndp->ni_pathlen--;
913 }
914
915 cp = cnp->cn_nameptr;
916 vnode_put(ndp->ni_dvp);
917 ndp->ni_dvp = NULLVP;
918
919 if (*cp == '\0') {
920 goto emptyname;
921 }
922
923 *keep_going = 1;
924 return 0;
925 }
926
927 /*
928 * Disallow directory write attempts on read-only file systems.
929 */
930 if (rdonly &&
931 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
932 error = EROFS;
933 goto out;
934 }
935
936 /* If SAVESTART is set, we should have a dvp */
937 if (cnp->cn_flags & SAVESTART) {
938 /*
939 * note that we already hold a reference
940 * on both dp and ni_dvp, but for some reason
941 * can't get another one... in this case we
942 * need to do vnode_put on dp in 'bad2'
943 */
944 if ((vnode_get(ndp->ni_dvp))) {
945 error = ENOENT;
946 goto out;
947 }
948 ndp->ni_startdir = ndp->ni_dvp;
949 }
950 if (!wantparent && ndp->ni_dvp) {
951 vnode_put(ndp->ni_dvp);
952 ndp->ni_dvp = NULLVP;
953 }
954
955 if (cnp->cn_flags & AUDITVNPATH1) {
956 AUDIT_ARG(vnpath, dp, ARG_VNODE1);
957 } else if (cnp->cn_flags & AUDITVNPATH2) {
958 AUDIT_ARG(vnpath, dp, ARG_VNODE2);
959 }
960
961#if NAMEDRSRCFORK
962 /*
963 * Caller wants the resource fork.
964 */
965 if ((cnp->cn_flags & CN_WANTSRSRCFORK) && (dp != NULLVP)) {
966 error = lookup_handle_rsrc_fork(dp, ndp, cnp, wantparent, ctx);
967 if (error != 0) {
968 goto out;
969 }
970
971 dp = ndp->ni_vp;
972 }
973#endif
974 if (kdebug_enable) {
975 kdebug_lookup(ndp->ni_vp, cnp);
976 }
977
978 return 0;
979
980emptyname:
981 error = lookup_handle_emptyname(ndp, cnp, wantparent);
982 if (error != 0) {
983 goto out;
984 }
985
986 return 0;
987out:
988 return error;
989}
990
991/*
992 * Comes in iocount on ni_vp. May overwrite ni_dvp, but doesn't interpret incoming value.
993 */
994static int
995lookup_handle_emptyname(struct nameidata *ndp, struct componentname *cnp, int wantparent)
996{
997 vnode_t dp;
998 int error = 0;
999
1000 dp = ndp->ni_vp;
1001 cnp->cn_namelen = 0;
1002 /*
1003 * A degenerate name (e.g. / or "") which is a way of
1004 * talking about a directory, e.g. like "/." or ".".
1005 */
1006 if (dp->v_type != VDIR) {
1007 error = ENOTDIR;
1008 goto out;
1009 }
1010 if (cnp->cn_nameiop != LOOKUP) {
1011 error = EISDIR;
1012 goto out;
1013 }
1014 if (wantparent) {
1015 /*
1016 * note that we already hold a reference
1017 * on dp, but for some reason can't
1018 * get another one... in this case we
1019 * need to do vnode_put on dp in 'bad'
1020 */
1021 if ((vnode_get(dp))) {
1022 error = ENOENT;
1023 goto out;
1024 }
1025 ndp->ni_dvp = dp;
1026 }
1027 cnp->cn_flags &= ~ISDOTDOT;
1028 cnp->cn_flags |= ISLASTCN;
1029 ndp->ni_next = cnp->cn_nameptr;
1030 ndp->ni_vp = dp;
1031
1032 if (cnp->cn_flags & AUDITVNPATH1) {
1033 AUDIT_ARG(vnpath, dp, ARG_VNODE1);
1034 } else if (cnp->cn_flags & AUDITVNPATH2) {
1035 AUDIT_ARG(vnpath, dp, ARG_VNODE2);
1036 }
1037 if (cnp->cn_flags & SAVESTART) {
1038 panic("lookup: SAVESTART");
1039 }
1040
1041 return 0;
1042out:
1043 return error;
1044}
1045/*
1046 * Search a pathname.
1047 * This is a very central and rather complicated routine.
1048 *
1049 * The pathname is pointed to by ni_ptr and is of length ni_pathlen.
1050 * The starting directory is taken from ni_startdir. The pathname is
1051 * descended until done, or a symbolic link is encountered. The variable
1052 * ni_more is clear if the path is completed; it is set to one if a
1053 * symbolic link needing interpretation is encountered.
1054 *
1055 * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on
1056 * whether the name is to be looked up, created, renamed, or deleted.
1057 * When CREATE, RENAME, or DELETE is specified, information usable in
1058 * creating, renaming, or deleting a directory entry may be calculated.
1059 * If flag has LOCKPARENT or'ed into it, the parent directory is returned
1060 * locked. If flag has WANTPARENT or'ed into it, the parent directory is
1061 * returned unlocked. Otherwise the parent directory is not returned. If
1062 * the target of the pathname exists and LOCKLEAF is or'ed into the flag
1063 * the target is returned locked, otherwise it is returned unlocked.
1064 * When creating or renaming and LOCKPARENT is specified, the target may not
1065 * be ".". When deleting and LOCKPARENT is specified, the target may be ".".
1066 *
1067 * Overall outline of lookup:
1068 *
1069 * dirloop:
1070 * identify next component of name at ndp->ni_ptr
1071 * handle degenerate case where name is null string
1072 * if .. and crossing mount points and on mounted filesys, find parent
1073 * call VNOP_LOOKUP routine for next component name
1074 * directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set
1075 * component vnode returned in ni_vp (if it exists), locked.
1076 * if result vnode is mounted on and crossing mount points,
1077 * find mounted on vnode
1078 * if more components of name, do next level at dirloop
1079 * return the answer in ni_vp, locked if LOCKLEAF set
1080 * if LOCKPARENT set, return locked parent in ni_dvp
1081 * if WANTPARENT set, return unlocked parent in ni_dvp
1082 *
1083 * Returns: 0 Success
1084 * ENOENT No such file or directory
1085 * EBADF Bad file descriptor
1086 * ENOTDIR Not a directory
1087 * EROFS Read-only file system [CREATE]
1088 * EISDIR Is a directory [CREATE]
1089 * cache_lookup_path:ERECYCLE (vnode was recycled from underneath us, redrive lookup again)
1090 * vnode_authorize:EROFS
1091 * vnode_authorize:EACCES
1092 * vnode_authorize:EPERM
1093 * vnode_authorize:???
1094 * VNOP_LOOKUP:ENOENT No such file or directory
1095 * VNOP_LOOKUP:EJUSTRETURN Restart system call (INTERNAL)
1096 * VNOP_LOOKUP:???
1097 * VFS_ROOT:ENOTSUP
1098 * VFS_ROOT:ENOENT
1099 * VFS_ROOT:???
1100 */
1101int
1102lookup(struct nameidata *ndp)
1103{
1104 char *cp; /* pointer into pathname argument */
1105 vnode_t tdp; /* saved dp */
1106 vnode_t dp; /* the directory we are searching */
1107 int docache = 1; /* == 0 do not cache last component */
1108 int wantparent; /* 1 => wantparent or lockparent flag */
1109 int rdonly; /* lookup read-only flag bit */
1110 int dp_authorized = 0;
1111 int error = 0;
1112 struct componentname *cnp = &ndp->ni_cnd;
1113 vfs_context_t ctx = cnp->cn_context;
1114 int vbusyflags = 0;
1115 int nc_generation = 0;
1116 vnode_t last_dp = NULLVP;
1117 int keep_going;
1118 int atroot;
1119
1120 /*
1121 * Setup: break out flag bits into variables.
1122 */
1123 if (cnp->cn_flags & NOCACHE) {
1124 docache = 0;
1125 }
1126 wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT);
1127 rdonly = cnp->cn_flags & RDONLY;
1128 cnp->cn_flags &= ~ISSYMLINK;
1129 cnp->cn_consume = 0;
1130
1131 dp = ndp->ni_startdir;
1132 ndp->ni_startdir = NULLVP;
1133
1134 if ((cnp->cn_flags & CN_NBMOUNTLOOK) != 0) {
1135 vbusyflags = LK_NOWAIT;
1136 }
1137 cp = cnp->cn_nameptr;
1138
1139 if (*cp == '\0') {
1140 if ((vnode_getwithref(dp))) {
1141 dp = NULLVP;
1142 error = ENOENT;
1143 goto bad;
1144 }
1145 ndp->ni_vp = dp;
1146 error = lookup_handle_emptyname(ndp, cnp, wantparent);
1147 if (error) {
1148 goto bad;
1149 }
1150
1151 return 0;
1152 }
1153dirloop:
1154 atroot = 0;
1155 ndp->ni_vp = NULLVP;
1156
1157 if ((error = cache_lookup_path(ndp, cnp, dp, ctx, &dp_authorized, last_dp))) {
1158 dp = NULLVP;
1159 goto bad;
1160 }
1161 if ((cnp->cn_flags & ISLASTCN)) {
1162 if (docache) {
1163 cnp->cn_flags |= MAKEENTRY;
1164 }
1165 } else {
1166 cnp->cn_flags |= MAKEENTRY;
1167 }
1168
1169 dp = ndp->ni_dvp;
1170
1171 if (ndp->ni_vp != NULLVP) {
1172 /*
1173 * cache_lookup_path returned a non-NULL ni_vp then,
1174 * we're guaranteed that the dp is a VDIR, it's
1175 * been authorized, and vp is not ".."
1176 *
1177 * make sure we don't try to enter the name back into
1178 * the cache if this vp is purged before we get to that
1179 * check since we won't have serialized behind whatever
1180 * activity is occurring in the FS that caused the purge
1181 */
1182 if (dp != NULLVP) {
1183 nc_generation = dp->v_nc_generation - 1;
1184 }
1185
1186 goto returned_from_lookup_path;
1187 }
1188
1189 /*
1190 * Handle "..": two special cases.
1191 * 1. If at root directory (e.g. after chroot)
1192 * or at absolute root directory
1193 * then ignore it so can't get out.
1194 * 2. If this vnode is the root of a mounted
1195 * filesystem, then replace it with the
1196 * vnode which was mounted on so we take the
1197 * .. in the other file system.
1198 */
1199 if ((cnp->cn_flags & ISDOTDOT)) {
1200 /*
1201 * if this is a chroot'ed process, check if the current
1202 * directory is still a subdirectory of the process's
1203 * root directory.
1204 */
1205 if (ndp->ni_rootdir && (ndp->ni_rootdir != rootvnode) &&
1206 dp != ndp->ni_rootdir) {
1207 int sdir_error;
1208 int is_subdir = FALSE;
1209
1210 sdir_error = vnode_issubdir(dp, ndp->ni_rootdir,
1211 &is_subdir, vfs_context_kernel());
1212
1213 /*
1214 * If we couldn't determine if dp is a subdirectory of
1215 * ndp->ni_rootdir (sdir_error != 0), we let the request
1216 * proceed.
1217 */
1218 if (!sdir_error && !is_subdir) {
1219 vnode_put(dp);
1220 dp = ndp->ni_rootdir;
1221 /*
1222 * There's a ref on the process's root directory
1223 * but we can't use vnode_getwithref here as
1224 * there is nothing preventing that ref being
1225 * released by another thread.
1226 */
1227 if (vnode_get(dp)) {
1228 error = ENOENT;
1229 goto bad;
1230 }
1231 }
1232 }
1233
1234 for (;;) {
1235 if (dp == ndp->ni_rootdir || dp == rootvnode) {
1236 ndp->ni_dvp = dp;
1237 ndp->ni_vp = dp;
1238 /*
1239 * we're pinned at the root
1240 * we've already got one reference on 'dp'
1241 * courtesy of cache_lookup_path... take
1242 * another one for the ".."
1243 * if we fail to get the new reference, we'll
1244 * drop our original down in 'bad'
1245 */
1246 if ((vnode_get(dp))) {
1247 error = ENOENT;
1248 goto bad;
1249 }
1250 atroot = 1;
1251 goto returned_from_lookup_path;
1252 }
1253 if ((dp->v_flag & VROOT) == 0 ||
1254 (cnp->cn_flags & NOCROSSMOUNT)) {
1255 break;
1256 }
1257 if (dp->v_mount == NULL) { /* forced umount */
1258 error = EBADF;
1259 goto bad;
1260 }
1261 tdp = dp;
1262 dp = tdp->v_mount->mnt_vnodecovered;
1263
1264 vnode_put(tdp);
1265
1266 if ((vnode_getwithref(dp))) {
1267 dp = NULLVP;
1268 error = ENOENT;
1269 goto bad;
1270 }
1271 ndp->ni_dvp = dp;
1272 dp_authorized = 0;
1273 }
1274 }
1275
1276 /*
1277 * We now have a segment name to search for, and a directory to search.
1278 */
1279unionlookup:
1280 ndp->ni_vp = NULLVP;
1281
1282 if (dp->v_type != VDIR) {
1283 error = ENOTDIR;
1284 goto lookup_error;
1285 }
1286 if ((cnp->cn_flags & DONOTAUTH) != DONOTAUTH) {
1287 error = lookup_authorize_search(dp, cnp, dp_authorized, ctx);
1288 if (error) {
1289 goto lookup_error;
1290 }
1291 }
1292
1293 /*
1294 * Now that we've authorized a lookup, can bail out if the filesystem
1295 * will be doing a batched operation. Return an iocount on dvp.
1296 */
1297#if NAMEDRSRCFORK
1298 if ((cnp->cn_flags & ISLASTCN) && namei_compound_available(dp, ndp) && !(cnp->cn_flags & CN_WANTSRSRCFORK)) {
1299#else
1300 if ((cnp->cn_flags & ISLASTCN) && namei_compound_available(dp, ndp)) {
1301#endif /* NAMEDRSRCFORK */
1302 ndp->ni_flag |= NAMEI_UNFINISHED;
1303 ndp->ni_ncgeneration = dp->v_nc_generation;
1304 return 0;
1305 }
1306
1307 nc_generation = dp->v_nc_generation;
1308
1309 /*
1310 * Note:
1311 * Filesystems that support hardlinks may want to call vnode_update_identity
1312 * if the lookup operation below will modify the in-core vnode to belong to a new point
1313 * in the namespace. VFS cannot infer whether or not the look up operation makes the vnode
1314 * name change or change parents. Without this, the lookup may make update
1315 * filesystem-specific in-core metadata but fail to update the v_parent or v_name
1316 * fields in the vnode. If VFS were to do this, it would be necessary to call
1317 * vnode_update_identity on every lookup operation -- expensive!
1318 *
1319 * However, even with this in place, multiple lookups may occur in between this lookup
1320 * and the subsequent vnop, so, at best, we could only guarantee that you would get a
1321 * valid path back, and not necessarily the one that you wanted.
1322 *
1323 * Example:
1324 * /tmp/a == /foo/b
1325 *
1326 * If you are now looking up /foo/b and the vnode for this link represents /tmp/a,
1327 * vnode_update_identity will fix the parentage so that you can get /foo/b back
1328 * through the v_parent chain (preventing you from getting /tmp/b back). It would
1329 * not fix whether or not you should or should not get /tmp/a vs. /foo/b.
1330 */
1331
1332 error = VNOP_LOOKUP(dp, &ndp->ni_vp, cnp, ctx);
1333
1334 if (error) {
1335lookup_error:
1336 if ((error == ENOENT) &&
1337 (dp->v_mount != NULL) &&
1338 (dp->v_mount->mnt_flag & MNT_UNION)) {
1339 tdp = dp;
1340 error = lookup_traverse_union(tdp, &dp, ctx);
1341 vnode_put(tdp);
1342 if (error) {
1343 dp = NULLVP;
1344 goto bad;
1345 }
1346
1347 ndp->ni_dvp = dp;
1348 dp_authorized = 0;
1349 goto unionlookup;
1350 }
1351
1352 if (error != EJUSTRETURN) {
1353 goto bad;
1354 }
1355
1356 if (ndp->ni_vp != NULLVP) {
1357 panic("leaf should be empty");
1358 }
1359
1360#if NAMEDRSRCFORK
1361 /*
1362 * At this point, error should be EJUSTRETURN.
1363 *
1364 * If CN_WANTSRSRCFORK is set, that implies that the
1365 * underlying filesystem could not find the "parent" of the
1366 * resource fork (the data fork), and we are doing a lookup
1367 * for a CREATE event.
1368 *
1369 * However, this should be converted to an error, as the
1370 * failure to find this parent should disallow further
1371 * progress to try and acquire a resource fork vnode.
1372 */
1373 if (cnp->cn_flags & CN_WANTSRSRCFORK) {
1374 error = ENOENT;
1375 goto bad;
1376 }
1377#endif
1378
1379 error = lookup_validate_creation_path(ndp);
1380 if (error) {
1381 goto bad;
1382 }
1383 /*
1384 * We return with ni_vp NULL to indicate that the entry
1385 * doesn't currently exist, leaving a pointer to the
1386 * referenced directory vnode in ndp->ni_dvp.
1387 */
1388 if (cnp->cn_flags & SAVESTART) {
1389 if ((vnode_get(ndp->ni_dvp))) {
1390 error = ENOENT;
1391 goto bad;
1392 }
1393 ndp->ni_startdir = ndp->ni_dvp;
1394 }
1395 if (!wantparent) {
1396 vnode_put(ndp->ni_dvp);
1397 }
1398
1399 if (kdebug_enable) {
1400 kdebug_lookup(ndp->ni_dvp, cnp);
1401 }
1402 return 0;
1403 }
1404returned_from_lookup_path:
1405 /* We'll always have an iocount on ni_vp when this finishes. */
1406 error = lookup_handle_found_vnode(ndp, cnp, rdonly, vbusyflags, &keep_going, nc_generation, wantparent, atroot, ctx);
1407 if (error != 0) {
1408 goto bad2;
1409 }
1410
1411 if (keep_going) {
1412 dp = ndp->ni_vp;
1413
1414 /* namei() will handle symlinks */
1415 if ((dp->v_type == VLNK) &&
1416 ((cnp->cn_flags & FOLLOW) || (ndp->ni_flag & NAMEI_TRAILINGSLASH) || *ndp->ni_next == '/')) {
1417 return 0;
1418 }
1419
1420 /*
1421 * Otherwise, there's more path to process.
1422 * cache_lookup_path is now responsible for dropping io ref on dp
1423 * when it is called again in the dirloop. This ensures we hold
1424 * a ref on dp until we complete the next round of lookup.
1425 */
1426 last_dp = dp;
1427
1428 goto dirloop;
1429 }
1430
1431 return 0;
1432bad2:
1433 if (ndp->ni_dvp) {
1434 vnode_put(ndp->ni_dvp);
1435 }
1436
1437 vnode_put(ndp->ni_vp);
1438 ndp->ni_vp = NULLVP;
1439
1440 if (kdebug_enable) {
1441 kdebug_lookup(dp, cnp);
1442 }
1443 return error;
1444
1445bad:
1446 if (dp) {
1447 vnode_put(dp);
1448 }
1449 ndp->ni_vp = NULLVP;
1450
1451 if (kdebug_enable) {
1452 kdebug_lookup(dp, cnp);
1453 }
1454 return error;
1455}
1456
1457/*
1458 * Given a vnode in a union mount, traverse to the equivalent
1459 * vnode in the underlying mount.
1460 */
1461int
1462lookup_traverse_union(vnode_t dvp, vnode_t *new_dvp, vfs_context_t ctx)
1463{
1464 char *path = NULL, *pp;
1465 const char *name, *np;
1466 int len;
1467 int error = 0;
1468 struct nameidata nd;
1469 vnode_t vp = dvp;
1470
1471 *new_dvp = NULL;
1472
1473 if (vp && vp->v_flag & VROOT) {
1474 *new_dvp = vp->v_mount->mnt_vnodecovered;
1475 if (vnode_getwithref(*new_dvp)) {
1476 return ENOENT;
1477 }
1478 return 0;
1479 }
1480
1481 path = (char *) kalloc(MAXPATHLEN);
1482 if (path == NULL) {
1483 error = ENOMEM;
1484 goto done;
1485 }
1486
1487 /*
1488 * Walk back up to the mountpoint following the
1489 * v_parent chain and build a slash-separated path.
1490 * Then lookup that path starting with the covered vnode.
1491 */
1492 pp = path + (MAXPATHLEN - 1);
1493 *pp = '\0';
1494
1495 while (1) {
1496 name = vnode_getname(vp);
1497 if (name == NULL) {
1498 printf("lookup_traverse_union: null parent name: .%s\n", pp);
1499 error = ENOENT;
1500 goto done;
1501 }
1502 len = strlen(name);
1503 if ((len + 1) > (pp - path)) { // Enough space for this name ?
1504 error = ENAMETOOLONG;
1505 vnode_putname(name);
1506 goto done;
1507 }
1508 for (np = name + len; len > 0; len--) { // Copy name backwards
1509 *--pp = *--np;
1510 }
1511 vnode_putname(name);
1512 vp = vp->v_parent;
1513 if (vp == NULLVP || vp->v_flag & VROOT) {
1514 break;
1515 }
1516 *--pp = '/';
1517 }
1518
1519 /* Evaluate the path in the underlying mount */
1520 NDINIT(&nd, LOOKUP, OP_LOOKUP, USEDVP, UIO_SYSSPACE, CAST_USER_ADDR_T(pp), ctx);
1521 nd.ni_dvp = dvp->v_mount->mnt_vnodecovered;
1522 error = namei(&nd);
1523 if (error == 0) {
1524 *new_dvp = nd.ni_vp;
1525 }
1526 nameidone(&nd);
1527done:
1528 if (path) {
1529 kfree(path, MAXPATHLEN);
1530 }
1531 return error;
1532}
1533
1534int
1535lookup_validate_creation_path(struct nameidata *ndp)
1536{
1537 struct componentname *cnp = &ndp->ni_cnd;
1538
1539 /*
1540 * If creating and at end of pathname, then can consider
1541 * allowing file to be created.
1542 */
1543 if (cnp->cn_flags & RDONLY) {
1544 return EROFS;
1545 }
1546 if ((cnp->cn_flags & ISLASTCN) && (ndp->ni_flag & NAMEI_TRAILINGSLASH) && !(cnp->cn_flags & WILLBEDIR)) {
1547 return ENOENT;
1548 }
1549
1550 return 0;
1551}
1552
1553/*
1554 * Modifies only ni_vp. Always returns with ni_vp still valid (iocount held).
1555 */
1556static int
1557lookup_traverse_mountpoints(struct nameidata *ndp, struct componentname *cnp, vnode_t dp,
1558 int vbusyflags, vfs_context_t ctx)
1559{
1560 mount_t mp;
1561 vnode_t tdp;
1562 int error = 0;
1563 uint32_t depth = 0;
1564 vnode_t mounted_on_dp;
1565 int current_mount_generation = 0;
1566#if CONFIG_TRIGGERS
1567 vnode_t triggered_dp = NULLVP;
1568 int retry_cnt = 0;
1569#define MAX_TRIGGER_RETRIES 1
1570#endif
1571
1572 if (dp->v_type != VDIR || cnp->cn_flags & NOCROSSMOUNT) {
1573 return 0;
1574 }
1575
1576 mounted_on_dp = dp;
1577#if CONFIG_TRIGGERS
1578restart:
1579#endif
1580 current_mount_generation = mount_generation;
1581
1582 while (dp->v_mountedhere) {
1583 vnode_lock_spin(dp);
1584 if ((mp = dp->v_mountedhere)) {
1585 mp->mnt_crossref++;
1586 vnode_unlock(dp);
1587 } else {
1588 vnode_unlock(dp);
1589 break;
1590 }
1591
1592 if (ISSET(mp->mnt_lflag, MNT_LFORCE)) {
1593 mount_dropcrossref(mp, dp, 0);
1594 break; // don't traverse into a forced unmount
1595 }
1596
1597
1598 if (vfs_busy(mp, vbusyflags)) {
1599 mount_dropcrossref(mp, dp, 0);
1600 if (vbusyflags == LK_NOWAIT) {
1601 error = ENOENT;
1602 goto out;
1603 }
1604
1605 continue;
1606 }
1607
1608 error = VFS_ROOT(mp, &tdp, ctx);
1609
1610 mount_dropcrossref(mp, dp, 0);
1611 vfs_unbusy(mp);
1612
1613 if (error) {
1614 goto out;
1615 }
1616
1617 vnode_put(dp);
1618 ndp->ni_vp = dp = tdp;
1619 if (dp->v_type != VDIR) {
1620#if DEVELOPMENT || DEBUG
1621 panic("%s : Root of filesystem not a directory\n",
1622 __FUNCTION__);
1623#else
1624 break;
1625#endif
1626 }
1627 depth++;
1628 }
1629
1630#if CONFIG_TRIGGERS
1631 /*
1632 * The triggered_dp check here is required but is susceptible to a
1633 * (unlikely) race in which trigger mount is done from here and is
1634 * unmounted before we get past vfs_busy above. We retry to deal with
1635 * that case but it has the side effect of unwanted retries for
1636 * "special" processes which don't want to trigger mounts.
1637 */
1638 if (dp->v_resolve && retry_cnt < MAX_TRIGGER_RETRIES) {
1639 error = vnode_trigger_resolve(dp, ndp, ctx);
1640 if (error) {
1641 goto out;
1642 }
1643 if (dp == triggered_dp) {
1644 retry_cnt += 1;
1645 } else {
1646 retry_cnt = 0;
1647 }
1648 triggered_dp = dp;
1649 goto restart;
1650 }
1651#endif /* CONFIG_TRIGGERS */
1652
1653 if (depth) {
1654 mp = mounted_on_dp->v_mountedhere;
1655
1656 if (mp) {
1657 mount_lock_spin(mp);
1658 mp->mnt_realrootvp_vid = dp->v_id;
1659 mp->mnt_realrootvp = dp;
1660 mp->mnt_generation = current_mount_generation;
1661 mount_unlock(mp);
1662 }
1663 }
1664
1665 return 0;
1666
1667out:
1668 return error;
1669}
1670
1671/*
1672 * Takes ni_vp and ni_dvp non-NULL. Returns with *new_dp set to the location
1673 * at which to start a lookup with a resolved path and with an iocount.
1674 */
1675static int
1676handle_symlink_for_namei(struct nameidata *ndp, vnode_t *new_dp, vfs_context_t ctx)
1677{
1678 int error;
1679 char *cp; /* pointer into pathname argument */
1680 uio_t auio;
1681 union {
1682 union {
1683 struct user_iovec s_uiovec;
1684 struct kern_iovec s_kiovec;
1685 } u_iovec;
1686 struct uio s_uio;
1687 char uio_buf[UIO_SIZEOF(1)];
1688 } u_uio_buf; /* union only for aligning uio_buf correctly */
1689 int need_newpathbuf;
1690 u_int linklen;
1691 struct componentname *cnp = &ndp->ni_cnd;
1692 vnode_t dp;
1693 char *tmppn;
1694 u_int rsrclen = (cnp->cn_flags & CN_WANTSRSRCFORK) ? sizeof(_PATH_RSRCFORKSPEC) : 0;
1695
1696 if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
1697 return ELOOP;
1698 }
1699#if CONFIG_MACF
1700 if ((error = mac_vnode_check_readlink(ctx, ndp->ni_vp)) != 0) {
1701 return error;
1702 }
1703#endif /* MAC */
1704 if (ndp->ni_pathlen > 1 || !(cnp->cn_flags & HASBUF)) {
1705 need_newpathbuf = 1;
1706 } else {
1707 need_newpathbuf = 0;
1708 }
1709
1710 if (need_newpathbuf) {
1711 MALLOC_ZONE(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
1712 if (cp == NULL) {
1713 return ENOMEM;
1714 }
1715 } else {
1716 cp = cnp->cn_pnbuf;
1717 }
1718 auio = uio_createwithbuffer(1, 0, UIO_SYSSPACE, UIO_READ,
1719 &u_uio_buf.uio_buf[0], sizeof(u_uio_buf.uio_buf));
1720
1721 uio_addiov(auio, CAST_USER_ADDR_T(cp), MAXPATHLEN);
1722
1723 error = VNOP_READLINK(ndp->ni_vp, auio, ctx);
1724 if (error) {
1725 if (need_newpathbuf) {
1726 FREE_ZONE(cp, MAXPATHLEN, M_NAMEI);
1727 }
1728 return error;
1729 }
1730
1731 /*
1732 * Safe to set unsigned with a [larger] signed type here
1733 * because 0 <= uio_resid <= MAXPATHLEN and MAXPATHLEN
1734 * is only 1024.
1735 */
1736 linklen = MAXPATHLEN - (u_int)uio_resid(auio);
1737 if (linklen + ndp->ni_pathlen + rsrclen > MAXPATHLEN) {
1738 if (need_newpathbuf) {
1739 FREE_ZONE(cp, MAXPATHLEN, M_NAMEI);
1740 }
1741
1742 return ENAMETOOLONG;
1743 }
1744 if (need_newpathbuf) {
1745 long len = cnp->cn_pnlen;
1746
1747 tmppn = cnp->cn_pnbuf;
1748 bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
1749 cnp->cn_pnbuf = cp;
1750 cnp->cn_pnlen = MAXPATHLEN;
1751
1752 if ((cnp->cn_flags & HASBUF)) {
1753 FREE_ZONE(tmppn, len, M_NAMEI);
1754 } else {
1755 cnp->cn_flags |= HASBUF;
1756 }
1757 } else {
1758 cnp->cn_pnbuf[linklen] = '\0';
1759 }
1760
1761 ndp->ni_pathlen += linklen;
1762 cnp->cn_nameptr = cnp->cn_pnbuf;
1763
1764 /*
1765 * starting point for 'relative'
1766 * symbolic link path
1767 *
1768 * If the starting point is not the root we have to return an iocounted
1769 * dp to namei so we don't release the icoount here.
1770 */
1771 dp = ndp->ni_dvp;
1772 ndp->ni_dvp = NULLVP;
1773
1774 /*
1775 * get rid of references returned via 'lookup'
1776 */
1777 vnode_put(ndp->ni_vp);
1778 ndp->ni_vp = NULLVP;
1779
1780 /*
1781 * Check if symbolic link restarts us at the root
1782 */
1783 if (*(cnp->cn_nameptr) == '/') {
1784 while (*(cnp->cn_nameptr) == '/') {
1785 cnp->cn_nameptr++;
1786 ndp->ni_pathlen--;
1787 }
1788 vnode_put(dp);
1789 if ((dp = ndp->ni_rootdir) == NULLVP) {
1790 return ENOENT;
1791 }
1792 if (vnode_get(dp) != 0) {
1793 return ENOENT;
1794 }
1795 }
1796
1797 if (dp == NULLVP || (dp->v_lflag & VL_DEAD)) {
1798 if (dp) {
1799 vnode_put(dp);
1800 }
1801 return ENOENT;
1802 }
1803
1804 *new_dp = dp;
1805
1806 return 0;
1807}
1808
1809/*
1810 * relookup - lookup a path name component
1811 * Used by lookup to re-aquire things.
1812 */
1813int
1814relookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp)
1815{
1816 struct vnode *dp = NULL; /* the directory we are searching */
1817 int wantparent; /* 1 => wantparent or lockparent flag */
1818 int rdonly; /* lookup read-only flag bit */
1819 int error = 0;
1820#ifdef NAMEI_DIAGNOSTIC
1821 int i, newhash; /* DEBUG: check name hash */
1822 char *cp; /* DEBUG: check name ptr/len */
1823#endif
1824 vfs_context_t ctx = cnp->cn_context;;
1825
1826 /*
1827 * Setup: break out flag bits into variables.
1828 */
1829 wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT);
1830 rdonly = cnp->cn_flags & RDONLY;
1831 cnp->cn_flags &= ~ISSYMLINK;
1832
1833 if (cnp->cn_flags & NOCACHE) {
1834 cnp->cn_flags &= ~MAKEENTRY;
1835 } else {
1836 cnp->cn_flags |= MAKEENTRY;
1837 }
1838
1839 dp = dvp;
1840
1841 /*
1842 * Check for degenerate name (e.g. / or "")
1843 * which is a way of talking about a directory,
1844 * e.g. like "/." or ".".
1845 */
1846 if (cnp->cn_nameptr[0] == '\0') {
1847 if (cnp->cn_nameiop != LOOKUP || wantparent) {
1848 error = EISDIR;
1849 goto bad;
1850 }
1851 if (dp->v_type != VDIR) {
1852 error = ENOTDIR;
1853 goto bad;
1854 }
1855 if ((vnode_get(dp))) {
1856 error = ENOENT;
1857 goto bad;
1858 }
1859 *vpp = dp;
1860
1861 if (cnp->cn_flags & SAVESTART) {
1862 panic("lookup: SAVESTART");
1863 }
1864 return 0;
1865 }
1866 /*
1867 * We now have a segment name to search for, and a directory to search.
1868 */
1869 if ((error = VNOP_LOOKUP(dp, vpp, cnp, ctx))) {
1870 if (error != EJUSTRETURN) {
1871 goto bad;
1872 }
1873#if DIAGNOSTIC
1874 if (*vpp != NULL) {
1875 panic("leaf should be empty");
1876 }
1877#endif
1878 /*
1879 * If creating and at end of pathname, then can consider
1880 * allowing file to be created.
1881 */
1882 if (rdonly) {
1883 error = EROFS;
1884 goto bad;
1885 }
1886 /*
1887 * We return with ni_vp NULL to indicate that the entry
1888 * doesn't currently exist, leaving a pointer to the
1889 * (possibly locked) directory inode in ndp->ni_dvp.
1890 */
1891 return 0;
1892 }
1893 dp = *vpp;
1894
1895#if DIAGNOSTIC
1896 /*
1897 * Check for symbolic link
1898 */
1899 if (dp->v_type == VLNK && (cnp->cn_flags & FOLLOW)) {
1900 panic("relookup: symlink found.\n");
1901 }
1902#endif
1903
1904 /*
1905 * Disallow directory write attempts on read-only file systems.
1906 */
1907 if (rdonly &&
1908 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
1909 error = EROFS;
1910 goto bad2;
1911 }
1912 /* ASSERT(dvp == ndp->ni_startdir) */
1913
1914 return 0;
1915
1916bad2:
1917 vnode_put(dp);
1918bad:
1919 *vpp = NULL;
1920
1921 return error;
1922}
1923
1924/*
1925 * Free pathname buffer
1926 */
1927void
1928nameidone(struct nameidata *ndp)
1929{
1930 if (ndp->ni_cnd.cn_flags & HASBUF) {
1931 char *tmp = ndp->ni_cnd.cn_pnbuf;
1932
1933 ndp->ni_cnd.cn_pnbuf = NULL;
1934 ndp->ni_cnd.cn_flags &= ~HASBUF;
1935 FREE_ZONE(tmp, ndp->ni_cnd.cn_pnlen, M_NAMEI);
1936 }
1937}
1938
1939
1940/*
1941 * Log (part of) a pathname using the KERNEL_DEBUG_CONSTANT mechanism, as used
1942 * by fs_usage. The path up to and including the current component name are
1943 * logged. Up to NUMPARMS*4 bytes of pathname will be logged. If the path
1944 * to be logged is longer than that, then the last NUMPARMS*4 bytes are logged.
1945 * That is, the truncation removes the leading portion of the path.
1946 *
1947 * The logging is done via multiple KERNEL_DEBUG_CONSTANT calls. The first one
1948 * is marked with DBG_FUNC_START. The last one is marked with DBG_FUNC_END
1949 * (in addition to DBG_FUNC_START if it is also the first). There may be
1950 * intermediate ones with neither DBG_FUNC_START nor DBG_FUNC_END.
1951 *
1952 * The first KERNEL_DEBUG_CONSTANT passes the vnode pointer and 12 bytes of
1953 * pathname. The remaining KERNEL_DEBUG_CONSTANT calls add 16 bytes of pathname
1954 * each. The minimum number of KERNEL_DEBUG_CONSTANT calls required to pass
1955 * the path are used. Any excess padding in the final KERNEL_DEBUG_CONSTANT
1956 * (because not all of the 12 or 16 bytes are needed for the remainder of the
1957 * path) is set to zero bytes, or '>' if there is more path beyond the
1958 * current component name (usually because an intermediate component was not
1959 * found).
1960 *
1961 * NOTE: If the path length is greater than NUMPARMS*4, or is not of the form
1962 * 12+N*16, there will be no padding.
1963 *
1964 * TODO: If there is more path beyond the current component name, should we
1965 * force some padding? For example, a lookup for /foo_bar_baz/spam that
1966 * fails because /foo_bar_baz is not found will only log "/foo_bar_baz", with
1967 * no '>' padding. But /foo_bar/spam would log "/foo_bar>>>>".
1968 */
1969#if (KDEBUG_LEVEL >= KDEBUG_LEVEL_IST)
1970
1971void
1972kdebug_vfs_lookup(long *dbg_parms, int dbg_namelen, void *dp, uint32_t flags)
1973{
1974 int code;
1975 unsigned int i;
1976 bool lookup = flags & KDBG_VFS_LOOKUP_FLAG_LOOKUP;
1977 bool noprocfilt = flags & KDBG_VFS_LOOKUP_FLAG_NOPROCFILT;
1978
1979 /*
1980 * In the event that we collect multiple, consecutive pathname
1981 * entries, we must mark the start of the path's string and the end.
1982 */
1983 if (lookup) {
1984 code = VFS_LOOKUP | DBG_FUNC_START;
1985 } else {
1986 code = VFS_LOOKUP_DONE | DBG_FUNC_START;
1987 }
1988
1989 if (dbg_namelen <= (int)(3 * sizeof(long))) {
1990 code |= DBG_FUNC_END;
1991 }
1992
1993 if (noprocfilt) {
1994 KDBG_RELEASE_NOPROCFILT(code, kdebug_vnode(dp), dbg_parms[0],
1995 dbg_parms[1], dbg_parms[2]);
1996 } else {
1997 KDBG_RELEASE(code, kdebug_vnode(dp), dbg_parms[0], dbg_parms[1],
1998 dbg_parms[2]);
1999 }
2000
2001 code &= ~DBG_FUNC_START;
2002
2003 for (i = 3, dbg_namelen -= (3 * sizeof(long)); dbg_namelen > 0; i += 4, dbg_namelen -= (4 * sizeof(long))) {
2004 if (dbg_namelen <= (int)(4 * sizeof(long))) {
2005 code |= DBG_FUNC_END;
2006 }
2007
2008 if (noprocfilt) {
2009 KDBG_RELEASE_NOPROCFILT(code, dbg_parms[i], dbg_parms[i + 1],
2010 dbg_parms[i + 2], dbg_parms[i + 3]);
2011 } else {
2012 KDBG_RELEASE(code, dbg_parms[i], dbg_parms[i + 1], dbg_parms[i + 2],
2013 dbg_parms[i + 3]);
2014 }
2015 }
2016}
2017
2018void
2019kdebug_lookup_gen_events(long *dbg_parms, int dbg_namelen, void *dp,
2020 bool lookup)
2021{
2022 kdebug_vfs_lookup(dbg_parms, dbg_namelen, dp,
2023 lookup ? KDBG_VFS_LOOKUP_FLAG_LOOKUP : 0);
2024}
2025
2026void
2027kdebug_lookup(vnode_t dp, struct componentname *cnp)
2028{
2029 int dbg_namelen;
2030 char *dbg_nameptr;
2031 long dbg_parms[NUMPARMS];
2032
2033 /* Collect the pathname for tracing */
2034 dbg_namelen = (cnp->cn_nameptr - cnp->cn_pnbuf) + cnp->cn_namelen;
2035 dbg_nameptr = cnp->cn_nameptr + cnp->cn_namelen;
2036
2037 if (dbg_namelen > (int)sizeof(dbg_parms)) {
2038 dbg_namelen = sizeof(dbg_parms);
2039 }
2040 dbg_nameptr -= dbg_namelen;
2041
2042 /* Copy the (possibly truncated) path itself */
2043 memcpy(dbg_parms, dbg_nameptr, dbg_namelen);
2044
2045 /* Pad with '\0' or '>' */
2046 if (dbg_namelen < (int)sizeof(dbg_parms)) {
2047 memset((char *)dbg_parms + dbg_namelen,
2048 *(cnp->cn_nameptr + cnp->cn_namelen) ? '>' : 0,
2049 sizeof(dbg_parms) - dbg_namelen);
2050 }
2051 kdebug_vfs_lookup(dbg_parms, dbg_namelen, (void *)dp,
2052 KDBG_VFS_LOOKUP_FLAG_LOOKUP);
2053}
2054
2055#else /* (KDEBUG_LEVEL >= KDEBUG_LEVEL_IST) */
2056
2057void
2058kdebug_vfs_lookup(long *dbg_parms __unused, int dbg_namelen __unused,
2059 void *dp __unused, __unused uint32_t flags)
2060{
2061}
2062
2063static void
2064kdebug_lookup(struct vnode *dp __unused, struct componentname *cnp __unused)
2065{
2066}
2067#endif /* (KDEBUG_LEVEL >= KDEBUG_LEVEL_IST) */
2068
2069int
2070vfs_getbyid(fsid_t *fsid, ino64_t ino, vnode_t *vpp, vfs_context_t ctx)
2071{
2072 mount_t mp;
2073 int error;
2074
2075 mp = mount_lookupby_volfsid(fsid->val[0], 1);
2076 if (mp == NULL) {
2077 return EINVAL;
2078 }
2079
2080 /* Get the target vnode. */
2081 if (ino == 2) {
2082 error = VFS_ROOT(mp, vpp, ctx);
2083 } else {
2084 error = VFS_VGET(mp, ino, vpp, ctx);
2085 }
2086
2087 vfs_unbusy(mp);
2088 return error;
2089}
2090/*
2091 * Obtain the real path from a legacy volfs style path.
2092 *
2093 * Valid formats of input path:
2094 *
2095 * "555/@"
2096 * "555/2"
2097 * "555/123456"
2098 * "555/123456/foobar"
2099 *
2100 * Where:
2101 * 555 represents the volfs file system id
2102 * '@' and '2' are aliases to the root of a file system
2103 * 123456 represents a file id
2104 * "foobar" represents a file name
2105 */
2106#if CONFIG_VOLFS
2107static int
2108vfs_getrealpath(const char * path, char * realpath, size_t bufsize, vfs_context_t ctx)
2109{
2110 vnode_t vp;
2111 struct mount *mp = NULL;
2112 char *str;
2113 char ch;
2114 uint32_t id;
2115 ino64_t ino;
2116 int error;
2117 int length;
2118
2119 /* Get file system id and move str to next component. */
2120 id = strtoul(path, &str, 10);
2121 if (id == 0 || str[0] != '/') {
2122 return EINVAL;
2123 }
2124 while (*str == '/') {
2125 str++;
2126 }
2127 ch = *str;
2128
2129 mp = mount_lookupby_volfsid(id, 1);
2130 if (mp == NULL) {
2131 return EINVAL; /* unexpected failure */
2132 }
2133 /* Check for an alias to a file system root. */
2134 if (ch == '@' && str[1] == '\0') {
2135 ino = 2;
2136 str++;
2137 } else {
2138 /* Get file id and move str to next component. */
2139 ino = strtouq(str, &str, 10);
2140 }
2141
2142 /* Get the target vnode. */
2143 if (ino == 2) {
2144 struct vfs_attr vfsattr;
2145 int use_vfs_root = TRUE;
2146
2147 VFSATTR_INIT(&vfsattr);
2148 VFSATTR_WANTED(&vfsattr, f_capabilities);
2149 if (vfs_getattr(mp, &vfsattr, vfs_context_kernel()) == 0 &&
2150 VFSATTR_IS_SUPPORTED(&vfsattr, f_capabilities)) {
2151 if ((vfsattr.f_capabilities.capabilities[VOL_CAPABILITIES_FORMAT] & VOL_CAP_FMT_VOL_GROUPS) &&
2152 (vfsattr.f_capabilities.valid[VOL_CAPABILITIES_FORMAT] & VOL_CAP_FMT_VOL_GROUPS)) {
2153 use_vfs_root = FALSE;
2154 }
2155 }
2156
2157 if (use_vfs_root) {
2158 error = VFS_ROOT(mp, &vp, ctx);
2159 } else {
2160 error = VFS_VGET(mp, ino, &vp, ctx);
2161 }
2162 } else {
2163 error = VFS_VGET(mp, ino, &vp, ctx);
2164 }
2165 vfs_unbusy(mp);
2166 if (error) {
2167 goto out;
2168 }
2169 realpath[0] = '\0';
2170
2171 /* Get the absolute path to this vnode. */
2172 error = build_path(vp, realpath, bufsize, &length, 0, ctx);
2173 vnode_put(vp);
2174
2175 if (error == 0 && *str != '\0') {
2176 int attempt = strlcat(realpath, str, MAXPATHLEN);
2177 if (attempt > MAXPATHLEN) {
2178 error = ENAMETOOLONG;
2179 }
2180 }
2181out:
2182 return error;
2183}
2184#endif
2185
2186void
2187lookup_compound_vnop_post_hook(int error, vnode_t dvp, vnode_t vp, struct nameidata *ndp, int did_create)
2188{
2189 if (error == 0 && vp == NULLVP) {
2190 panic("NULL vp with error == 0.\n");
2191 }
2192
2193 /*
2194 * We don't want to do any of this if we didn't use the compound vnop
2195 * to perform the lookup... i.e. if we're allowing and using the legacy pattern,
2196 * where we did a full lookup.
2197 */
2198 if ((ndp->ni_flag & NAMEI_COMPOUND_OP_MASK) == 0) {
2199 return;
2200 }
2201
2202 /*
2203 * If we're going to continue the lookup, we'll handle
2204 * all lookup-related updates at that time.
2205 */
2206 if (error == EKEEPLOOKING) {
2207 return;
2208 }
2209
2210 /*
2211 * Only audit or update cache for *found* vnodes. For creation
2212 * neither would happen in the non-compound-vnop case.
2213 */
2214 if ((vp != NULLVP) && !did_create) {
2215 /*
2216 * If MAKEENTRY isn't set, and we've done a successful compound VNOP,
2217 * then we certainly don't want to update cache or identity.
2218 */
2219 if ((error != 0) || (ndp->ni_cnd.cn_flags & MAKEENTRY)) {
2220 lookup_consider_update_cache(dvp, vp, &ndp->ni_cnd, ndp->ni_ncgeneration);
2221 }
2222 if (ndp->ni_cnd.cn_flags & AUDITVNPATH1) {
2223 AUDIT_ARG(vnpath, vp, ARG_VNODE1);
2224 } else if (ndp->ni_cnd.cn_flags & AUDITVNPATH2) {
2225 AUDIT_ARG(vnpath, vp, ARG_VNODE2);
2226 }
2227 }
2228
2229 /*
2230 * If you created (whether you opened or not), cut a lookup tracepoint
2231 * for the parent dir (as would happen without a compound vnop). Note: we may need
2232 * a vnode despite failure in this case!
2233 *
2234 * If you did not create:
2235 * Found child (succeeded or not): cut a tracepoint for the child.
2236 * Did not find child: cut a tracepoint with the parent.
2237 */
2238 if (kdebug_enable) {
2239 kdebug_lookup(vp ? vp : dvp, &ndp->ni_cnd);
2240 }
2241}