Annotation of src/sys/kern/vfs_lookup.c, Revision 1.81
1.81 ! chs 1: /* $NetBSD: vfs_lookup.c,v 1.80 2007/01/31 08:29:20 elad Exp $ */
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.81 ! chs 40: __KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.80 2007/01/31 08:29:20 elad Exp $");
1.27 thorpej 41:
42: #include "opt_ktrace.h"
1.50 cb 43: #include "opt_systrace.h"
1.67 chs 44: #include "opt_magiclinks.h"
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>
53: #include <sys/mount.h>
54: #include <sys/errno.h>
1.39 lukem 55: #include <sys/filedesc.h>
56: #include <sys/hash.h>
1.10 cgd 57: #include <sys/malloc.h>
58: #include <sys/proc.h>
1.40 wrstuden 59: #include <sys/syslog.h>
1.70 elad 60: #include <sys/kauth.h>
1.12 mycroft 61:
1.10 cgd 62: #ifdef KTRACE
63: #include <sys/ktrace.h>
64: #endif
1.50 cb 65: #ifdef SYSTRACE
66: #include <sys/systrace.h>
67: #endif
1.16 christos 68:
1.67 chs 69: #ifndef MAGICLINKS
70: #define MAGICLINKS 0
71: #endif
72:
1.76 elad 73: struct pathname_internal {
74: char *pathbuf;
75: boolean_t needfree;
76: };
77:
1.67 chs 78: int vfs_magiclinks = MAGICLINKS;
79:
1.35 thorpej 80: struct pool pnbuf_pool; /* pathname buffer pool */
1.37 thorpej 81: struct pool_cache pnbuf_cache; /* pathname buffer cache */
1.44 thorpej 82:
1.10 cgd 83: /*
1.61 thorpej 84: * Substitute replacement text for 'magic' strings in symlinks.
85: * Returns 0 if successful, and returns non-zero if an error
86: * occurs. (Currently, the only possible error is running out
87: * of temporary pathname space.)
88: *
89: * Looks for "@<string>" and "@<string>/", where <string> is a
90: * recognized 'magic' string. Replaces the "@<string>" with the
91: * appropriate replacement text. (Note that in some cases the
92: * replacement text may have zero length.)
93: *
94: * This would have been table driven, but the variance in
95: * replacement strings (and replacement string lengths) made
96: * that impractical.
97: */
1.63 thorpej 98: #define VNL(x) \
99: (sizeof(x) - 1)
100:
101: #define VO '{'
102: #define VC '}'
103:
1.61 thorpej 104: #define MATCH(str) \
1.63 thorpej 105: ((termchar == '/' && i + VNL(str) == *len) || \
106: (i + VNL(str) < *len && \
107: cp[i + VNL(str)] == termchar)) && \
108: !strncmp((str), &cp[i], VNL(str))
1.61 thorpej 109:
110: #define SUBSTITUTE(m, s, sl) \
1.63 thorpej 111: if ((newlen + (sl)) > MAXPATHLEN) \
112: return (1); \
113: i += VNL(m); \
114: if (termchar != '/') \
115: i++; \
116: memcpy(&tmp[newlen], (s), (sl)); \
117: newlen += (sl); \
118: change = 1; \
119: termchar = '/';
1.61 thorpej 120:
121: static int
1.63 thorpej 122: symlink_magic(struct proc *p, char *cp, int *len)
1.61 thorpej 123: {
1.66 yamt 124: char *tmp;
1.61 thorpej 125: int change, i, newlen;
1.63 thorpej 126: int termchar = '/';
1.61 thorpej 127:
1.66 yamt 128: tmp = PNBUF_GET();
1.61 thorpej 129: for (change = i = newlen = 0; i < *len; ) {
1.63 thorpej 130: if (cp[i] != '@') {
1.61 thorpej 131: tmp[newlen++] = cp[i++];
1.63 thorpej 132: continue;
133: }
134:
135: i++;
136:
137: /* Check for @{var} syntax. */
138: if (cp[i] == VO) {
139: termchar = VC;
1.61 thorpej 140: i++;
1.63 thorpej 141: }
142:
143: /*
144: * The following checks should be ordered according
145: * to frequency of use.
146: */
147: if (MATCH("machine_arch")) {
148: SUBSTITUTE("machine_arch", MACHINE_ARCH,
149: sizeof(MACHINE_ARCH) - 1);
150: } else if (MATCH("machine")) {
151: SUBSTITUTE("machine", MACHINE,
152: sizeof(MACHINE) - 1);
153: } else if (MATCH("hostname")) {
154: SUBSTITUTE("hostname", hostname,
155: hostnamelen);
156: } else if (MATCH("osrelease")) {
157: SUBSTITUTE("osrelease", osrelease,
158: strlen(osrelease));
159: } else if (MATCH("emul")) {
160: SUBSTITUTE("emul", p->p_emul->e_name,
161: strlen(p->p_emul->e_name));
162: } else if (MATCH("kernel_ident")) {
163: SUBSTITUTE("kernel_ident", kernel_ident,
164: strlen(kernel_ident));
165: } else if (MATCH("domainname")) {
166: SUBSTITUTE("domainname", domainname,
167: domainnamelen);
168: } else if (MATCH("ostype")) {
169: SUBSTITUTE("ostype", ostype,
170: strlen(ostype));
1.72 elad 171: } else if (MATCH("uid")) {
172: char uidtmp[11]; /* XXX elad */
173:
174: (void)snprintf(uidtmp, sizeof(uidtmp), "%u",
175: kauth_cred_geteuid(kauth_cred_get()));
176: SUBSTITUTE("uid", uidtmp, strlen(uidtmp));
1.63 thorpej 177: } else {
178: tmp[newlen++] = '@';
179: if (termchar == VC)
180: tmp[newlen++] = VO;
1.61 thorpej 181: }
182: }
183:
1.66 yamt 184: if (change) {
185: memcpy(cp, tmp, newlen);
186: *len = newlen;
187: }
188: PNBUF_PUT(tmp);
1.61 thorpej 189:
190: return (0);
191: }
192:
1.63 thorpej 193: #undef VNL
194: #undef VO
195: #undef VC
196: #undef MATCH
197: #undef SUBSTITUTE
198:
1.76 elad 199: int
200: pathname_get(const char *dirp, enum uio_seg segflg, pathname_t *path)
201: {
202: int error;
203:
204: if (dirp == NULL)
205: return (EFAULT);
206:
207: *path = malloc(sizeof(struct pathname_internal), M_TEMP,
208: M_ZERO|M_WAITOK);
209:
210: if (segflg == UIO_USERSPACE) {
211: (*path)->pathbuf = PNBUF_GET();
212: error = copyinstr(dirp, (*path)->pathbuf, MAXPATHLEN,
213: NULL);
214: if (error) {
215: PNBUF_PUT((*path)->pathbuf);
1.80 elad 216: free(*path, M_TEMP);
217: *path = NULL;
1.76 elad 218: return (error);
219: }
220: (*path)->needfree = TRUE;
221: } else {
222: (*path)->pathbuf = __UNCONST(dirp);
223: (*path)->needfree = FALSE;
224: }
225:
226: return (0);
227: }
228:
229: const char *
230: pathname_path(pathname_t path)
231: {
232: KASSERT(path != NULL);
233: return (path->pathbuf);
234: }
235:
236: void
237: pathname_put(pathname_t path)
238: {
239: if (path != NULL) {
240: if (path->pathbuf != NULL && path->needfree)
241: PNBUF_PUT(path->pathbuf);
242: free(path, M_TEMP);
243: }
244: }
245:
1.61 thorpej 246: /*
1.69 rumble 247: * Convert a pathname into a pointer to a locked vnode.
1.10 cgd 248: *
249: * The FOLLOW flag is set when symbolic links are to be followed
250: * when they occur at the end of the name translation process.
251: * Symbolic links are always followed for all other pathname
252: * components other than the last.
253: *
254: * The segflg defines whether the name is to be copied from user
255: * space or kernel space.
256: *
257: * Overall outline of namei:
258: *
259: * copy in name
260: * get starting directory
261: * while (!done && !error) {
262: * call lookup to search path.
263: * if symbolic link, massage name in buffer and continue
264: * }
265: */
1.12 mycroft 266: int
1.60 thorpej 267: namei(struct nameidata *ndp)
1.10 cgd 268: {
1.30 thorpej 269: struct cwdinfo *cwdi; /* pointer to cwd state */
1.33 augustss 270: char *cp; /* pointer into pathname argument */
271: struct vnode *dp; /* the directory we are searching */
1.10 cgd 272: struct iovec aiov; /* uio for reading symbolic links */
273: struct uio auio;
1.23 mycroft 274: int error, linklen;
1.12 mycroft 275: struct componentname *cnp = &ndp->ni_cnd;
1.10 cgd 276:
1.12 mycroft 277: #ifdef DIAGNOSTIC
1.64 christos 278: if (!cnp->cn_cred || !cnp->cn_lwp)
1.58 christos 279: panic("namei: bad cred/proc");
1.12 mycroft 280: if (cnp->cn_nameiop & (~OPMASK))
1.58 christos 281: panic("namei: nameiop contaminated with flags");
1.12 mycroft 282: if (cnp->cn_flags & OPMASK)
1.58 christos 283: panic("namei: flags contaminated with nameiops");
1.12 mycroft 284: #endif
1.64 christos 285: cwdi = cnp->cn_lwp->l_proc->p_cwdi;
1.10 cgd 286:
287: /*
288: * Get a buffer for the name to be translated, and copy the
289: * name into the buffer.
290: */
1.12 mycroft 291: if ((cnp->cn_flags & HASBUF) == 0)
1.35 thorpej 292: cnp->cn_pnbuf = PNBUF_GET();
1.10 cgd 293: if (ndp->ni_segflg == UIO_SYSSPACE)
1.12 mycroft 294: error = copystr(ndp->ni_dirp, cnp->cn_pnbuf,
1.10 cgd 295: MAXPATHLEN, &ndp->ni_pathlen);
296: else
1.12 mycroft 297: error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf,
1.10 cgd 298: MAXPATHLEN, &ndp->ni_pathlen);
1.21 kleink 299:
300: /*
301: * POSIX.1 requirement: "" is not a valid file name.
1.56 perry 302: */
1.21 kleink 303: if (!error && ndp->ni_pathlen == 1)
304: error = ENOENT;
305:
1.10 cgd 306: if (error) {
1.35 thorpej 307: PNBUF_PUT(cnp->cn_pnbuf);
1.10 cgd 308: ndp->ni_vp = NULL;
309: return (error);
310: }
311: ndp->ni_loopcnt = 0;
1.21 kleink 312:
1.10 cgd 313: #ifdef KTRACE
1.64 christos 314: if (KTRPOINT(cnp->cn_lwp->l_proc, KTR_NAMEI))
315: ktrnamei(cnp->cn_lwp, cnp->cn_pnbuf);
1.50 cb 316: #endif
317: #ifdef SYSTRACE
1.64 christos 318: if (ISSET(cnp->cn_lwp->l_proc->p_flag, P_SYSTRACE))
1.50 cb 319: systrace_namei(ndp);
1.10 cgd 320: #endif
321:
322: /*
323: * Get starting point for the translation.
324: */
1.30 thorpej 325: if ((ndp->ni_rootdir = cwdi->cwdi_rdir) == NULL)
1.11 cgd 326: ndp->ni_rootdir = rootvnode;
1.23 mycroft 327: /*
328: * Check if starting from root directory or current directory.
329: */
330: if (cnp->cn_pnbuf[0] == '/') {
331: dp = ndp->ni_rootdir;
332: VREF(dp);
333: } else {
1.30 thorpej 334: dp = cwdi->cwdi_cdir;
1.23 mycroft 335: VREF(dp);
336: }
1.73 chs 337: vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
1.10 cgd 338: for (;;) {
1.73 chs 339: if (!dp->v_mount) {
1.45 erh 340: /* Give up if the directory is no longer mounted */
1.73 chs 341: vput(dp);
1.45 erh 342: PNBUF_PUT(cnp->cn_pnbuf);
343: return (ENOENT);
344: }
1.12 mycroft 345: cnp->cn_nameptr = cnp->cn_pnbuf;
1.10 cgd 346: ndp->ni_startdir = dp;
1.73 chs 347: error = lookup(ndp);
348: if (error != 0) {
349: if (ndp->ni_dvp) {
350: vput(ndp->ni_dvp);
351: }
1.35 thorpej 352: PNBUF_PUT(cnp->cn_pnbuf);
1.10 cgd 353: return (error);
354: }
1.73 chs 355:
1.10 cgd 356: /*
357: * Check for symbolic link
358: */
1.12 mycroft 359: if ((cnp->cn_flags & ISSYMLINK) == 0) {
1.73 chs 360: if ((cnp->cn_flags & LOCKPARENT) == 0 && ndp->ni_dvp) {
361: if (ndp->ni_dvp == ndp->ni_vp) {
362: vrele(ndp->ni_dvp);
363: } else {
364: vput(ndp->ni_dvp);
365: }
366: }
1.12 mycroft 367: if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0)
1.35 thorpej 368: PNBUF_PUT(cnp->cn_pnbuf);
1.10 cgd 369: else
1.12 mycroft 370: cnp->cn_flags |= HASBUF;
1.10 cgd 371: return (0);
372: }
1.73 chs 373:
1.10 cgd 374: if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
375: error = ELOOP;
376: break;
377: }
1.25 enami 378: if (ndp->ni_vp->v_mount->mnt_flag & MNT_SYMPERM) {
379: error = VOP_ACCESS(ndp->ni_vp, VEXEC, cnp->cn_cred,
1.64 christos 380: cnp->cn_lwp);
1.25 enami 381: if (error != 0)
382: break;
383: }
1.10 cgd 384: if (ndp->ni_pathlen > 1)
1.35 thorpej 385: cp = PNBUF_GET();
1.10 cgd 386: else
1.12 mycroft 387: cp = cnp->cn_pnbuf;
1.10 cgd 388: aiov.iov_base = cp;
389: aiov.iov_len = MAXPATHLEN;
390: auio.uio_iov = &aiov;
391: auio.uio_iovcnt = 1;
392: auio.uio_offset = 0;
393: auio.uio_rw = UIO_READ;
394: auio.uio_resid = MAXPATHLEN;
1.68 yamt 395: UIO_SETUP_SYSSPACE(&auio);
1.16 christos 396: error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
397: if (error) {
1.73 chs 398: badlink:
1.10 cgd 399: if (ndp->ni_pathlen > 1)
1.35 thorpej 400: PNBUF_PUT(cp);
1.10 cgd 401: break;
402: }
403: linklen = MAXPATHLEN - auio.uio_resid;
1.23 mycroft 404: if (linklen == 0) {
405: error = ENOENT;
406: goto badlink;
407: }
1.73 chs 408:
1.61 thorpej 409: /*
410: * Do symlink substitution, if appropriate, and
411: * check length for potential overflow.
412: */
1.67 chs 413: if ((vfs_magiclinks &&
1.64 christos 414: symlink_magic(cnp->cn_lwp->l_proc, cp, &linklen)) ||
1.61 thorpej 415: (linklen + ndp->ni_pathlen >= MAXPATHLEN)) {
1.10 cgd 416: error = ENAMETOOLONG;
1.23 mycroft 417: goto badlink;
1.10 cgd 418: }
419: if (ndp->ni_pathlen > 1) {
1.28 perry 420: memcpy(cp + linklen, ndp->ni_next, ndp->ni_pathlen);
1.35 thorpej 421: PNBUF_PUT(cnp->cn_pnbuf);
1.12 mycroft 422: cnp->cn_pnbuf = cp;
1.10 cgd 423: } else
1.12 mycroft 424: cnp->cn_pnbuf[linklen] = '\0';
1.10 cgd 425: ndp->ni_pathlen += linklen;
426: vput(ndp->ni_vp);
427: dp = ndp->ni_dvp;
1.73 chs 428:
1.23 mycroft 429: /*
430: * Check if root directory should replace current directory.
431: */
432: if (cnp->cn_pnbuf[0] == '/') {
1.73 chs 433: vput(dp);
1.23 mycroft 434: dp = ndp->ni_rootdir;
435: VREF(dp);
1.73 chs 436: vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
1.23 mycroft 437: }
1.10 cgd 438: }
1.73 chs 439: KASSERT(ndp->ni_dvp != ndp->ni_vp);
440: vput(ndp->ni_dvp);
1.10 cgd 441: vput(ndp->ni_vp);
442: ndp->ni_vp = NULL;
1.73 chs 443: PNBUF_PUT(cnp->cn_pnbuf);
1.10 cgd 444: return (error);
445: }
446:
447: /*
1.39 lukem 448: * Determine the namei hash (for cn_hash) for name.
449: * If *ep != NULL, hash from name to ep-1.
450: * If *ep == NULL, hash from name until the first NUL or '/', and
451: * return the location of this termination character in *ep.
452: *
453: * This function returns an equivalent hash to the MI hash32_strn().
454: * The latter isn't used because in the *ep == NULL case, determining
455: * the length of the string to the first NUL or `/' and then calling
456: * hash32_strn() involves unnecessary double-handling of the data.
457: */
458: uint32_t
459: namei_hash(const char *name, const char **ep)
460: {
461: uint32_t hash;
462:
463: hash = HASH32_STR_INIT;
464: if (*ep != NULL) {
465: for (; name < *ep; name++)
1.59 christos 466: hash = hash * 33 + *(const uint8_t *)name;
1.39 lukem 467: } else {
468: for (; *name != '\0' && *name != '/'; name++)
1.59 christos 469: hash = hash * 33 + *(const uint8_t *)name;
1.39 lukem 470: *ep = name;
471: }
472: return (hash + (hash >> 5));
473: }
474:
475: /*
1.10 cgd 476: * Search a pathname.
477: * This is a very central and rather complicated routine.
478: *
479: * The pathname is pointed to by ni_ptr and is of length ni_pathlen.
480: * The starting directory is taken from ni_startdir. The pathname is
481: * descended until done, or a symbolic link is encountered. The variable
482: * ni_more is clear if the path is completed; it is set to one if a
483: * symbolic link needing interpretation is encountered.
484: *
485: * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on
486: * whether the name is to be looked up, created, renamed, or deleted.
487: * When CREATE, RENAME, or DELETE is specified, information usable in
488: * creating, renaming, or deleting a directory entry may be calculated.
489: * If flag has LOCKPARENT or'ed into it, the parent directory is returned
1.79 pooka 490: * locked. Otherwise the parent directory is not returned. If the target
491: * of the pathname exists and LOCKLEAF is or'ed into the flag the target
492: * is returned locked, otherwise it is returned unlocked. When creating
493: * or renaming and LOCKPARENT is specified, the target may not be ".".
494: * When deleting and LOCKPARENT is specified, the target may be ".".
1.56 perry 495: *
1.10 cgd 496: * Overall outline of lookup:
497: *
498: * dirloop:
499: * identify next component of name at ndp->ni_ptr
500: * handle degenerate case where name is null string
501: * if .. and crossing mount points and on mounted filesys, find parent
502: * call VOP_LOOKUP routine for next component name
1.79 pooka 503: * directory vnode returned in ni_dvp, locked.
1.10 cgd 504: * component vnode returned in ni_vp (if it exists), locked.
505: * if result vnode is mounted on and crossing mount points,
506: * find mounted on vnode
507: * if more components of name, do next level at dirloop
508: * return the answer in ni_vp, locked if LOCKLEAF set
509: * if LOCKPARENT set, return locked parent in ni_dvp
510: */
1.12 mycroft 511: int
1.60 thorpej 512: lookup(struct nameidata *ndp)
1.10 cgd 513: {
1.33 augustss 514: const char *cp; /* pointer into pathname argument */
515: struct vnode *dp = 0; /* the directory we are searching */
1.10 cgd 516: struct vnode *tdp; /* saved dp */
517: struct mount *mp; /* mount table entry */
518: int docache; /* == 0 do not cache last component */
1.12 mycroft 519: int rdonly; /* lookup read-only flag bit */
1.10 cgd 520: int error = 0;
1.23 mycroft 521: int slashes;
1.12 mycroft 522: struct componentname *cnp = &ndp->ni_cnd;
1.64 christos 523: struct lwp *l = cnp->cn_lwp;
1.10 cgd 524:
525: /*
526: * Setup: break out flag bits into variables.
527: */
1.12 mycroft 528: docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE;
1.78 pooka 529: if (cnp->cn_nameiop == DELETE)
1.10 cgd 530: docache = 0;
1.12 mycroft 531: rdonly = cnp->cn_flags & RDONLY;
1.10 cgd 532: ndp->ni_dvp = NULL;
1.12 mycroft 533: cnp->cn_flags &= ~ISSYMLINK;
1.10 cgd 534: dp = ndp->ni_startdir;
535: ndp->ni_startdir = NULLVP;
536:
1.23 mycroft 537: /*
538: * If we have a leading string of slashes, remove them, and just make
539: * sure the current node is a directory.
540: */
541: cp = cnp->cn_nameptr;
542: if (*cp == '/') {
543: do {
544: cp++;
545: } while (*cp == '/');
546: ndp->ni_pathlen -= cp - cnp->cn_nameptr;
547: cnp->cn_nameptr = cp;
548:
549: if (dp->v_type != VDIR) {
550: error = ENOTDIR;
1.75 yamt 551: vput(dp);
1.23 mycroft 552: goto bad;
553: }
554:
555: /*
556: * If we've exhausted the path name, then just return the
557: * current node. If the caller requested the parent node (i.e.
558: * it's a CREATE, DELETE, or RENAME), and we don't have one
559: * (because this is the root directory), then we must fail.
560: */
561: if (cnp->cn_nameptr[0] == '\0') {
1.73 chs 562: if (ndp->ni_dvp == NULL && cnp->cn_nameiop != LOOKUP) {
1.65 chs 563: switch (cnp->cn_nameiop) {
564: case CREATE:
565: error = EEXIST;
566: break;
567: case DELETE:
568: case RENAME:
569: error = EBUSY;
570: break;
571: default:
572: KASSERT(0);
573: }
1.74 chs 574: vput(dp);
1.23 mycroft 575: goto bad;
576: }
577: ndp->ni_vp = dp;
578: cnp->cn_flags |= ISLASTCN;
579: goto terminal;
580: }
581: }
582:
1.10 cgd 583: dirloop:
584: /*
585: * Search a new directory.
586: *
1.12 mycroft 587: * The cn_hash value is for use by vfs_cache.
1.10 cgd 588: * The last component of the filename is left accessible via
1.12 mycroft 589: * cnp->cn_nameptr for callers that need the name. Callers needing
1.10 cgd 590: * the name set the SAVENAME flag. When done, they assume
591: * responsibility for freeing the pathname buffer.
1.73 chs 592: *
593: * At this point, our only vnode state is that "dp" is held and locked.
1.10 cgd 594: */
1.12 mycroft 595: cnp->cn_consume = 0;
1.39 lukem 596: cp = NULL;
597: cnp->cn_hash = namei_hash(cnp->cn_nameptr, &cp);
1.12 mycroft 598: cnp->cn_namelen = cp - cnp->cn_nameptr;
599: if (cnp->cn_namelen > NAME_MAX) {
1.75 yamt 600: vput(dp);
1.10 cgd 601: error = ENAMETOOLONG;
1.77 chs 602: ndp->ni_dvp = NULL;
1.10 cgd 603: goto bad;
604: }
605: #ifdef NAMEI_DIAGNOSTIC
606: { char c = *cp;
1.41 soren 607: *(char *)cp = '\0';
1.19 christos 608: printf("{%s}: ", cnp->cn_nameptr);
1.41 soren 609: *(char *)cp = c; }
1.52 yamt 610: #endif /* NAMEI_DIAGNOSTIC */
1.12 mycroft 611: ndp->ni_pathlen -= cnp->cn_namelen;
1.10 cgd 612: ndp->ni_next = cp;
1.23 mycroft 613: /*
614: * If this component is followed by a slash, then move the pointer to
615: * the next component forward, and remember that this component must be
616: * a directory.
617: */
618: if (*cp == '/') {
619: do {
620: cp++;
621: } while (*cp == '/');
622: slashes = cp - ndp->ni_next;
623: ndp->ni_pathlen -= slashes;
624: ndp->ni_next = cp;
625: cnp->cn_flags |= REQUIREDIR;
626: } else {
627: slashes = 0;
628: cnp->cn_flags &= ~REQUIREDIR;
629: }
630: /*
631: * We do special processing on the last component, whether or not it's
632: * a directory. Cache all intervening lookups, but not the final one.
633: */
634: if (*cp == '\0') {
635: if (docache)
636: cnp->cn_flags |= MAKEENTRY;
637: else
638: cnp->cn_flags &= ~MAKEENTRY;
639: cnp->cn_flags |= ISLASTCN;
640: } else {
641: cnp->cn_flags |= MAKEENTRY;
642: cnp->cn_flags &= ~ISLASTCN;
643: }
1.12 mycroft 644: if (cnp->cn_namelen == 2 &&
645: cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.')
646: cnp->cn_flags |= ISDOTDOT;
647: else
648: cnp->cn_flags &= ~ISDOTDOT;
1.10 cgd 649:
650: /*
651: * Handle "..": two special cases.
652: * 1. If at root directory (e.g. after chroot)
1.12 mycroft 653: * or at absolute root directory
1.10 cgd 654: * then ignore it so can't get out.
1.40 wrstuden 655: * 1a. If we have somehow gotten out of a jail, warn
656: * and also ignore it so we can't get farther out.
1.10 cgd 657: * 2. If this vnode is the root of a mounted
658: * filesystem, then replace it with the
659: * vnode which was mounted on so we take the
660: * .. in the other file system.
661: */
1.12 mycroft 662: if (cnp->cn_flags & ISDOTDOT) {
1.64 christos 663: struct proc *p = l->l_proc;
664:
1.10 cgd 665: for (;;) {
1.12 mycroft 666: if (dp == ndp->ni_rootdir || dp == rootvnode) {
1.10 cgd 667: ndp->ni_dvp = dp;
668: ndp->ni_vp = dp;
669: VREF(dp);
670: goto nextname;
1.40 wrstuden 671: }
672: if (ndp->ni_rootdir != rootvnode) {
673: int retval;
1.73 chs 674:
1.40 wrstuden 675: VOP_UNLOCK(dp, 0);
1.64 christos 676: retval = vn_isunder(dp, ndp->ni_rootdir, l);
1.40 wrstuden 677: vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
678: if (!retval) {
679: /* Oops! We got out of jail! */
680: log(LOG_WARNING,
681: "chrooted pid %d uid %d (%s) "
682: "detected outside of its chroot\n",
1.71 ad 683: p->p_pid, kauth_cred_geteuid(l->l_cred),
1.64 christos 684: p->p_comm);
1.40 wrstuden 685: /* Put us at the jail root. */
686: vput(dp);
687: dp = ndp->ni_rootdir;
688: ndp->ni_dvp = dp;
689: ndp->ni_vp = dp;
690: VREF(dp);
691: VREF(dp);
692: vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
693: goto nextname;
694: }
1.10 cgd 695: }
696: if ((dp->v_flag & VROOT) == 0 ||
1.12 mycroft 697: (cnp->cn_flags & NOCROSSMOUNT))
1.10 cgd 698: break;
699: tdp = dp;
700: dp = dp->v_mount->mnt_vnodecovered;
701: vput(tdp);
702: VREF(dp);
1.26 fvdl 703: vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
1.10 cgd 704: }
705: }
706:
707: /*
708: * We now have a segment name to search for, and a directory to search.
1.73 chs 709: * Again, our only vnode state is that "dp" is held and locked.
1.10 cgd 710: */
1.12 mycroft 711: unionlookup:
712: ndp->ni_dvp = dp;
1.26 fvdl 713: ndp->ni_vp = NULL;
1.73 chs 714: error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp);
715: if (error != 0) {
1.10 cgd 716: #ifdef DIAGNOSTIC
717: if (ndp->ni_vp != NULL)
1.43 christos 718: panic("leaf `%s' should be empty", cnp->cn_nameptr);
1.52 yamt 719: #endif /* DIAGNOSTIC */
1.10 cgd 720: #ifdef NAMEI_DIAGNOSTIC
1.19 christos 721: printf("not found\n");
1.52 yamt 722: #endif /* NAMEI_DIAGNOSTIC */
1.12 mycroft 723: if ((error == ENOENT) &&
1.10 cgd 724: (dp->v_flag & VROOT) &&
725: (dp->v_mount->mnt_flag & MNT_UNION)) {
726: tdp = dp;
727: dp = dp->v_mount->mnt_vnodecovered;
1.73 chs 728: vput(tdp);
1.10 cgd 729: VREF(dp);
1.26 fvdl 730: vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
1.12 mycroft 731: goto unionlookup;
1.10 cgd 732: }
1.12 mycroft 733:
1.10 cgd 734: if (error != EJUSTRETURN)
735: goto bad;
1.73 chs 736:
1.10 cgd 737: /*
1.23 mycroft 738: * If this was not the last component, or there were trailing
1.51 christos 739: * slashes, and we are not going to create a directory,
740: * then the name must exist.
1.23 mycroft 741: */
1.51 christos 742: if ((cnp->cn_flags & (REQUIREDIR | CREATEDIR)) == REQUIREDIR) {
1.23 mycroft 743: error = ENOENT;
744: goto bad;
745: }
1.73 chs 746:
1.23 mycroft 747: /*
1.10 cgd 748: * If creating and at end of pathname, then can consider
749: * allowing file to be created.
750: */
1.26 fvdl 751: if (rdonly) {
1.10 cgd 752: error = EROFS;
753: goto bad;
754: }
1.73 chs 755:
1.10 cgd 756: /*
757: * We return with ni_vp NULL to indicate that the entry
758: * doesn't currently exist, leaving a pointer to the
1.69 rumble 759: * (possibly locked) directory vnode in ndp->ni_dvp.
1.10 cgd 760: */
1.12 mycroft 761: if (cnp->cn_flags & SAVESTART) {
1.10 cgd 762: ndp->ni_startdir = ndp->ni_dvp;
763: VREF(ndp->ni_startdir);
764: }
765: return (0);
766: }
767: #ifdef NAMEI_DIAGNOSTIC
1.19 christos 768: printf("found\n");
1.52 yamt 769: #endif /* NAMEI_DIAGNOSTIC */
1.10 cgd 770:
1.12 mycroft 771: /*
1.23 mycroft 772: * Take into account any additional components consumed by the
773: * underlying filesystem. This will include any trailing slashes after
774: * the last component consumed.
1.12 mycroft 775: */
776: if (cnp->cn_consume > 0) {
1.23 mycroft 777: ndp->ni_pathlen -= cnp->cn_consume - slashes;
778: ndp->ni_next += cnp->cn_consume - slashes;
1.12 mycroft 779: cnp->cn_consume = 0;
1.23 mycroft 780: if (ndp->ni_next[0] == '\0')
781: cnp->cn_flags |= ISLASTCN;
1.12 mycroft 782: }
783:
1.10 cgd 784: dp = ndp->ni_vp;
1.73 chs 785:
786: /*
787: * "dp" and "ndp->ni_dvp" are both locked and held,
788: * and may be the same vnode.
789: */
790:
1.10 cgd 791: /*
792: * Check to see if the vnode has been mounted on;
793: * if so find the root of the mounted file system.
794: */
795: while (dp->v_type == VDIR && (mp = dp->v_mountedhere) &&
1.12 mycroft 796: (cnp->cn_flags & NOCROSSMOUNT) == 0) {
1.26 fvdl 797: if (vfs_busy(mp, 0, 0))
1.12 mycroft 798: continue;
1.73 chs 799:
800: KASSERT(ndp->ni_dvp != dp);
1.77 chs 801: VOP_UNLOCK(ndp->ni_dvp, 0);
1.73 chs 802: vput(dp);
1.47 thorpej 803: error = VFS_ROOT(mp, &tdp);
1.26 fvdl 804: vfs_unbusy(mp);
1.32 wrstuden 805: if (error) {
1.77 chs 806: vn_lock(ndp->ni_dvp, LK_EXCLUSIVE | LK_RETRY);
1.73 chs 807: goto bad;
1.32 wrstuden 808: }
1.77 chs 809: VOP_UNLOCK(tdp, 0);
1.10 cgd 810: ndp->ni_vp = dp = tdp;
1.77 chs 811: vn_lock(ndp->ni_dvp, LK_EXCLUSIVE | LK_RETRY);
812: vn_lock(ndp->ni_vp, LK_EXCLUSIVE | LK_RETRY);
1.14 mycroft 813: }
814:
815: /*
1.23 mycroft 816: * Check for symbolic link. Back up over any slashes that we skipped,
817: * as we will need them again.
1.14 mycroft 818: */
1.23 mycroft 819: if ((dp->v_type == VLNK) && (cnp->cn_flags & (FOLLOW|REQUIREDIR))) {
820: ndp->ni_pathlen += slashes;
821: ndp->ni_next -= slashes;
1.14 mycroft 822: cnp->cn_flags |= ISSYMLINK;
823: return (0);
1.10 cgd 824: }
825:
1.23 mycroft 826: /*
827: * Check for directory, if the component was followed by a series of
828: * slashes.
829: */
830: if ((dp->v_type != VDIR) && (cnp->cn_flags & REQUIREDIR)) {
831: error = ENOTDIR;
1.73 chs 832: KASSERT(dp != ndp->ni_dvp);
833: vput(dp);
834: goto bad;
1.23 mycroft 835: }
836:
1.10 cgd 837: nextname:
1.73 chs 838:
1.10 cgd 839: /*
1.23 mycroft 840: * Not a symbolic link. If this was not the last component, then
841: * continue at the next component, else return.
1.10 cgd 842: */
1.23 mycroft 843: if (!(cnp->cn_flags & ISLASTCN)) {
1.12 mycroft 844: cnp->cn_nameptr = ndp->ni_next;
1.73 chs 845: if (ndp->ni_dvp == dp) {
846: vrele(ndp->ni_dvp);
847: } else {
848: vput(ndp->ni_dvp);
849: }
1.10 cgd 850: goto dirloop;
851: }
1.23 mycroft 852:
853: terminal:
1.73 chs 854:
1.10 cgd 855: /*
1.26 fvdl 856: * Disallow directory write attempts on read-only file systems.
1.10 cgd 857: */
1.26 fvdl 858: if (rdonly &&
859: (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
1.73 chs 860:
1.10 cgd 861: /*
862: * Disallow directory write attempts on read-only
863: * file systems.
864: */
1.26 fvdl 865: error = EROFS;
1.73 chs 866: if (dp != ndp->ni_dvp) {
867: vput(dp);
868: }
869: goto bad;
1.10 cgd 870: }
1.23 mycroft 871: if (ndp->ni_dvp != NULL) {
872: if (cnp->cn_flags & SAVESTART) {
873: ndp->ni_startdir = ndp->ni_dvp;
874: VREF(ndp->ni_startdir);
875: }
1.10 cgd 876: }
1.73 chs 877: if ((cnp->cn_flags & LOCKLEAF) == 0) {
1.26 fvdl 878: VOP_UNLOCK(dp, 0);
1.73 chs 879: }
1.10 cgd 880: return (0);
881:
882: bad:
883: ndp->ni_vp = NULL;
1.12 mycroft 884: return (error);
885: }
886:
887: /*
888: * Reacquire a path name component.
1.73 chs 889: * dvp is locked on entry and exit.
890: * *vpp is locked on exit unless it's NULL.
1.12 mycroft 891: */
892: int
1.60 thorpej 893: relookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp)
1.12 mycroft 894: {
895: int rdonly; /* lookup read-only flag bit */
896: int error = 0;
1.52 yamt 897: #ifdef DEBUG
1.81 ! chs 898: uint32_t newhash; /* DEBUG: check name hash */
1.41 soren 899: const char *cp; /* DEBUG: check name ptr/len */
1.52 yamt 900: #endif /* DEBUG */
1.12 mycroft 901:
902: /*
903: * Setup: break out flag bits into variables.
904: */
905: rdonly = cnp->cn_flags & RDONLY;
906: cnp->cn_flags &= ~ISSYMLINK;
907:
908: /*
909: * Search a new directory.
910: *
911: * The cn_hash value is for use by vfs_cache.
912: * The last component of the filename is left accessible via
913: * cnp->cn_nameptr for callers that need the name. Callers needing
914: * the name set the SAVENAME flag. When done, they assume
915: * responsibility for freeing the pathname buffer.
916: */
1.52 yamt 917: #ifdef DEBUG
1.39 lukem 918: cp = NULL;
919: newhash = namei_hash(cnp->cn_nameptr, &cp);
1.81 ! chs 920: if ((uint32_t)newhash != (uint32_t)cnp->cn_hash)
1.12 mycroft 921: panic("relookup: bad hash");
922: if (cnp->cn_namelen != cp - cnp->cn_nameptr)
1.58 christos 923: panic("relookup: bad len");
1.53 yamt 924: while (*cp == '/')
925: cp++;
1.12 mycroft 926: if (*cp != 0)
927: panic("relookup: not last component");
1.52 yamt 928: #endif /* DEBUG */
1.12 mycroft 929:
930: /*
931: * Check for degenerate name (e.g. / or "")
932: * which is a way of talking about a directory,
933: * e.g. like "/." or ".".
934: */
1.23 mycroft 935: if (cnp->cn_nameptr[0] == '\0')
936: panic("relookup: null name");
1.12 mycroft 937:
938: if (cnp->cn_flags & ISDOTDOT)
1.58 christos 939: panic("relookup: lookup on dot-dot");
1.12 mycroft 940:
941: /*
942: * We now have a segment name to search for, and a directory to search.
943: */
1.81 ! chs 944: if ((error = VOP_LOOKUP(dvp, vpp, cnp)) != 0) {
1.12 mycroft 945: #ifdef DIAGNOSTIC
946: if (*vpp != NULL)
1.43 christos 947: panic("leaf `%s' should be empty", cnp->cn_nameptr);
1.12 mycroft 948: #endif
949: if (error != EJUSTRETURN)
950: goto bad;
951: }
952:
953: #ifdef DIAGNOSTIC
954: /*
955: * Check for symbolic link
956: */
1.81 ! chs 957: if (*vpp && (*vpp)->v_type == VLNK && (cnp->cn_flags & FOLLOW))
1.58 christos 958: panic("relookup: symlink found");
1.12 mycroft 959: #endif
960:
961: /*
962: * Check for read-only file systems.
963: */
1.81 ! chs 964: if (rdonly && cnp->cn_nameiop != LOOKUP) {
1.26 fvdl 965: error = EROFS;
1.81 ! chs 966: if (*vpp) {
! 967: vput(*vpp);
! 968: }
1.73 chs 969: goto bad;
1.12 mycroft 970: }
971: if (cnp->cn_flags & SAVESTART)
972: VREF(dvp);
973: return (0);
974:
975: bad:
976: *vpp = NULL;
1.10 cgd 977: return (error);
978: }
CVSweb <webmaster@jp.NetBSD.org>