Annotation of src/sys/kern/vfs_lookup.c, Revision 1.208.6.2
1.208.6.2! martin 1: /* $NetBSD$ */
1.13 cgd 2:
1.10 cgd 3: /*
1.12 mycroft 4: * Copyright (c) 1982, 1986, 1989, 1993
5: * The Regents of the University of California. All rights reserved.
1.10 cgd 6: * (c) UNIX System Laboratories, Inc.
7: * All or some portions of this file are derived from material licensed
8: * to the University of California by American Telephone and Telegraph
9: * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10: * the permission of UNIX System Laboratories, Inc.
11: *
12: * Redistribution and use in source and binary forms, with or without
13: * modification, are permitted provided that the following conditions
14: * are met:
15: * 1. Redistributions of source code must retain the above copyright
16: * notice, this list of conditions and the following disclaimer.
17: * 2. Redistributions in binary form must reproduce the above copyright
18: * notice, this list of conditions and the following disclaimer in the
19: * documentation and/or other materials provided with the distribution.
1.49 agc 20: * 3. Neither the name of the University nor the names of its contributors
1.10 cgd 21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: *
1.26 fvdl 36: * @(#)vfs_lookup.c 8.10 (Berkeley) 5/27/95
1.10 cgd 37: */
1.38 lukem 38:
39: #include <sys/cdefs.h>
1.208.6.2! martin 40: __KERNEL_RCSID(0, "$NetBSD$");
1.27 thorpej 41:
1.203 pooka 42: #ifdef _KERNEL_OPT
1.67 chs 43: #include "opt_magiclinks.h"
1.203 pooka 44: #endif
1.10 cgd 45:
46: #include <sys/param.h>
1.15 cgd 47: #include <sys/systm.h>
1.61 thorpej 48: #include <sys/kernel.h>
1.10 cgd 49: #include <sys/syslimits.h>
50: #include <sys/time.h>
51: #include <sys/namei.h>
52: #include <sys/vnode.h>
1.208.6.2! martin 53: #include <sys/vnode_impl.h>
1.10 cgd 54: #include <sys/mount.h>
55: #include <sys/errno.h>
1.39 lukem 56: #include <sys/filedesc.h>
57: #include <sys/hash.h>
1.10 cgd 58: #include <sys/proc.h>
1.40 wrstuden 59: #include <sys/syslog.h>
1.70 elad 60: #include <sys/kauth.h>
1.97 ad 61: #include <sys/ktrace.h>
1.192 christos 62: #include <sys/dirent.h>
1.12 mycroft 63:
1.67 chs 64: #ifndef MAGICLINKS
65: #define MAGICLINKS 0
66: #endif
67:
68: int vfs_magiclinks = MAGICLINKS;
69:
1.191 christos 70: __CTASSERT(MAXNAMLEN == NAME_MAX);
71:
1.10 cgd 72: /*
1.61 thorpej 73: * Substitute replacement text for 'magic' strings in symlinks.
74: * Returns 0 if successful, and returns non-zero if an error
75: * occurs. (Currently, the only possible error is running out
76: * of temporary pathname space.)
77: *
78: * Looks for "@<string>" and "@<string>/", where <string> is a
79: * recognized 'magic' string. Replaces the "@<string>" with the
80: * appropriate replacement text. (Note that in some cases the
81: * replacement text may have zero length.)
82: *
83: * This would have been table driven, but the variance in
84: * replacement strings (and replacement string lengths) made
85: * that impractical.
86: */
1.63 thorpej 87: #define VNL(x) \
88: (sizeof(x) - 1)
89:
90: #define VO '{'
91: #define VC '}'
92:
1.61 thorpej 93: #define MATCH(str) \
1.63 thorpej 94: ((termchar == '/' && i + VNL(str) == *len) || \
95: (i + VNL(str) < *len && \
96: cp[i + VNL(str)] == termchar)) && \
97: !strncmp((str), &cp[i], VNL(str))
1.61 thorpej 98:
99: #define SUBSTITUTE(m, s, sl) \
1.115 christos 100: if ((newlen + (sl)) >= MAXPATHLEN) \
101: return 1; \
1.63 thorpej 102: i += VNL(m); \
103: if (termchar != '/') \
104: i++; \
1.115 christos 105: (void)memcpy(&tmp[newlen], (s), (sl)); \
1.63 thorpej 106: newlen += (sl); \
107: change = 1; \
108: termchar = '/';
1.61 thorpej 109:
110: static int
1.115 christos 111: symlink_magic(struct proc *p, char *cp, size_t *len)
1.61 thorpej 112: {
1.66 yamt 113: char *tmp;
1.115 christos 114: size_t change, i, newlen, slen;
115: char termchar = '/';
116: char idtmp[11]; /* enough for 32 bit *unsigned* integer */
1.101 mjf 117:
1.61 thorpej 118:
1.66 yamt 119: tmp = PNBUF_GET();
1.61 thorpej 120: for (change = i = newlen = 0; i < *len; ) {
1.63 thorpej 121: if (cp[i] != '@') {
1.61 thorpej 122: tmp[newlen++] = cp[i++];
1.63 thorpej 123: continue;
124: }
125:
126: i++;
127:
128: /* Check for @{var} syntax. */
129: if (cp[i] == VO) {
130: termchar = VC;
1.61 thorpej 131: i++;
1.63 thorpej 132: }
133:
134: /*
135: * The following checks should be ordered according
136: * to frequency of use.
137: */
138: if (MATCH("machine_arch")) {
1.115 christos 139: slen = VNL(MACHINE_ARCH);
140: SUBSTITUTE("machine_arch", MACHINE_ARCH, slen);
1.63 thorpej 141: } else if (MATCH("machine")) {
1.115 christos 142: slen = VNL(MACHINE);
143: SUBSTITUTE("machine", MACHINE, slen);
1.63 thorpej 144: } else if (MATCH("hostname")) {
1.115 christos 145: SUBSTITUTE("hostname", hostname, hostnamelen);
1.63 thorpej 146: } else if (MATCH("osrelease")) {
1.115 christos 147: slen = strlen(osrelease);
148: SUBSTITUTE("osrelease", osrelease, slen);
1.63 thorpej 149: } else if (MATCH("emul")) {
1.115 christos 150: slen = strlen(p->p_emul->e_name);
151: SUBSTITUTE("emul", p->p_emul->e_name, slen);
1.63 thorpej 152: } else if (MATCH("kernel_ident")) {
1.115 christos 153: slen = strlen(kernel_ident);
154: SUBSTITUTE("kernel_ident", kernel_ident, slen);
1.63 thorpej 155: } else if (MATCH("domainname")) {
1.115 christos 156: SUBSTITUTE("domainname", domainname, domainnamelen);
1.63 thorpej 157: } else if (MATCH("ostype")) {
1.115 christos 158: slen = strlen(ostype);
159: SUBSTITUTE("ostype", ostype, slen);
1.72 elad 160: } else if (MATCH("uid")) {
1.115 christos 161: slen = snprintf(idtmp, sizeof(idtmp), "%u",
1.72 elad 162: kauth_cred_geteuid(kauth_cred_get()));
1.115 christos 163: SUBSTITUTE("uid", idtmp, slen);
1.101 mjf 164: } else if (MATCH("ruid")) {
1.115 christos 165: slen = snprintf(idtmp, sizeof(idtmp), "%u",
1.101 mjf 166: kauth_cred_getuid(kauth_cred_get()));
1.115 christos 167: SUBSTITUTE("ruid", idtmp, slen);
168: } else if (MATCH("gid")) {
169: slen = snprintf(idtmp, sizeof(idtmp), "%u",
170: kauth_cred_getegid(kauth_cred_get()));
171: SUBSTITUTE("gid", idtmp, slen);
172: } else if (MATCH("rgid")) {
173: slen = snprintf(idtmp, sizeof(idtmp), "%u",
174: kauth_cred_getgid(kauth_cred_get()));
175: SUBSTITUTE("rgid", idtmp, slen);
1.63 thorpej 176: } else {
177: tmp[newlen++] = '@';
178: if (termchar == VC)
179: tmp[newlen++] = VO;
1.61 thorpej 180: }
181: }
182:
1.66 yamt 183: if (change) {
1.115 christos 184: (void)memcpy(cp, tmp, newlen);
1.66 yamt 185: *len = newlen;
186: }
187: PNBUF_PUT(tmp);
1.61 thorpej 188:
1.115 christos 189: return 0;
1.61 thorpej 190: }
191:
1.63 thorpej 192: #undef VNL
193: #undef VO
194: #undef VC
195: #undef MATCH
196: #undef SUBSTITUTE
197:
1.123 dholland 198: ////////////////////////////////////////////////////////////
199:
200: /*
1.197 dholland 201: * Determine the namei hash (for the namecache) for name.
1.131 dholland 202: * If *ep != NULL, hash from name to ep-1.
203: * If *ep == NULL, hash from name until the first NUL or '/', and
204: * return the location of this termination character in *ep.
205: *
206: * This function returns an equivalent hash to the MI hash32_strn().
207: * The latter isn't used because in the *ep == NULL case, determining
208: * the length of the string to the first NUL or `/' and then calling
209: * hash32_strn() involves unnecessary double-handling of the data.
210: */
211: uint32_t
212: namei_hash(const char *name, const char **ep)
213: {
214: uint32_t hash;
215:
216: hash = HASH32_STR_INIT;
217: if (*ep != NULL) {
218: for (; name < *ep; name++)
219: hash = hash * 33 + *(const uint8_t *)name;
220: } else {
221: for (; *name != '\0' && *name != '/'; name++)
222: hash = hash * 33 + *(const uint8_t *)name;
223: *ep = name;
224: }
225: return (hash + (hash >> 5));
226: }
227:
1.197 dholland 228: /*
229: * Find the end of the first path component in NAME and return its
230: * length.
231: */
232: static size_t
233: namei_getcomponent(const char *name)
234: {
235: size_t pos;
236:
237: pos = 0;
238: while (name[pos] != '\0' && name[pos] != '/') {
239: pos++;
240: }
241: return pos;
242: }
243:
1.131 dholland 244: ////////////////////////////////////////////////////////////
245:
246: /*
1.123 dholland 247: * Sealed abstraction for pathnames.
248: *
249: * System-call-layer level code that is going to call namei should
250: * first create a pathbuf and adjust all the bells and whistles on it
1.176 dholland 251: * as needed by context.
1.123 dholland 252: */
253:
254: struct pathbuf {
255: char *pb_path;
256: char *pb_pathcopy;
257: unsigned pb_pathcopyuses;
258: };
259:
260: static struct pathbuf *
261: pathbuf_create_raw(void)
262: {
263: struct pathbuf *pb;
264:
265: pb = kmem_alloc(sizeof(*pb), KM_SLEEP);
266: pb->pb_path = PNBUF_GET();
267: if (pb->pb_path == NULL) {
268: kmem_free(pb, sizeof(*pb));
269: return NULL;
270: }
271: pb->pb_pathcopy = NULL;
272: pb->pb_pathcopyuses = 0;
273: return pb;
274: }
275:
276: void
277: pathbuf_destroy(struct pathbuf *pb)
278: {
279: KASSERT(pb->pb_pathcopyuses == 0);
280: KASSERT(pb->pb_pathcopy == NULL);
281: PNBUF_PUT(pb->pb_path);
282: kmem_free(pb, sizeof(*pb));
283: }
284:
285: struct pathbuf *
1.124 dholland 286: pathbuf_assimilate(char *pnbuf)
287: {
288: struct pathbuf *pb;
289:
290: pb = kmem_alloc(sizeof(*pb), KM_SLEEP);
291: pb->pb_path = pnbuf;
292: pb->pb_pathcopy = NULL;
293: pb->pb_pathcopyuses = 0;
294: return pb;
295: }
296:
297: struct pathbuf *
1.123 dholland 298: pathbuf_create(const char *path)
299: {
300: struct pathbuf *pb;
301: int error;
302:
303: pb = pathbuf_create_raw();
304: if (pb == NULL) {
305: return NULL;
306: }
307: error = copystr(path, pb->pb_path, PATH_MAX, NULL);
308: if (error != 0) {
309: KASSERT(!"kernel path too long in pathbuf_create");
310: /* make sure it's null-terminated, just in case */
311: pb->pb_path[PATH_MAX-1] = '\0';
312: }
313: return pb;
314: }
315:
316: int
317: pathbuf_copyin(const char *userpath, struct pathbuf **ret)
318: {
319: struct pathbuf *pb;
320: int error;
321:
322: pb = pathbuf_create_raw();
323: if (pb == NULL) {
324: return ENOMEM;
325: }
326: error = copyinstr(userpath, pb->pb_path, PATH_MAX, NULL);
327: if (error) {
328: pathbuf_destroy(pb);
329: return error;
330: }
331: *ret = pb;
332: return 0;
333: }
334:
335: /*
1.173 dholland 336: * XXX should not exist:
1.176 dholland 337: * 1. whether a pointer is kernel or user should be statically checkable.
1.173 dholland 338: * 2. copyin should be handled by the upper part of the syscall layer,
339: * not in here.
1.123 dholland 340: */
341: int
342: pathbuf_maybe_copyin(const char *path, enum uio_seg seg, struct pathbuf **ret)
343: {
344: if (seg == UIO_USERSPACE) {
345: return pathbuf_copyin(path, ret);
346: } else {
347: *ret = pathbuf_create(path);
348: if (*ret == NULL) {
349: return ENOMEM;
350: }
351: return 0;
352: }
353: }
354:
355: /*
356: * Get a copy of the path buffer as it currently exists. If this is
357: * called after namei starts the results may be arbitrary.
358: */
359: void
360: pathbuf_copystring(const struct pathbuf *pb, char *buf, size_t maxlen)
361: {
362: strlcpy(buf, pb->pb_path, maxlen);
363: }
364:
365: /*
366: * These two functions allow access to a saved copy of the original
367: * path string. The first copy should be gotten before namei is
368: * called. Each copy that is gotten should be put back.
369: */
370:
371: const char *
372: pathbuf_stringcopy_get(struct pathbuf *pb)
373: {
374: if (pb->pb_pathcopyuses == 0) {
375: pb->pb_pathcopy = PNBUF_GET();
376: strcpy(pb->pb_pathcopy, pb->pb_path);
377: }
378: pb->pb_pathcopyuses++;
379: return pb->pb_pathcopy;
380: }
381:
382: void
383: pathbuf_stringcopy_put(struct pathbuf *pb, const char *str)
384: {
385: KASSERT(str == pb->pb_pathcopy);
386: KASSERT(pb->pb_pathcopyuses > 0);
387: pb->pb_pathcopyuses--;
388: if (pb->pb_pathcopyuses == 0) {
389: PNBUF_PUT(pb->pb_pathcopy);
390: pb->pb_pathcopy = NULL;
391: }
392: }
393:
394:
395: ////////////////////////////////////////////////////////////
396:
1.61 thorpej 397: /*
1.173 dholland 398: * namei: convert a pathname into a pointer to a (maybe-locked) vnode,
399: * and maybe also its parent directory vnode, and assorted other guff.
400: * See namei(9) for the interface documentation.
401: *
1.10 cgd 402: *
403: * The FOLLOW flag is set when symbolic links are to be followed
404: * when they occur at the end of the name translation process.
405: * Symbolic links are always followed for all other pathname
406: * components other than the last.
407: *
408: * The segflg defines whether the name is to be copied from user
409: * space or kernel space.
410: *
411: * Overall outline of namei:
412: *
413: * copy in name
414: * get starting directory
415: * while (!done && !error) {
416: * call lookup to search path.
417: * if symbolic link, massage name in buffer and continue
418: * }
419: */
1.117 dholland 420:
421: /*
1.173 dholland 422: * Search a pathname.
423: * This is a very central and rather complicated routine.
424: *
425: * The pathname is pointed to by ni_ptr and is of length ni_pathlen.
426: * The starting directory is passed in. The pathname is descended
427: * until done, or a symbolic link is encountered. The variable ni_more
428: * is clear if the path is completed; it is set to one if a symbolic
429: * link needing interpretation is encountered.
430: *
431: * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on
432: * whether the name is to be looked up, created, renamed, or deleted.
433: * When CREATE, RENAME, or DELETE is specified, information usable in
434: * creating, renaming, or deleting a directory entry may be calculated.
435: * If flag has LOCKPARENT or'ed into it, the parent directory is returned
436: * locked. Otherwise the parent directory is not returned. If the target
437: * of the pathname exists and LOCKLEAF is or'ed into the flag the target
438: * is returned locked, otherwise it is returned unlocked. When creating
439: * or renaming and LOCKPARENT is specified, the target may not be ".".
440: * When deleting and LOCKPARENT is specified, the target may be ".".
441: *
442: * Overall outline of lookup:
443: *
444: * dirloop:
445: * identify next component of name at ndp->ni_ptr
446: * handle degenerate case where name is null string
447: * if .. and crossing mount points and on mounted filesys, find parent
448: * call VOP_LOOKUP routine for next component name
449: * directory vnode returned in ni_dvp, locked.
450: * component vnode returned in ni_vp (if it exists), locked.
451: * if result vnode is mounted on and crossing mount points,
452: * find mounted on vnode
453: * if more components of name, do next level at dirloop
454: * return the answer in ni_vp, locked if LOCKLEAF set
455: * if LOCKPARENT set, return locked parent in ni_dvp
456: */
457:
458:
459: /*
1.117 dholland 460: * Internal state for a namei operation.
1.173 dholland 461: *
462: * cnp is always equal to &ndp->ni_cnp.
1.117 dholland 463: */
464: struct namei_state {
465: struct nameidata *ndp;
466: struct componentname *cnp;
467:
1.118 dholland 468: int docache; /* == 0 do not cache last component */
469: int rdonly; /* lookup read-only flag bit */
470: int slashes;
1.137 dholland 471:
472: unsigned attempt_retry:1; /* true if error allows emul retry */
1.208.6.1 christos 473: unsigned root_referenced:1; /* true if ndp->ni_rootdir and
474: ndp->ni_erootdir were referenced */
1.117 dholland 475: };
476:
1.118 dholland 477:
1.117 dholland 478: /*
479: * Initialize the namei working state.
480: */
481: static void
482: namei_init(struct namei_state *state, struct nameidata *ndp)
483: {
1.202 riastrad 484:
1.117 dholland 485: state->ndp = ndp;
486: state->cnp = &ndp->ni_cnd;
487:
1.118 dholland 488: state->docache = 0;
489: state->rdonly = 0;
490: state->slashes = 0;
1.133 dholland 491:
1.208.6.1 christos 492: state->root_referenced = 0;
493:
1.205 riastrad 494: KASSERTMSG((state->cnp->cn_cred != NULL), "namei: bad cred/proc");
495: KASSERTMSG(((state->cnp->cn_nameiop & (~OPMASK)) == 0),
496: "namei: nameiop contaminated with flags: %08"PRIx32,
497: state->cnp->cn_nameiop);
498: KASSERTMSG(((state->cnp->cn_flags & OPMASK) == 0),
499: "name: flags contaminated with nameiops: %08"PRIx32,
500: state->cnp->cn_flags);
1.133 dholland 501:
502: /*
503: * The buffer for name translation shall be the one inside the
504: * pathbuf.
505: */
506: state->ndp->ni_pnbuf = state->ndp->ni_pathbuf->pb_path;
1.117 dholland 507: }
508:
509: /*
510: * Clean up the working namei state, leaving things ready for return
511: * from namei.
512: */
513: static void
514: namei_cleanup(struct namei_state *state)
515: {
516: KASSERT(state->cnp == &state->ndp->ni_cnd);
517:
1.208.6.1 christos 518: if (state->root_referenced) {
519: vrele(state->ndp->ni_rootdir);
520: if (state->ndp->ni_erootdir != NULL)
521: vrele(state->ndp->ni_erootdir);
522: }
1.117 dholland 523: }
524:
525: //////////////////////////////
526:
527: /*
1.133 dholland 528: * Get the directory context.
529: * Initializes the rootdir and erootdir state and returns a reference
530: * to the starting dir.
1.117 dholland 531: */
1.133 dholland 532: static struct vnode *
1.196 dholland 533: namei_getstartdir(struct namei_state *state)
1.117 dholland 534: {
535: struct nameidata *ndp = state->ndp;
536: struct componentname *cnp = state->cnp;
537: struct cwdinfo *cwdi; /* pointer to cwd state */
1.133 dholland 538: struct vnode *rootdir, *erootdir, *curdir, *startdir;
1.117 dholland 539:
1.208.6.1 christos 540: if (state->root_referenced) {
541: vrele(state->ndp->ni_rootdir);
542: if (state->ndp->ni_erootdir != NULL)
543: vrele(state->ndp->ni_erootdir);
544: state->root_referenced = 0;
545: }
546:
1.208.6.2! martin 547: /* NB: must not block while inspecting the cwdinfo. */
! 548: cwdi = cwdenter(RW_READER);
1.21 kleink 549:
1.133 dholland 550: /* root dir */
551: if (cwdi->cwdi_rdir == NULL || (cnp->cn_flags & NOCHROOT)) {
552: rootdir = rootvnode;
553: } else {
554: rootdir = cwdi->cwdi_rdir;
1.10 cgd 555: }
1.123 dholland 556:
1.133 dholland 557: /* emulation root dir, if any */
558: if ((cnp->cn_flags & TRYEMULROOT) == 0) {
559: /* if we don't want it, don't fetch it */
560: erootdir = NULL;
561: } else if (cnp->cn_flags & EMULROOTSET) {
562: /* explicitly set emulroot; "/../" doesn't override this */
563: erootdir = ndp->ni_erootdir;
564: } else if (!strncmp(ndp->ni_pnbuf, "/../", 4)) {
565: /* explicit reference to real rootdir */
566: erootdir = NULL;
567: } else {
568: /* may be null */
569: erootdir = cwdi->cwdi_edir;
570: }
1.21 kleink 571:
1.133 dholland 572: /* current dir */
1.196 dholland 573: curdir = cwdi->cwdi_cdir;
1.85 dsl 574:
1.133 dholland 575: if (ndp->ni_pnbuf[0] != '/') {
1.198 dholland 576: if (ndp->ni_atdir != NULL) {
577: startdir = ndp->ni_atdir;
1.196 dholland 578: } else {
579: startdir = curdir;
580: }
1.133 dholland 581: erootdir = NULL;
582: } else if (cnp->cn_flags & TRYEMULROOT && erootdir != NULL) {
583: startdir = erootdir;
1.23 mycroft 584: } else {
1.133 dholland 585: startdir = rootdir;
586: erootdir = NULL;
1.23 mycroft 587: }
1.133 dholland 588:
589: state->ndp->ni_rootdir = rootdir;
590: state->ndp->ni_erootdir = erootdir;
1.117 dholland 591:
592: /*
1.133 dholland 593: * Get a reference to the start dir so we can safely unlock cwdi.
594: *
1.208.6.1 christos 595: * Must hold references to rootdir and erootdir while we're running.
596: * A multithreaded process may chroot during namei.
1.117 dholland 597: */
1.133 dholland 598: vref(startdir);
1.208.6.1 christos 599: vref(state->ndp->ni_rootdir);
600: if (state->ndp->ni_erootdir != NULL)
601: vref(state->ndp->ni_erootdir);
602: state->root_referenced = 1;
1.133 dholland 603:
1.208.6.2! martin 604: cwdexit(cwdi);
1.133 dholland 605: return startdir;
606: }
607:
608: /*
609: * Get the directory context for the nfsd case, in parallel to
610: * getstartdir. Initializes the rootdir and erootdir state and
1.173 dholland 611: * returns a reference to the passed-in starting dir.
1.133 dholland 612: */
613: static struct vnode *
1.196 dholland 614: namei_getstartdir_for_nfsd(struct namei_state *state)
1.133 dholland 615: {
1.198 dholland 616: KASSERT(state->ndp->ni_atdir != NULL);
1.193 dholland 617:
1.133 dholland 618: /* always use the real root, and never set an emulation root */
619: state->ndp->ni_rootdir = rootvnode;
620: state->ndp->ni_erootdir = NULL;
621:
1.198 dholland 622: vref(state->ndp->ni_atdir);
1.208.6.1 christos 623: KASSERT(! state->root_referenced);
624: vref(state->ndp->ni_rootdir);
625: state->root_referenced = 1;
1.198 dholland 626: return state->ndp->ni_atdir;
1.133 dholland 627: }
628:
629:
630: /*
631: * Ktrace the namei operation.
632: */
633: static void
634: namei_ktrace(struct namei_state *state)
635: {
636: struct nameidata *ndp = state->ndp;
637: struct componentname *cnp = state->cnp;
638: struct lwp *self = curlwp; /* thread doing namei() */
639: const char *emul_path;
640:
1.97 ad 641: if (ktrpoint(KTR_NAMEI)) {
1.90 dsl 642: if (ndp->ni_erootdir != NULL) {
1.89 dsl 643: /*
644: * To make any sense, the trace entry need to have the
645: * text of the emulation path prepended.
646: * Usually we can get this from the current process,
647: * but when called from emul_find_interp() it is only
648: * in the exec_package - so we get it passed in ni_next
649: * (this is a hack).
650: */
1.88 dsl 651: if (cnp->cn_flags & EMULROOTSET)
1.89 dsl 652: emul_path = ndp->ni_next;
1.88 dsl 653: else
1.117 dholland 654: emul_path = self->l_proc->p_emul->e_path;
1.97 ad 655: ktrnamei2(emul_path, strlen(emul_path),
1.124 dholland 656: ndp->ni_pnbuf, ndp->ni_pathlen);
1.88 dsl 657: } else
1.124 dholland 658: ktrnamei(ndp->ni_pnbuf, ndp->ni_pathlen);
1.88 dsl 659: }
1.133 dholland 660: }
661:
662: /*
1.166 dholland 663: * Start up namei. Find the root dir and cwd, establish the starting
664: * directory for lookup, and lock it. Also calls ktrace when
1.133 dholland 665: * appropriate.
666: */
667: static int
1.196 dholland 668: namei_start(struct namei_state *state, int isnfsd,
1.140 dholland 669: struct vnode **startdir_ret)
1.133 dholland 670: {
671: struct nameidata *ndp = state->ndp;
1.140 dholland 672: struct vnode *startdir;
1.133 dholland 673:
674: /* length includes null terminator (was originally from copyinstr) */
675: ndp->ni_pathlen = strlen(ndp->ni_pnbuf) + 1;
676:
677: /*
678: * POSIX.1 requirement: "" is not a valid file name.
679: */
680: if (ndp->ni_pathlen == 1) {
681: return ENOENT;
682: }
683:
684: ndp->ni_loopcnt = 0;
685:
686: /* Get starting directory, set up root, and ktrace. */
1.193 dholland 687: if (isnfsd) {
1.196 dholland 688: startdir = namei_getstartdir_for_nfsd(state);
1.133 dholland 689: /* no ktrace */
690: } else {
1.196 dholland 691: startdir = namei_getstartdir(state);
1.133 dholland 692: namei_ktrace(state);
693: }
1.97 ad 694:
1.200 manu 695: /* NDAT may feed us with a non directory namei_getstartdir */
1.208 dholland 696: if (startdir->v_type != VDIR) {
697: vrele(startdir);
1.200 manu 698: return ENOTDIR;
1.208 dholland 699: }
1.200 manu 700:
1.140 dholland 701: *startdir_ret = startdir;
1.117 dholland 702: return 0;
703: }
704:
705: /*
1.173 dholland 706: * Check for being at a symlink that we're going to follow.
1.117 dholland 707: */
708: static inline int
1.144 dholland 709: namei_atsymlink(struct namei_state *state, struct vnode *foundobj)
1.117 dholland 710: {
1.144 dholland 711: return (foundobj->v_type == VLNK) &&
1.139 dholland 712: (state->cnp->cn_flags & (FOLLOW|REQUIREDIR));
1.117 dholland 713: }
714:
715: /*
716: * Follow a symlink.
1.173 dholland 717: *
718: * Updates searchdir. inhibitmagic causes magic symlinks to not be
719: * interpreted; this is used by nfsd.
1.174 jakllsch 720: *
721: * Unlocks foundobj on success (ugh)
1.117 dholland 722: */
723: static inline int
1.141 dholland 724: namei_follow(struct namei_state *state, int inhibitmagic,
1.161 dholland 725: struct vnode *searchdir, struct vnode *foundobj,
1.141 dholland 726: struct vnode **newsearchdir_ret)
1.117 dholland 727: {
728: struct nameidata *ndp = state->ndp;
729: struct componentname *cnp = state->cnp;
730:
731: struct lwp *self = curlwp; /* thread doing namei() */
732: struct iovec aiov; /* uio for reading symbolic links */
733: struct uio auio;
734: char *cp; /* pointer into pathname argument */
735: size_t linklen;
736: int error;
737:
738: if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
739: return ELOOP;
740: }
1.208.6.2! martin 741:
! 742: vn_lock(foundobj, LK_EXCLUSIVE | LK_RETRY);
1.161 dholland 743: if (foundobj->v_mount->mnt_flag & MNT_SYMPERM) {
744: error = VOP_ACCESS(foundobj, VEXEC, cnp->cn_cred);
1.208.6.2! martin 745: if (error != 0) {
! 746: VOP_UNLOCK(foundobj);
1.117 dholland 747: return error;
1.208.6.2! martin 748: }
1.117 dholland 749: }
1.124 dholland 750:
751: /* FUTURE: fix this to not use a second buffer */
752: cp = PNBUF_GET();
1.117 dholland 753: aiov.iov_base = cp;
754: aiov.iov_len = MAXPATHLEN;
755: auio.uio_iov = &aiov;
756: auio.uio_iovcnt = 1;
757: auio.uio_offset = 0;
758: auio.uio_rw = UIO_READ;
759: auio.uio_resid = MAXPATHLEN;
760: UIO_SETUP_SYSSPACE(&auio);
1.161 dholland 761: error = VOP_READLINK(foundobj, &auio, cnp->cn_cred);
1.208.6.2! martin 762: VOP_UNLOCK(foundobj);
1.117 dholland 763: if (error) {
1.124 dholland 764: PNBUF_PUT(cp);
1.117 dholland 765: return error;
766: }
767: linklen = MAXPATHLEN - auio.uio_resid;
768: if (linklen == 0) {
1.124 dholland 769: PNBUF_PUT(cp);
770: return ENOENT;
1.117 dholland 771: }
772:
773: /*
774: * Do symlink substitution, if appropriate, and
775: * check length for potential overflow.
1.134 dholland 776: *
777: * Inhibit symlink substitution for nfsd.
778: * XXX: This is how it was before; is that a bug or a feature?
1.117 dholland 779: */
1.134 dholland 780: if ((!inhibitmagic && vfs_magiclinks &&
1.117 dholland 781: symlink_magic(self->l_proc, cp, &linklen)) ||
782: (linklen + ndp->ni_pathlen >= MAXPATHLEN)) {
1.124 dholland 783: PNBUF_PUT(cp);
784: return ENAMETOOLONG;
1.117 dholland 785: }
786: if (ndp->ni_pathlen > 1) {
1.124 dholland 787: /* includes a null-terminator */
1.117 dholland 788: memcpy(cp + linklen, ndp->ni_next, ndp->ni_pathlen);
1.124 dholland 789: } else {
790: cp[linklen] = '\0';
791: }
1.117 dholland 792: ndp->ni_pathlen += linklen;
1.124 dholland 793: memcpy(ndp->ni_pnbuf, cp, ndp->ni_pathlen);
794: PNBUF_PUT(cp);
1.167 dholland 795:
796: /* we're now starting from the beginning of the buffer again */
797: cnp->cn_nameptr = ndp->ni_pnbuf;
1.117 dholland 798:
799: /*
800: * Check if root directory should replace current directory.
801: */
1.124 dholland 802: if (ndp->ni_pnbuf[0] == '/') {
1.208.6.2! martin 803: vrele(searchdir);
1.117 dholland 804: /* Keep absolute symbolic links inside emulation root */
1.141 dholland 805: searchdir = ndp->ni_erootdir;
806: if (searchdir == NULL ||
1.124 dholland 807: (ndp->ni_pnbuf[1] == '.'
808: && ndp->ni_pnbuf[2] == '.'
809: && ndp->ni_pnbuf[3] == '/')) {
1.117 dholland 810: ndp->ni_erootdir = NULL;
1.141 dholland 811: searchdir = ndp->ni_rootdir;
1.117 dholland 812: }
1.141 dholland 813: vref(searchdir);
1.186 dholland 814: while (cnp->cn_nameptr[0] == '/') {
815: cnp->cn_nameptr++;
816: ndp->ni_pathlen--;
817: }
1.117 dholland 818: }
819:
1.141 dholland 820: *newsearchdir_ret = searchdir;
1.117 dholland 821: return 0;
822: }
823:
824: //////////////////////////////
825:
1.39 lukem 826: /*
1.173 dholland 827: * Inspect the leading path component and update the state accordingly.
1.10 cgd 828: */
1.118 dholland 829: static int
830: lookup_parsepath(struct namei_state *state)
831: {
832: const char *cp; /* pointer into pathname argument */
833:
834: struct componentname *cnp = state->cnp;
835: struct nameidata *ndp = state->ndp;
836:
837: KASSERT(cnp == &ndp->ni_cnd);
838:
1.10 cgd 839: /*
840: * Search a new directory.
841: *
842: * The last component of the filename is left accessible via
1.12 mycroft 843: * cnp->cn_nameptr for callers that need the name. Callers needing
1.10 cgd 844: * the name set the SAVENAME flag. When done, they assume
845: * responsibility for freeing the pathname buffer.
1.127 yamt 846: *
1.147 dholland 847: * At this point, our only vnode state is that the search dir
1.208.6.2! martin 848: * is held.
1.10 cgd 849: */
1.12 mycroft 850: cnp->cn_consume = 0;
1.197 dholland 851: cnp->cn_namelen = namei_getcomponent(cnp->cn_nameptr);
852: cp = cnp->cn_nameptr + cnp->cn_namelen;
1.191 christos 853: if (cnp->cn_namelen > KERNEL_NAME_MAX) {
1.118 dholland 854: return ENAMETOOLONG;
1.10 cgd 855: }
856: #ifdef NAMEI_DIAGNOSTIC
857: { char c = *cp;
1.41 soren 858: *(char *)cp = '\0';
1.19 christos 859: printf("{%s}: ", cnp->cn_nameptr);
1.41 soren 860: *(char *)cp = c; }
1.52 yamt 861: #endif /* NAMEI_DIAGNOSTIC */
1.12 mycroft 862: ndp->ni_pathlen -= cnp->cn_namelen;
1.10 cgd 863: ndp->ni_next = cp;
1.23 mycroft 864: /*
865: * If this component is followed by a slash, then move the pointer to
866: * the next component forward, and remember that this component must be
867: * a directory.
868: */
869: if (*cp == '/') {
870: do {
871: cp++;
872: } while (*cp == '/');
1.118 dholland 873: state->slashes = cp - ndp->ni_next;
874: ndp->ni_pathlen -= state->slashes;
1.23 mycroft 875: ndp->ni_next = cp;
876: cnp->cn_flags |= REQUIREDIR;
877: } else {
1.118 dholland 878: state->slashes = 0;
1.23 mycroft 879: cnp->cn_flags &= ~REQUIREDIR;
880: }
881: /*
882: * We do special processing on the last component, whether or not it's
883: * a directory. Cache all intervening lookups, but not the final one.
884: */
885: if (*cp == '\0') {
1.118 dholland 886: if (state->docache)
1.23 mycroft 887: cnp->cn_flags |= MAKEENTRY;
888: else
889: cnp->cn_flags &= ~MAKEENTRY;
890: cnp->cn_flags |= ISLASTCN;
891: } else {
892: cnp->cn_flags |= MAKEENTRY;
893: cnp->cn_flags &= ~ISLASTCN;
894: }
1.12 mycroft 895: if (cnp->cn_namelen == 2 &&
896: cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.')
897: cnp->cn_flags |= ISDOTDOT;
898: else
899: cnp->cn_flags &= ~ISDOTDOT;
1.10 cgd 900:
1.118 dholland 901: return 0;
902: }
903:
1.173 dholland 904: /*
1.208.6.2! martin 905: * Take care of crossing a mounted-on vnode. On error, foundobj_ret will be
! 906: * vrele'd, but searchdir is left alone.
! 907: */
! 908: static int
! 909: lookup_crossmount(struct namei_state *state,
! 910: struct vnode **searchdir_ret,
! 911: struct vnode **foundobj_ret,
! 912: bool *searchdir_locked)
! 913: {
! 914: struct componentname *cnp = state->cnp;
! 915: struct vnode *foundobj;
! 916: struct vnode *searchdir;
! 917: struct mount *mp;
! 918: int error, lktype;
! 919:
! 920: searchdir = *searchdir_ret;
! 921: foundobj = *foundobj_ret;
! 922: error = 0;
! 923:
! 924: KASSERT((cnp->cn_flags & NOCROSSMOUNT) == 0);
! 925: KASSERT(searchdir != NULL);
! 926:
! 927: /* First, unlock searchdir (oof). */
! 928: if (*searchdir_locked) {
! 929: lktype = VOP_ISLOCKED(searchdir);
! 930: VOP_UNLOCK(searchdir);
! 931: *searchdir_locked = false;
! 932: } else {
! 933: lktype = LK_NONE;
! 934: }
! 935:
! 936: /*
! 937: * Do an unlocked check to see if the vnode has been mounted on; if
! 938: * so find the root of the mounted file system.
! 939: */
! 940: while (foundobj->v_type == VDIR &&
! 941: (mp = foundobj->v_mountedhere) != NULL &&
! 942: (cnp->cn_flags & NOCROSSMOUNT) == 0) {
! 943: KASSERTMSG(searchdir != foundobj, "same vn %p", searchdir);
! 944: /*
! 945: * First get the vnode stable. LK_SHARED works brilliantly
! 946: * here because almost nothing else wants to lock the
! 947: * covered vnode.
! 948: */
! 949: error = vn_lock(foundobj, LK_SHARED);
! 950: if (error != 0) {
! 951: vrele(foundobj);
! 952: *foundobj_ret = NULL;
! 953: break;
! 954: }
! 955:
! 956: /* Then check to see if something is still mounted on it. */
! 957: if ((mp = foundobj->v_mountedhere) == NULL) {
! 958: VOP_UNLOCK(foundobj);
! 959: break;
! 960: }
! 961:
! 962: /* Get a reference to the mountpoint, and ditch foundobj. */
! 963: error = vfs_busy(mp);
! 964: vput(foundobj);
! 965: if (error != 0) {
! 966: *foundobj_ret = NULL;
! 967: break;
! 968: }
! 969:
! 970: /* Now get a reference on the root vnode, and drop mount. */
! 971: error = VFS_ROOT(mp, LK_NONE, &foundobj);
! 972: vfs_unbusy(mp);
! 973: if (error) {
! 974: *foundobj_ret = NULL;
! 975: break;
! 976: }
! 977:
! 978: /*
! 979: * Avoid locking vnodes from two filesystems because
! 980: * it's prone to deadlock, e.g. when using puffs.
! 981: * Also, it isn't a good idea to propagate slowness of
! 982: * a filesystem up to the root directory. For now,
! 983: * only handle the common case, where foundobj is
! 984: * VDIR.
! 985: *
! 986: * In this case set searchdir to null to avoid using
! 987: * it again. It is not correct to set searchdir ==
! 988: * foundobj here as that will confuse the caller.
! 989: * (See PR 40740.)
! 990: */
! 991: if (searchdir == NULL) {
! 992: /* already been here once; do nothing further */
! 993: } else if (foundobj->v_type == VDIR) {
! 994: vrele(searchdir);
! 995: *searchdir_ret = searchdir = NULL;
! 996: *foundobj_ret = foundobj;
! 997: lktype = LK_NONE;
! 998: }
! 999: }
! 1000:
! 1001: /* If searchdir is still around, re-lock it. */
! 1002: if (error == 0 && lktype != LK_NONE) {
! 1003: vn_lock(searchdir, lktype | LK_RETRY);
! 1004: *searchdir_locked = true;
! 1005: }
! 1006: return error;
! 1007: }
! 1008:
! 1009: /*
1.173 dholland 1010: * Call VOP_LOOKUP for a single lookup; return a new search directory
1011: * (used when crossing mountpoints up or searching union mounts down) and
1012: * the found object, which for create operations may be NULL on success.
1.204 dholland 1013: *
1014: * Note that the new search directory may be null, which means the
1015: * searchdir was unlocked and released. This happens in the common case
1016: * when crossing a mount point downwards, in order to avoid coupling
1017: * locks between different file system volumes. Importantly, this can
1018: * happen even if the call fails. (XXX: this is gross and should be
1019: * tidied somehow.)
1.173 dholland 1020: */
1.118 dholland 1021: static int
1.147 dholland 1022: lookup_once(struct namei_state *state,
1023: struct vnode *searchdir,
1.150 dholland 1024: struct vnode **newsearchdir_ret,
1.208.6.2! martin 1025: struct vnode **foundobj_ret,
! 1026: bool *newsearchdir_locked_ret)
1.118 dholland 1027: {
1.163 dholland 1028: struct vnode *tmpvn; /* scratch vnode */
1029: struct vnode *foundobj; /* result */
1.118 dholland 1030: struct lwp *l = curlwp;
1.208.6.2! martin 1031: bool searchdir_locked = false;
! 1032: int error, lktype;
1.118 dholland 1033:
1034: struct componentname *cnp = state->cnp;
1035: struct nameidata *ndp = state->ndp;
1036:
1037: KASSERT(cnp == &ndp->ni_cnd);
1.154 dholland 1038: *newsearchdir_ret = searchdir;
1.118 dholland 1039:
1.10 cgd 1040: /*
1041: * Handle "..": two special cases.
1042: * 1. If at root directory (e.g. after chroot)
1.12 mycroft 1043: * or at absolute root directory
1.10 cgd 1044: * then ignore it so can't get out.
1.85 dsl 1045: * 1a. If at the root of the emulation filesystem go to the real
1046: * root. So "/../<path>" is always absolute.
1047: * 1b. If we have somehow gotten out of a jail, warn
1.40 wrstuden 1048: * and also ignore it so we can't get farther out.
1.10 cgd 1049: * 2. If this vnode is the root of a mounted
1050: * filesystem, then replace it with the
1051: * vnode which was mounted on so we take the
1052: * .. in the other file system.
1053: */
1.12 mycroft 1054: if (cnp->cn_flags & ISDOTDOT) {
1.64 christos 1055: struct proc *p = l->l_proc;
1056:
1.10 cgd 1057: for (;;) {
1.154 dholland 1058: if (searchdir == ndp->ni_rootdir ||
1059: searchdir == rootvnode) {
1.147 dholland 1060: foundobj = searchdir;
1061: vref(foundobj);
1062: *foundobj_ret = foundobj;
1.175 yamt 1063: error = 0;
1064: goto done;
1.40 wrstuden 1065: }
1066: if (ndp->ni_rootdir != rootvnode) {
1067: int retval;
1.73 chs 1068:
1.147 dholland 1069: retval = vn_isunder(searchdir, ndp->ni_rootdir, l);
1.40 wrstuden 1070: if (!retval) {
1071: /* Oops! We got out of jail! */
1072: log(LOG_WARNING,
1073: "chrooted pid %d uid %d (%s) "
1074: "detected outside of its chroot\n",
1.71 ad 1075: p->p_pid, kauth_cred_geteuid(l->l_cred),
1.64 christos 1076: p->p_comm);
1.40 wrstuden 1077: /* Put us at the jail root. */
1.208.6.2! martin 1078: vrele(searchdir);
1.147 dholland 1079: searchdir = NULL;
1080: foundobj = ndp->ni_rootdir;
1081: vref(foundobj);
1082: vref(foundobj);
1.150 dholland 1083: *newsearchdir_ret = foundobj;
1.147 dholland 1084: *foundobj_ret = foundobj;
1.175 yamt 1085: error = 0;
1086: goto done;
1.40 wrstuden 1087: }
1.10 cgd 1088: }
1.147 dholland 1089: if ((searchdir->v_vflag & VV_ROOT) == 0 ||
1.12 mycroft 1090: (cnp->cn_flags & NOCROSSMOUNT))
1.10 cgd 1091: break;
1.163 dholland 1092: tmpvn = searchdir;
1.147 dholland 1093: searchdir = searchdir->v_mount->mnt_vnodecovered;
1.153 dholland 1094: vref(searchdir);
1.208.6.2! martin 1095: vrele(tmpvn);
1.154 dholland 1096: *newsearchdir_ret = searchdir;
1.10 cgd 1097: }
1098: }
1099:
1100: /*
1.208.6.2! martin 1101: * If the file system supports VOP_LOOKUP() with a shared lock, and
! 1102: * we are not making any modifications (nameiop LOOKUP) or this is
! 1103: * not the last component then get a shared lock. Where we can't do
! 1104: * fast-forwarded lookups (for example with layered file systems)
! 1105: * then this is the fallback for reducing lock contention.
! 1106: */
! 1107: if ((searchdir->v_mount->mnt_iflag & IMNT_SHRLOOKUP) != 0 &&
! 1108: (cnp->cn_nameiop == LOOKUP || (cnp->cn_flags & ISLASTCN) == 0)) {
! 1109: lktype = LK_SHARED;
! 1110: } else {
! 1111: lktype = LK_EXCLUSIVE;
! 1112: }
! 1113:
! 1114: /*
1.10 cgd 1115: * We now have a segment name to search for, and a directory to search.
1.208.6.2! martin 1116: * Our vnode state here is that "searchdir" is held.
1.10 cgd 1117: */
1.12 mycroft 1118: unionlookup:
1.148 dholland 1119: foundobj = NULL;
1.208.6.2! martin 1120: if (!searchdir_locked) {
! 1121: vn_lock(searchdir, lktype | LK_RETRY);
! 1122: searchdir_locked = true;
! 1123: }
1.148 dholland 1124: error = VOP_LOOKUP(searchdir, &foundobj, cnp);
1.154 dholland 1125:
1.73 chs 1126: if (error != 0) {
1.205 riastrad 1127: KASSERTMSG((foundobj == NULL),
1128: "leaf `%s' should be empty but is %p",
1129: cnp->cn_nameptr, foundobj);
1.10 cgd 1130: #ifdef NAMEI_DIAGNOSTIC
1.19 christos 1131: printf("not found\n");
1.52 yamt 1132: #endif /* NAMEI_DIAGNOSTIC */
1.208.6.2! martin 1133:
! 1134: /*
! 1135: * If ENOLCK, the file system needs us to retry the lookup
! 1136: * with an exclusive lock. It's likely nothing was found in
! 1137: * cache and/or modifications need to be made.
! 1138: */
! 1139: if (error == ENOLCK) {
! 1140: KASSERT(VOP_ISLOCKED(searchdir) == LK_SHARED);
! 1141: KASSERT(searchdir_locked);
! 1142: if (vn_lock(searchdir, LK_UPGRADE | LK_NOWAIT)) {
! 1143: VOP_UNLOCK(searchdir);
! 1144: searchdir_locked = false;
! 1145: }
! 1146: lktype = LK_EXCLUSIVE;
! 1147: goto unionlookup;
! 1148: }
! 1149:
1.12 mycroft 1150: if ((error == ENOENT) &&
1.147 dholland 1151: (searchdir->v_vflag & VV_ROOT) &&
1152: (searchdir->v_mount->mnt_flag & MNT_UNION)) {
1.163 dholland 1153: tmpvn = searchdir;
1.147 dholland 1154: searchdir = searchdir->v_mount->mnt_vnodecovered;
1.153 dholland 1155: vref(searchdir);
1.163 dholland 1156: vput(tmpvn);
1.208.6.2! martin 1157: searchdir_locked = false;
1.154 dholland 1158: *newsearchdir_ret = searchdir;
1.12 mycroft 1159: goto unionlookup;
1.10 cgd 1160: }
1.12 mycroft 1161:
1.10 cgd 1162: if (error != EJUSTRETURN)
1.175 yamt 1163: goto done;
1.73 chs 1164:
1.10 cgd 1165: /*
1.23 mycroft 1166: * If this was not the last component, or there were trailing
1.51 christos 1167: * slashes, and we are not going to create a directory,
1168: * then the name must exist.
1.23 mycroft 1169: */
1.51 christos 1170: if ((cnp->cn_flags & (REQUIREDIR | CREATEDIR)) == REQUIREDIR) {
1.175 yamt 1171: error = ENOENT;
1172: goto done;
1.23 mycroft 1173: }
1.73 chs 1174:
1.23 mycroft 1175: /*
1.10 cgd 1176: * If creating and at end of pathname, then can consider
1177: * allowing file to be created.
1178: */
1.118 dholland 1179: if (state->rdonly) {
1.175 yamt 1180: error = EROFS;
1181: goto done;
1.10 cgd 1182: }
1.73 chs 1183:
1.10 cgd 1184: /*
1.166 dholland 1185: * We return success and a NULL foundobj to indicate
1186: * that the entry doesn't currently exist, leaving a
1.173 dholland 1187: * pointer to the (normally, locked) directory vnode
1188: * as searchdir.
1.10 cgd 1189: */
1.147 dholland 1190: *foundobj_ret = NULL;
1.175 yamt 1191: error = 0;
1192: goto done;
1.10 cgd 1193: }
1194: #ifdef NAMEI_DIAGNOSTIC
1.19 christos 1195: printf("found\n");
1.52 yamt 1196: #endif /* NAMEI_DIAGNOSTIC */
1.10 cgd 1197:
1.12 mycroft 1198: /*
1.23 mycroft 1199: * Take into account any additional components consumed by the
1200: * underlying filesystem. This will include any trailing slashes after
1201: * the last component consumed.
1.12 mycroft 1202: */
1203: if (cnp->cn_consume > 0) {
1.118 dholland 1204: ndp->ni_pathlen -= cnp->cn_consume - state->slashes;
1205: ndp->ni_next += cnp->cn_consume - state->slashes;
1.12 mycroft 1206: cnp->cn_consume = 0;
1.23 mycroft 1207: if (ndp->ni_next[0] == '\0')
1208: cnp->cn_flags |= ISLASTCN;
1.12 mycroft 1209: }
1210:
1.208.6.2! martin 1211: /* Unlock, unless the caller needs the parent locked. */
! 1212: if (searchdir != NULL) {
! 1213: KASSERT(searchdir_locked);
! 1214: if ((cnp->cn_flags & (ISLASTCN | LOCKPARENT)) !=
! 1215: (ISLASTCN | LOCKPARENT)) {
! 1216: VOP_UNLOCK(searchdir);
! 1217: searchdir_locked = false;
1.201 hannken 1218: }
1.208.6.2! martin 1219: } else {
! 1220: KASSERT(!searchdir_locked);
1.201 hannken 1221: }
1.73 chs 1222:
1.208.6.2! martin 1223: *foundobj_ret = foundobj;
! 1224: error = 0;
! 1225: done:
! 1226: *newsearchdir_locked_ret = searchdir_locked;
! 1227: return error;
! 1228: }
1.204 dholland 1229:
1.208.6.2! martin 1230: /*
! 1231: * Parse out the first path name component that we need to to consider.
! 1232: *
! 1233: * While doing this, attempt to use the name cache to fast-forward through
! 1234: * as many "easy" to find components of the path as possible.
! 1235: *
! 1236: * We use the namecache's node locks to form a chain, and avoid as many
! 1237: * vnode references and locks as possible. In the ideal case, only the
! 1238: * final vnode will have its reference count adjusted and lock taken.
! 1239: */
! 1240: static int
! 1241: lookup_fastforward(struct namei_state *state, struct vnode **searchdir_ret,
! 1242: struct vnode **foundobj_ret)
! 1243: {
! 1244: struct componentname *cnp = state->cnp;
! 1245: struct nameidata *ndp = state->ndp;
! 1246: krwlock_t *plock;
! 1247: struct vnode *foundobj, *searchdir;
! 1248: int error, error2;
! 1249: size_t oldpathlen;
! 1250: const char *oldnameptr;
1.204 dholland 1251:
1.208.6.2! martin 1252: /*
! 1253: * Eat as many path name components as possible before giving up and
! 1254: * letting lookup_once() handle it. Remember the starting point in
! 1255: * case we can't get vnode references and need to roll back.
! 1256: */
! 1257: plock = NULL;
! 1258: searchdir = *searchdir_ret;
! 1259: oldnameptr = cnp->cn_nameptr;
! 1260: oldpathlen = ndp->ni_pathlen;
! 1261: for (;;) {
! 1262: foundobj = NULL;
! 1263:
! 1264: /*
! 1265: * Get the next component name. There should be no slashes
! 1266: * here, and we shouldn't have looped around if we were
! 1267: * done.
! 1268: */
! 1269: KASSERT(cnp->cn_nameptr[0] != '/');
! 1270: KASSERT(cnp->cn_nameptr[0] != '\0');
! 1271: if ((error = lookup_parsepath(state)) != 0) {
! 1272: break;
1.107 ad 1273: }
1.208.6.2! martin 1274:
! 1275: /*
! 1276: * Can't deal with dotdot lookups, because it means lock
! 1277: * order reversal, and there are checks in lookup_once()
! 1278: * that need to be made. Also check for missing mountpoints.
! 1279: */
! 1280: if ((cnp->cn_flags & ISDOTDOT) != 0 ||
! 1281: searchdir->v_mount == NULL) {
! 1282: error = EOPNOTSUPP;
! 1283: break;
1.190 yamt 1284: }
1.208.6.2! martin 1285:
! 1286: /*
! 1287: * Can't deal with last component when modifying; this needs
! 1288: * searchdir locked and VOP_LOOKUP() called (which can and
! 1289: * does modify state, despite the name).
! 1290: */
! 1291: if ((cnp->cn_flags & ISLASTCN) != 0) {
! 1292: if (cnp->cn_nameiop != LOOKUP ||
! 1293: (cnp->cn_flags & LOCKPARENT) != 0) {
! 1294: error = EOPNOTSUPP;
! 1295: break;
1.204 dholland 1296: }
1.32 wrstuden 1297: }
1.208.6.2! martin 1298:
! 1299: /* Can't deal with -o union lookups. */
! 1300: if ((searchdir->v_vflag & VV_ROOT) != 0 &&
! 1301: (searchdir->v_mount->mnt_flag & MNT_UNION) != 0) {
! 1302: error = EOPNOTSUPP;
! 1303: break;
! 1304: }
! 1305:
1.190 yamt 1306: /*
1.208.6.2! martin 1307: * Good, now look for it in cache. cache_lookup_linked()
! 1308: * will fail if there's nothing there, or if there's no
! 1309: * ownership info for the directory, or if the user doesn't
! 1310: * have permission to look up files in this directory.
! 1311: */
! 1312: if (!cache_lookup_linked(searchdir, cnp->cn_nameptr,
! 1313: cnp->cn_namelen, &foundobj, &plock, cnp->cn_cred)) {
! 1314: error = EOPNOTSUPP;
! 1315: break;
! 1316: }
! 1317: KASSERT(plock != NULL && rw_lock_held(plock));
! 1318:
! 1319: /* Scored a hit. Negative is good too (ENOENT). */
! 1320: if (foundobj == NULL) {
! 1321: error = ENOENT;
! 1322: break;
! 1323: }
! 1324:
! 1325: /*
! 1326: * Stop and get a hold on the vnode if there's something
! 1327: * that can't be handled here:
1.204 dholland 1328: *
1.208.6.2! martin 1329: * - we've reached the last component.
! 1330: * - or encountered a mount point that needs to be crossed.
! 1331: * - or encountered something other than a directory.
1.190 yamt 1332: */
1.208.6.2! martin 1333: if ((cnp->cn_flags & ISLASTCN) != 0 ||
! 1334: foundobj->v_type != VDIR ||
! 1335: (foundobj->v_type == VDIR &&
! 1336: foundobj->v_mountedhere != NULL)) {
! 1337: mutex_enter(foundobj->v_interlock);
! 1338: error = vcache_tryvget(foundobj);
! 1339: /* v_interlock now unheld */
! 1340: if (error != 0) {
! 1341: foundobj = NULL;
! 1342: }
! 1343: break;
! 1344: }
! 1345:
! 1346: /*
! 1347: * Otherwise, we're still in business. Set the found VDIR
! 1348: * vnode as the search dir for the next component and
! 1349: * continue on to it.
! 1350: */
! 1351: cnp->cn_nameptr = ndp->ni_next;
! 1352: searchdir = foundobj;
! 1353: }
! 1354:
! 1355: /*
! 1356: * If we ended up with a new search dir, ref it before dropping the
! 1357: * namecache's lock. The lock prevents both searchdir and foundobj
! 1358: * from disappearing. If we can't ref the new searchdir, we have a
! 1359: * bit of a problem. Roll back the fastforward to the beginning and
! 1360: * let lookup_once() take care of it.
! 1361: */
! 1362: if (searchdir != *searchdir_ret) {
! 1363: mutex_enter(searchdir->v_interlock);
! 1364: error2 = vcache_tryvget(searchdir);
! 1365: /* v_interlock now unheld */
! 1366: KASSERT(plock != NULL);
! 1367: rw_exit(plock);
! 1368: if (__predict_true(error2 == 0)) {
! 1369: /* Returning new searchdir, and maybe new foundobj. */
! 1370: vrele(*searchdir_ret);
! 1371: *searchdir_ret = searchdir;
1.190 yamt 1372: } else {
1.208.6.2! martin 1373: /* Returning nothing. */
! 1374: if (foundobj != NULL) {
! 1375: vrele(foundobj);
! 1376: foundobj = NULL;
! 1377: }
! 1378: cnp->cn_nameptr = oldnameptr;
! 1379: ndp->ni_pathlen = oldpathlen;
! 1380: error = lookup_parsepath(state);
! 1381: if (error == 0) {
! 1382: error = EOPNOTSUPP;
! 1383: }
1.190 yamt 1384: }
1.208.6.2! martin 1385: } else if (plock != NULL) {
! 1386: /* Drop any namecache lock still held. */
! 1387: rw_exit(plock);
1.14 mycroft 1388: }
1389:
1.208.6.2! martin 1390: KASSERT(error == 0 ? foundobj != NULL : foundobj == NULL);
1.147 dholland 1391: *foundobj_ret = foundobj;
1.175 yamt 1392: return error;
1.118 dholland 1393: }
1394:
1.131 dholland 1395: //////////////////////////////
1396:
1.173 dholland 1397: /*
1398: * Do a complete path search from a single root directory.
1399: * (This is called up to twice if TRYEMULROOT is in effect.)
1400: */
1.131 dholland 1401: static int
1.196 dholland 1402: namei_oneroot(struct namei_state *state,
1.193 dholland 1403: int neverfollow, int inhibitmagic, int isnfsd)
1.131 dholland 1404: {
1405: struct nameidata *ndp = state->ndp;
1406: struct componentname *cnp = state->cnp;
1.146 dholland 1407: struct vnode *searchdir, *foundobj;
1.208.6.2! martin 1408: bool searchdir_locked = false;
1.137 dholland 1409: int error;
1.131 dholland 1410:
1.196 dholland 1411: error = namei_start(state, isnfsd, &searchdir);
1.131 dholland 1412: if (error) {
1.164 dholland 1413: ndp->ni_dvp = NULL;
1414: ndp->ni_vp = NULL;
1.131 dholland 1415: return error;
1416: }
1.185 dholland 1417: KASSERT(searchdir->v_type == VDIR);
1.131 dholland 1418:
1.133 dholland 1419: /*
1.139 dholland 1420: * Setup: break out flag bits into variables.
1421: */
1422: state->docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE;
1423: if (cnp->cn_nameiop == DELETE)
1424: state->docache = 0;
1425: state->rdonly = cnp->cn_flags & RDONLY;
1426:
1427: /*
1.133 dholland 1428: * Keep going until we run out of path components.
1429: */
1.139 dholland 1430: cnp->cn_nameptr = ndp->ni_pnbuf;
1.185 dholland 1431:
1432: /* drop leading slashes (already used them to choose startdir) */
1433: while (cnp->cn_nameptr[0] == '/') {
1434: cnp->cn_nameptr++;
1435: ndp->ni_pathlen--;
1436: }
1437: /* was it just "/"? */
1438: if (cnp->cn_nameptr[0] == '\0') {
1439: foundobj = searchdir;
1440: searchdir = NULL;
1441: cnp->cn_flags |= ISLASTCN;
1442:
1443: /* bleh */
1444: goto skiploop;
1445: }
1446:
1.131 dholland 1447: for (;;) {
1.204 dholland 1448: KASSERT(searchdir != NULL);
1.208.6.2! martin 1449: KASSERT(!searchdir_locked);
1.133 dholland 1450:
1451: /*
1.208.6.2! martin 1452: * Parse out the first path name component that we need to
! 1453: * to consider. While doing this, attempt to use the name
! 1454: * cache to fast-forward through as many "easy" to find
! 1455: * components of the path as possible.
1.133 dholland 1456: */
1.208.6.2! martin 1457: error = lookup_fastforward(state, &searchdir, &foundobj);
1.133 dholland 1458:
1459: /*
1.208.6.2! martin 1460: * If we didn't get a good answer from the namecache, then
! 1461: * go directly to the file system.
1.133 dholland 1462: */
1.208.6.2! martin 1463: if (error != 0 && error != ENOENT) {
! 1464: error = lookup_once(state, searchdir, &searchdir,
! 1465: &foundobj, &searchdir_locked);
! 1466: }
1.138 dholland 1467:
1.208.6.2! martin 1468: /*
! 1469: * If the vnode we found is mounted on, then cross the mount
! 1470: * and get the root vnode in foundobj. If this encounters
! 1471: * an error, it will dispose of foundobj, but searchdir is
! 1472: * untouched.
! 1473: */
! 1474: if (error == 0 && foundobj != NULL &&
! 1475: foundobj->v_type == VDIR &&
! 1476: foundobj->v_mountedhere != NULL &&
! 1477: (cnp->cn_flags & NOCROSSMOUNT) == 0) {
! 1478: error = lookup_crossmount(state, &searchdir,
! 1479: &foundobj, &searchdir_locked);
1.131 dholland 1480: }
1.138 dholland 1481:
1.139 dholland 1482: if (error) {
1.204 dholland 1483: if (searchdir != NULL) {
1.208.6.2! martin 1484: if (searchdir_locked) {
! 1485: searchdir_locked = false;
! 1486: vput(searchdir);
! 1487: } else {
! 1488: vrele(searchdir);
! 1489: }
1.204 dholland 1490: }
1.168 dholland 1491: ndp->ni_dvp = NULL;
1.139 dholland 1492: ndp->ni_vp = NULL;
1.138 dholland 1493: /*
1.139 dholland 1494: * Note that if we're doing TRYEMULROOT we can
1495: * retry with the normal root. Where this is
1496: * currently set matches previous practice,
1497: * but the previous practice didn't make much
1498: * sense and somebody should sit down and
1499: * figure out which cases should cause retry
1500: * and which shouldn't. XXX.
1.138 dholland 1501: */
1.139 dholland 1502: state->attempt_retry = 1;
1503: return (error);
1504: }
1.157 dholland 1505:
1.162 dholland 1506: if (foundobj == NULL) {
1507: /*
1508: * Success with no object returned means we're
1509: * creating something and it isn't already
1.181 dholland 1510: * there. Break out of the main loop now so
1.162 dholland 1511: * the code below doesn't have to test for
1512: * foundobj == NULL.
1513: */
1.204 dholland 1514: /* lookup_once can't have dropped the searchdir */
1515: KASSERT(searchdir != NULL);
1.181 dholland 1516: break;
1.138 dholland 1517: }
1.131 dholland 1518:
1519: /*
1.139 dholland 1520: * Check for symbolic link. If we've reached one,
1521: * follow it, unless we aren't supposed to. Back up
1522: * over any slashes that we skipped, as we will need
1523: * them again.
1.131 dholland 1524: */
1.146 dholland 1525: if (namei_atsymlink(state, foundobj)) {
1.208.6.2! martin 1526: /* Don't need searchdir locked any more. */
! 1527: if (searchdir_locked) {
! 1528: searchdir_locked = false;
! 1529: VOP_UNLOCK(searchdir);
! 1530: }
1.139 dholland 1531: ndp->ni_pathlen += state->slashes;
1532: ndp->ni_next -= state->slashes;
1.134 dholland 1533: if (neverfollow) {
1534: error = EINVAL;
1.204 dholland 1535: } else if (searchdir == NULL) {
1536: /*
1537: * dholland 20160410: lookup_once only
1538: * drops searchdir if it crossed a
1539: * mount point. Therefore, if we get
1540: * here it means we crossed a mount
1541: * point to a mounted filesystem whose
1542: * root vnode is a symlink. In theory
1543: * we could continue at this point by
1544: * using the pre-crossing searchdir
1545: * (e.g. just take out an extra
1546: * reference on it before calling
1547: * lookup_once so we still have it),
1548: * but this will make an ugly mess and
1549: * it should never happen in practice
1550: * as only badly broken filesystems
1551: * have non-directory root vnodes. (I
1552: * have seen this sort of thing with
1553: * NFS occasionally but even then it
1554: * means something's badly wrong.)
1555: */
1556: error = ENOTDIR;
1.134 dholland 1557: } else {
1.152 dholland 1558: /*
1559: * dholland 20110410: if we're at a
1560: * union mount it might make sense to
1561: * use the top of the union stack here
1562: * rather than the layer we found the
1563: * symlink in. (FUTURE)
1564: */
1.141 dholland 1565: error = namei_follow(state, inhibitmagic,
1.165 dholland 1566: searchdir, foundobj,
1.152 dholland 1567: &searchdir);
1.134 dholland 1568: }
1.131 dholland 1569: if (error) {
1.165 dholland 1570: KASSERT(searchdir != foundobj);
1.204 dholland 1571: if (searchdir != NULL) {
1.208.6.2! martin 1572: vrele(searchdir);
1.204 dholland 1573: }
1.208.6.2! martin 1574: vrele(foundobj);
1.168 dholland 1575: ndp->ni_dvp = NULL;
1.131 dholland 1576: ndp->ni_vp = NULL;
1577: return error;
1578: }
1.174 jakllsch 1579: vrele(foundobj);
1.167 dholland 1580: foundobj = NULL;
1.189 riastrad 1581:
1582: /*
1583: * If we followed a symlink to `/' and there
1584: * are no more components after the symlink,
1585: * we're done with the loop and what we found
1586: * is the searchdir.
1587: */
1588: if (cnp->cn_nameptr[0] == '\0') {
1.204 dholland 1589: KASSERT(searchdir != NULL);
1.189 riastrad 1590: foundobj = searchdir;
1591: searchdir = NULL;
1592: cnp->cn_flags |= ISLASTCN;
1593: break;
1594: }
1595:
1.139 dholland 1596: continue;
1597: }
1598:
1599: /*
1.183 dholland 1600: * Not a symbolic link.
1601: *
1.139 dholland 1602: * Check for directory, if the component was
1603: * followed by a series of slashes.
1604: */
1.190 yamt 1605: if ((foundobj->v_type != VDIR) &&
1606: (cnp->cn_flags & REQUIREDIR)) {
1.204 dholland 1607: KASSERT(foundobj != searchdir);
1608: if (searchdir) {
1.208.6.2! martin 1609: if (searchdir_locked) {
! 1610: searchdir_locked = false;
! 1611: vput(searchdir);
! 1612: } else {
! 1613: vrele(searchdir);
! 1614: }
! 1615: } else {
! 1616: KASSERT(!searchdir_locked);
1.139 dholland 1617: }
1.208.6.2! martin 1618: vrele(foundobj);
1.168 dholland 1619: ndp->ni_dvp = NULL;
1620: ndp->ni_vp = NULL;
1.139 dholland 1621: state->attempt_retry = 1;
1622: return ENOTDIR;
1623: }
1624:
1625: /*
1.183 dholland 1626: * Stop if we've reached the last component.
1.139 dholland 1627: */
1.183 dholland 1628: if (cnp->cn_flags & ISLASTCN) {
1629: break;
1.139 dholland 1630: }
1631:
1.183 dholland 1632: /*
1633: * Continue with the next component.
1634: */
1635: cnp->cn_nameptr = ndp->ni_next;
1.208.6.2! martin 1636: if (searchdir != NULL) {
! 1637: if (searchdir_locked) {
! 1638: searchdir_locked = false;
! 1639: vput(searchdir);
! 1640: } else {
! 1641: vrele(searchdir);
! 1642: }
1.183 dholland 1643: }
1644: searchdir = foundobj;
1645: foundobj = NULL;
1.179 dholland 1646: }
1647:
1.208.6.2! martin 1648: KASSERT((cnp->cn_flags & LOCKPARENT) == 0 || searchdir == NULL ||
! 1649: VOP_ISLOCKED(searchdir) == LK_EXCLUSIVE);
! 1650:
1.185 dholland 1651: skiploop:
1652:
1.182 dholland 1653: if (foundobj != NULL) {
1.146 dholland 1654: if (foundobj == ndp->ni_erootdir) {
1.139 dholland 1655: /*
1656: * We are about to return the emulation root.
1657: * This isn't a good idea because code might
1658: * repeatedly lookup ".." until the file
1659: * matches that returned for "/" and loop
1660: * forever. So convert it to the real root.
1661: */
1.170 dholland 1662: if (searchdir != NULL) {
1.208.6.2! martin 1663: if (searchdir_locked) {
1.157 dholland 1664: vput(searchdir);
1.208.6.2! martin 1665: searchdir_locked = false;
! 1666: } else {
! 1667: vrele(searchdir);
! 1668: }
1.170 dholland 1669: searchdir = NULL;
1670: }
1.208.6.2! martin 1671: vrele(foundobj);
1.146 dholland 1672: foundobj = ndp->ni_rootdir;
1673: vref(foundobj);
1.131 dholland 1674: }
1.139 dholland 1675:
1676: /*
1.158 dholland 1677: * If the caller requested the parent node (i.e. it's
1678: * a CREATE, DELETE, or RENAME), and we don't have one
1679: * (because this is the root directory, or we crossed
1680: * a mount point), then we must fail.
1.139 dholland 1681: */
1.158 dholland 1682: if (cnp->cn_nameiop != LOOKUP &&
1683: (searchdir == NULL ||
1684: searchdir->v_mount != foundobj->v_mount)) {
1.170 dholland 1685: if (searchdir) {
1.208.6.2! martin 1686: if (searchdir_locked) {
! 1687: vput(searchdir);
! 1688: searchdir_locked = false;
! 1689: } else {
! 1690: vrele(searchdir);
! 1691: }
! 1692: searchdir = NULL;
1.170 dholland 1693: }
1.208.6.2! martin 1694: vrele(foundobj);
1.170 dholland 1695: foundobj = NULL;
1696: ndp->ni_dvp = NULL;
1697: ndp->ni_vp = NULL;
1698: state->attempt_retry = 1;
1699:
1.139 dholland 1700: switch (cnp->cn_nameiop) {
1701: case CREATE:
1.171 dholland 1702: return EEXIST;
1.139 dholland 1703: case DELETE:
1704: case RENAME:
1.171 dholland 1705: return EBUSY;
1706: default:
1.139 dholland 1707: break;
1708: }
1.171 dholland 1709: panic("Invalid nameiop\n");
1.139 dholland 1710: }
1711:
1712: /*
1713: * Disallow directory write attempts on read-only lookups.
1714: * Prefers EEXIST over EROFS for the CREATE case.
1715: */
1716: if (state->rdonly &&
1717: (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
1.157 dholland 1718: if (searchdir) {
1.208.6.2! martin 1719: if (searchdir_locked) {
1.170 dholland 1720: vput(searchdir);
1.208.6.2! martin 1721: searchdir_locked = false;
1.170 dholland 1722: } else {
1723: vrele(searchdir);
1724: }
1725: searchdir = NULL;
1.157 dholland 1726: }
1.208.6.2! martin 1727: vrele(foundobj);
1.170 dholland 1728: foundobj = NULL;
1.168 dholland 1729: ndp->ni_dvp = NULL;
1.139 dholland 1730: ndp->ni_vp = NULL;
1731: state->attempt_retry = 1;
1.171 dholland 1732: return EROFS;
1.139 dholland 1733: }
1.208.6.2! martin 1734:
! 1735: /* Lock the leaf node if requested. */
! 1736: if ((cnp->cn_flags & (LOCKLEAF | LOCKPARENT)) == LOCKPARENT &&
! 1737: searchdir == foundobj) {
1.172 dholland 1738: /*
1739: * Note: if LOCKPARENT but not LOCKLEAF is
1740: * set, and searchdir == foundobj, this code
1741: * necessarily unlocks the parent as well as
1742: * the leaf. That is, just because you specify
1743: * LOCKPARENT doesn't mean you necessarily get
1744: * a locked parent vnode. The code in
1745: * vfs_syscalls.c, and possibly elsewhere,
1746: * that uses this combination "knows" this, so
1747: * it can't be safely changed. Feh. XXX
1748: */
1.208.6.2! martin 1749: KASSERT(searchdir_locked);
! 1750: VOP_UNLOCK(searchdir);
! 1751: searchdir_locked = false;
! 1752: } else if ((cnp->cn_flags & LOCKLEAF) != 0 &&
! 1753: (searchdir != foundobj ||
! 1754: (cnp->cn_flags & LOCKPARENT) == 0)) {
! 1755: const int lktype = (cnp->cn_flags & LOCKSHARED) != 0 ?
! 1756: LK_SHARED : LK_EXCLUSIVE;
! 1757: vn_lock(foundobj, lktype | LK_RETRY);
1.131 dholland 1758: }
1.179 dholland 1759: }
1.139 dholland 1760:
1.131 dholland 1761: /*
1.133 dholland 1762: * Done.
1.131 dholland 1763: */
1764:
1.133 dholland 1765: /*
1766: * If LOCKPARENT is not set, the parent directory isn't returned.
1767: */
1.157 dholland 1768: if ((cnp->cn_flags & LOCKPARENT) == 0 && searchdir != NULL) {
1.208.6.2! martin 1769: vrele(searchdir);
1.157 dholland 1770: searchdir = NULL;
1.131 dholland 1771: }
1772:
1.157 dholland 1773: ndp->ni_dvp = searchdir;
1.165 dholland 1774: ndp->ni_vp = foundobj;
1.137 dholland 1775: return 0;
1776: }
1777:
1.173 dholland 1778: /*
1779: * Do namei; wrapper layer that handles TRYEMULROOT.
1780: */
1.137 dholland 1781: static int
1.196 dholland 1782: namei_tryemulroot(struct namei_state *state,
1.193 dholland 1783: int neverfollow, int inhibitmagic, int isnfsd)
1.137 dholland 1784: {
1785: int error;
1786:
1787: struct nameidata *ndp = state->ndp;
1788: struct componentname *cnp = state->cnp;
1789: const char *savepath = NULL;
1790:
1791: KASSERT(cnp == &ndp->ni_cnd);
1792:
1793: if (cnp->cn_flags & TRYEMULROOT) {
1794: savepath = pathbuf_stringcopy_get(ndp->ni_pathbuf);
1795: }
1796:
1797: emul_retry:
1798: state->attempt_retry = 0;
1799:
1.196 dholland 1800: error = namei_oneroot(state, neverfollow, inhibitmagic, isnfsd);
1.137 dholland 1801: if (error) {
1802: /*
1803: * Once namei has started up, the existence of ni_erootdir
1804: * tells us whether we're working from an emulation root.
1805: * The TRYEMULROOT flag isn't necessarily authoritative.
1806: */
1807: if (ndp->ni_erootdir != NULL && state->attempt_retry) {
1808: /* Retry the whole thing using the normal root */
1809: cnp->cn_flags &= ~TRYEMULROOT;
1810: state->attempt_retry = 0;
1811:
1812: /* kinda gross */
1813: strcpy(ndp->ni_pathbuf->pb_path, savepath);
1814: pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath);
1815: savepath = NULL;
1816:
1817: goto emul_retry;
1818: }
1819: }
1.131 dholland 1820: if (savepath != NULL) {
1821: pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath);
1822: }
1.137 dholland 1823: return error;
1.131 dholland 1824: }
1825:
1.173 dholland 1826: /*
1827: * External interface.
1828: */
1.131 dholland 1829: int
1830: namei(struct nameidata *ndp)
1831: {
1832: struct namei_state state;
1833: int error;
1834:
1835: namei_init(&state, ndp);
1.196 dholland 1836: error = namei_tryemulroot(&state,
1.193 dholland 1837: 0/*!neverfollow*/, 0/*!inhibitmagic*/,
1838: 0/*isnfsd*/);
1.131 dholland 1839: namei_cleanup(&state);
1840:
1.159 dholland 1841: if (error) {
1842: /* make sure no stray refs leak out */
1.164 dholland 1843: KASSERT(ndp->ni_dvp == NULL);
1844: KASSERT(ndp->ni_vp == NULL);
1.159 dholland 1845: }
1846:
1.131 dholland 1847: return error;
1848: }
1849:
1850: ////////////////////////////////////////////////////////////
1851:
1.12 mycroft 1852: /*
1.173 dholland 1853: * External interface used by nfsd. This is basically different from
1854: * namei only in that it has the ability to pass in the "current
1855: * directory", and uses an extra flag "neverfollow" for which there's
1856: * no physical flag defined in namei.h. (There used to be a cut&paste
1857: * copy of about half of namei in nfsd to allow these minor
1858: * adjustments to exist.)
1.119 dholland 1859: *
1.173 dholland 1860: * XXX: the namei interface should be adjusted so nfsd can just use
1861: * ordinary namei().
1.118 dholland 1862: */
1.134 dholland 1863: int
1.135 dholland 1864: lookup_for_nfsd(struct nameidata *ndp, struct vnode *forcecwd, int neverfollow)
1.134 dholland 1865: {
1866: struct namei_state state;
1867: int error;
1.120 dholland 1868:
1.198 dholland 1869: KASSERT(ndp->ni_atdir == NULL);
1870: ndp->ni_atdir = forcecwd;
1.194 dholland 1871:
1.134 dholland 1872: namei_init(&state, ndp);
1.196 dholland 1873: error = namei_tryemulroot(&state,
1.193 dholland 1874: neverfollow, 1/*inhibitmagic*/, 1/*isnfsd*/);
1.119 dholland 1875: namei_cleanup(&state);
1876:
1.159 dholland 1877: if (error) {
1878: /* make sure no stray refs leak out */
1.164 dholland 1879: KASSERT(ndp->ni_dvp == NULL);
1880: KASSERT(ndp->ni_vp == NULL);
1.159 dholland 1881: }
1882:
1.119 dholland 1883: return error;
1884: }
1885:
1.173 dholland 1886: /*
1887: * A second external interface used by nfsd. This turns out to be a
1888: * single lookup used by the WebNFS code (ha!) to get "index.html" or
1889: * equivalent when asked for a directory. It should eventually evolve
1890: * into some kind of namei_once() call; for the time being it's kind
1891: * of a mess. XXX.
1892: *
1893: * dholland 20110109: I don't think it works, and I don't think it
1894: * worked before I started hacking and slashing either, and I doubt
1895: * anyone will ever notice.
1896: */
1897:
1898: /*
1899: * Internals. This calls lookup_once() after setting up the assorted
1900: * pieces of state the way they ought to be.
1901: */
1.136 dholland 1902: static int
1.196 dholland 1903: do_lookup_for_nfsd_index(struct namei_state *state)
1.136 dholland 1904: {
1905: int error = 0;
1906:
1907: struct componentname *cnp = state->cnp;
1908: struct nameidata *ndp = state->ndp;
1.196 dholland 1909: struct vnode *startdir;
1.147 dholland 1910: struct vnode *foundobj;
1.208.6.2! martin 1911: bool startdir_locked;
1.136 dholland 1912: const char *cp; /* pointer into pathname argument */
1913:
1914: KASSERT(cnp == &ndp->ni_cnd);
1915:
1.198 dholland 1916: startdir = state->ndp->ni_atdir;
1.196 dholland 1917:
1.136 dholland 1918: cnp->cn_nameptr = ndp->ni_pnbuf;
1919: state->docache = 1;
1920: state->rdonly = cnp->cn_flags & RDONLY;
1921: ndp->ni_dvp = NULL;
1922:
1923: cnp->cn_consume = 0;
1.197 dholland 1924: cnp->cn_namelen = namei_getcomponent(cnp->cn_nameptr);
1925: cp = cnp->cn_nameptr + cnp->cn_namelen;
1.191 christos 1926: KASSERT(cnp->cn_namelen <= KERNEL_NAME_MAX);
1.136 dholland 1927: ndp->ni_pathlen -= cnp->cn_namelen;
1928: ndp->ni_next = cp;
1929: state->slashes = 0;
1930: cnp->cn_flags &= ~REQUIREDIR;
1931: cnp->cn_flags |= MAKEENTRY|ISLASTCN;
1932:
1933: if (cnp->cn_namelen == 2 &&
1934: cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.')
1935: cnp->cn_flags |= ISDOTDOT;
1936: else
1937: cnp->cn_flags &= ~ISDOTDOT;
1938:
1.160 dholland 1939: /*
1940: * Because lookup_once can change the startdir, we need our
1941: * own reference to it to avoid consuming the caller's.
1942: */
1943: vref(startdir);
1.208.6.2! martin 1944: error = lookup_once(state, startdir, &startdir, &foundobj,
! 1945: &startdir_locked);
1.162 dholland 1946:
1.208.6.2! martin 1947: KASSERT((cnp->cn_flags & LOCKPARENT) == 0);
! 1948: if (startdir_locked) {
! 1949: VOP_UNLOCK(startdir);
! 1950: startdir_locked = false;
1.136 dholland 1951: }
1952:
1.208.6.2! martin 1953: /*
! 1954: * If the vnode we found is mounted on, then cross the mount and get
! 1955: * the root vnode in foundobj. If this encounters an error, it will
! 1956: * dispose of foundobj, but searchdir is untouched.
! 1957: */
! 1958: if (error == 0 && foundobj != NULL &&
! 1959: foundobj->v_type == VDIR &&
! 1960: foundobj->v_mountedhere != NULL &&
! 1961: (cnp->cn_flags & NOCROSSMOUNT) == 0) {
! 1962: error = lookup_crossmount(state, &startdir, &foundobj,
! 1963: &startdir_locked);
1.136 dholland 1964: }
1965:
1.208.6.2! martin 1966: /* Now toss startdir and see if we have an error. */
! 1967: if (startdir != NULL)
! 1968: vrele(startdir);
! 1969: if (error)
! 1970: foundobj = NULL;
! 1971: else if (foundobj != NULL && (cnp->cn_flags & LOCKLEAF) != 0)
! 1972: vn_lock(foundobj, LK_EXCLUSIVE | LK_RETRY);
! 1973:
! 1974: ndp->ni_vp = foundobj;
1.136 dholland 1975: return (error);
1976: }
1977:
1.173 dholland 1978: /*
1979: * External interface. The partitioning between this function and the
1980: * above isn't very clear - the above function exists mostly so code
1981: * that uses "state->" can be shuffled around without having to change
1982: * it to "state.".
1983: */
1.118 dholland 1984: int
1.128 dholland 1985: lookup_for_nfsd_index(struct nameidata *ndp, struct vnode *startdir)
1.118 dholland 1986: {
1987: struct namei_state state;
1988: int error;
1989:
1.198 dholland 1990: KASSERT(ndp->ni_atdir == NULL);
1991: ndp->ni_atdir = startdir;
1.194 dholland 1992:
1.133 dholland 1993: /*
1.135 dholland 1994: * Note: the name sent in here (is not|should not be) allowed
1995: * to contain a slash.
1.133 dholland 1996: */
1.191 christos 1997: if (strlen(ndp->ni_pathbuf->pb_path) > KERNEL_NAME_MAX) {
1.136 dholland 1998: return ENAMETOOLONG;
1999: }
2000: if (strchr(ndp->ni_pathbuf->pb_path, '/')) {
2001: return EINVAL;
2002: }
1.133 dholland 2003:
2004: ndp->ni_pathlen = strlen(ndp->ni_pathbuf->pb_path) + 1;
2005: ndp->ni_pnbuf = NULL;
2006: ndp->ni_cnd.cn_nameptr = NULL;
2007:
1.118 dholland 2008: namei_init(&state, ndp);
1.196 dholland 2009: error = do_lookup_for_nfsd_index(&state);
1.118 dholland 2010: namei_cleanup(&state);
2011:
2012: return error;
2013: }
2014:
1.131 dholland 2015: ////////////////////////////////////////////////////////////
2016:
1.118 dholland 2017: /*
1.12 mycroft 2018: * Reacquire a path name component.
1.73 chs 2019: * dvp is locked on entry and exit.
2020: * *vpp is locked on exit unless it's NULL.
1.12 mycroft 2021: */
2022: int
1.130 dholland 2023: relookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, int dummy)
1.12 mycroft 2024: {
2025: int rdonly; /* lookup read-only flag bit */
2026: int error = 0;
1.52 yamt 2027: #ifdef DEBUG
1.197 dholland 2028: size_t newlen; /* DEBUG: check name len */
2029: const char *cp; /* DEBUG: check name ptr */
1.52 yamt 2030: #endif /* DEBUG */
1.12 mycroft 2031:
1.130 dholland 2032: (void)dummy;
2033:
1.12 mycroft 2034: /*
2035: * Setup: break out flag bits into variables.
2036: */
2037: rdonly = cnp->cn_flags & RDONLY;
2038:
2039: /*
2040: * Search a new directory.
2041: *
2042: * The cn_hash value is for use by vfs_cache.
2043: * The last component of the filename is left accessible via
2044: * cnp->cn_nameptr for callers that need the name. Callers needing
2045: * the name set the SAVENAME flag. When done, they assume
2046: * responsibility for freeing the pathname buffer.
2047: */
1.52 yamt 2048: #ifdef DEBUG
1.197 dholland 2049: #if 0
1.39 lukem 2050: cp = NULL;
2051: newhash = namei_hash(cnp->cn_nameptr, &cp);
1.81 chs 2052: if ((uint32_t)newhash != (uint32_t)cnp->cn_hash)
1.12 mycroft 2053: panic("relookup: bad hash");
1.197 dholland 2054: #endif
1.199 para 2055: newlen = namei_getcomponent(cnp->cn_nameptr);
1.197 dholland 2056: if (cnp->cn_namelen != newlen)
1.58 christos 2057: panic("relookup: bad len");
1.197 dholland 2058: cp = cnp->cn_nameptr + cnp->cn_namelen;
1.53 yamt 2059: while (*cp == '/')
2060: cp++;
1.12 mycroft 2061: if (*cp != 0)
2062: panic("relookup: not last component");
1.52 yamt 2063: #endif /* DEBUG */
1.12 mycroft 2064:
2065: /*
2066: * Check for degenerate name (e.g. / or "")
2067: * which is a way of talking about a directory,
2068: * e.g. like "/." or ".".
2069: */
1.23 mycroft 2070: if (cnp->cn_nameptr[0] == '\0')
2071: panic("relookup: null name");
1.12 mycroft 2072:
2073: if (cnp->cn_flags & ISDOTDOT)
1.58 christos 2074: panic("relookup: lookup on dot-dot");
1.12 mycroft 2075:
2076: /*
2077: * We now have a segment name to search for, and a directory to search.
2078: */
1.195 dholland 2079: *vpp = NULL;
1.129 dholland 2080: error = VOP_LOOKUP(dvp, vpp, cnp);
2081: if ((error) != 0) {
1.205 riastrad 2082: KASSERTMSG((*vpp == NULL),
2083: "leaf `%s' should be empty but is %p",
2084: cnp->cn_nameptr, *vpp);
1.12 mycroft 2085: if (error != EJUSTRETURN)
2086: goto bad;
2087: }
2088:
2089: /*
2090: * Check for symbolic link
2091: */
1.205 riastrad 2092: KASSERTMSG((*vpp == NULL || (*vpp)->v_type != VLNK ||
2093: (cnp->cn_flags & FOLLOW) == 0),
2094: "relookup: symlink found");
1.12 mycroft 2095:
2096: /*
1.94 pooka 2097: * Check for read-only lookups.
1.12 mycroft 2098: */
1.81 chs 2099: if (rdonly && cnp->cn_nameiop != LOOKUP) {
1.26 fvdl 2100: error = EROFS;
1.81 chs 2101: if (*vpp) {
1.201 hannken 2102: vrele(*vpp);
1.81 chs 2103: }
1.73 chs 2104: goto bad;
1.12 mycroft 2105: }
1.201 hannken 2106: /*
2107: * Lock result.
2108: */
2109: if (*vpp && *vpp != dvp) {
2110: error = vn_lock(*vpp, LK_EXCLUSIVE);
2111: if (error != 0) {
2112: vrele(*vpp);
2113: goto bad;
2114: }
2115: }
1.12 mycroft 2116: return (0);
2117:
2118: bad:
2119: *vpp = NULL;
1.10 cgd 2120: return (error);
2121: }
1.116 dholland 2122:
2123: /*
2124: * namei_simple - simple forms of namei.
2125: *
2126: * These are wrappers to allow the simple case callers of namei to be
2127: * left alone while everything else changes under them.
2128: */
2129:
2130: /* Flags */
2131: struct namei_simple_flags_type {
2132: int dummy;
2133: };
2134: static const struct namei_simple_flags_type ns_nn, ns_nt, ns_fn, ns_ft;
2135: const namei_simple_flags_t NSM_NOFOLLOW_NOEMULROOT = &ns_nn;
2136: const namei_simple_flags_t NSM_NOFOLLOW_TRYEMULROOT = &ns_nt;
2137: const namei_simple_flags_t NSM_FOLLOW_NOEMULROOT = &ns_fn;
2138: const namei_simple_flags_t NSM_FOLLOW_TRYEMULROOT = &ns_ft;
2139:
2140: static
2141: int
2142: namei_simple_convert_flags(namei_simple_flags_t sflags)
2143: {
2144: if (sflags == NSM_NOFOLLOW_NOEMULROOT)
2145: return NOFOLLOW | 0;
2146: if (sflags == NSM_NOFOLLOW_TRYEMULROOT)
2147: return NOFOLLOW | TRYEMULROOT;
2148: if (sflags == NSM_FOLLOW_NOEMULROOT)
2149: return FOLLOW | 0;
2150: if (sflags == NSM_FOLLOW_TRYEMULROOT)
2151: return FOLLOW | TRYEMULROOT;
2152: panic("namei_simple_convert_flags: bogus sflags\n");
2153: return 0;
2154: }
2155:
2156: int
2157: namei_simple_kernel(const char *path, namei_simple_flags_t sflags,
1.200 manu 2158: struct vnode **vp_ret)
2159: {
2160: return nameiat_simple_kernel(NULL, path, sflags, vp_ret);
2161: }
2162:
2163: int
2164: nameiat_simple_kernel(struct vnode *dvp, const char *path,
2165: namei_simple_flags_t sflags, struct vnode **vp_ret)
1.116 dholland 2166: {
2167: struct nameidata nd;
1.123 dholland 2168: struct pathbuf *pb;
1.116 dholland 2169: int err;
2170:
1.123 dholland 2171: pb = pathbuf_create(path);
2172: if (pb == NULL) {
2173: return ENOMEM;
2174: }
2175:
1.116 dholland 2176: NDINIT(&nd,
2177: LOOKUP,
2178: namei_simple_convert_flags(sflags),
1.123 dholland 2179: pb);
1.200 manu 2180:
2181: if (dvp != NULL)
2182: NDAT(&nd, dvp);
2183:
1.116 dholland 2184: err = namei(&nd);
2185: if (err != 0) {
1.123 dholland 2186: pathbuf_destroy(pb);
1.116 dholland 2187: return err;
2188: }
2189: *vp_ret = nd.ni_vp;
1.123 dholland 2190: pathbuf_destroy(pb);
1.116 dholland 2191: return 0;
2192: }
2193:
2194: int
2195: namei_simple_user(const char *path, namei_simple_flags_t sflags,
1.200 manu 2196: struct vnode **vp_ret)
2197: {
2198: return nameiat_simple_user(NULL, path, sflags, vp_ret);
2199: }
2200:
2201: int
2202: nameiat_simple_user(struct vnode *dvp, const char *path,
2203: namei_simple_flags_t sflags, struct vnode **vp_ret)
1.116 dholland 2204: {
1.123 dholland 2205: struct pathbuf *pb;
1.116 dholland 2206: struct nameidata nd;
2207: int err;
2208:
1.123 dholland 2209: err = pathbuf_copyin(path, &pb);
2210: if (err) {
2211: return err;
2212: }
2213:
1.116 dholland 2214: NDINIT(&nd,
2215: LOOKUP,
2216: namei_simple_convert_flags(sflags),
1.123 dholland 2217: pb);
1.200 manu 2218:
2219: if (dvp != NULL)
2220: NDAT(&nd, dvp);
2221:
1.116 dholland 2222: err = namei(&nd);
2223: if (err != 0) {
1.123 dholland 2224: pathbuf_destroy(pb);
1.116 dholland 2225: return err;
2226: }
2227: *vp_ret = nd.ni_vp;
1.123 dholland 2228: pathbuf_destroy(pb);
1.116 dholland 2229: return 0;
2230: }
CVSweb <webmaster@jp.NetBSD.org>