The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/vfs_lookup.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: vfs_lookup.c,v 1.110.4.1 2008/11/17 19:01:15 snj Exp $ */
    2 
    3 /*
    4  * Copyright (c) 1982, 1986, 1989, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    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.
   20  * 3. Neither the name of the University nor the names of its contributors
   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  *
   36  *      @(#)vfs_lookup.c        8.10 (Berkeley) 5/27/95
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.110.4.1 2008/11/17 19:01:15 snj Exp $");
   41 
   42 #include "opt_magiclinks.h"
   43 
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #include <sys/kernel.h>
   47 #include <sys/syslimits.h>
   48 #include <sys/time.h>
   49 #include <sys/namei.h>
   50 #include <sys/vnode.h>
   51 #include <sys/mount.h>
   52 #include <sys/errno.h>
   53 #include <sys/filedesc.h>
   54 #include <sys/hash.h>
   55 #include <sys/malloc.h>
   56 #include <sys/proc.h>
   57 #include <sys/syslog.h>
   58 #include <sys/kauth.h>
   59 #include <sys/ktrace.h>
   60 
   61 #ifndef MAGICLINKS
   62 #define MAGICLINKS 0
   63 #endif
   64 
   65 struct pathname_internal {
   66         char *pathbuf;
   67         bool needfree;
   68 };
   69 
   70 int vfs_magiclinks = MAGICLINKS;
   71 
   72 pool_cache_t pnbuf_cache;       /* pathname buffer cache */
   73 
   74 /*
   75  * Substitute replacement text for 'magic' strings in symlinks.
   76  * Returns 0 if successful, and returns non-zero if an error
   77  * occurs.  (Currently, the only possible error is running out
   78  * of temporary pathname space.)
   79  *
   80  * Looks for "@<string>" and "@<string>/", where <string> is a
   81  * recognized 'magic' string.  Replaces the "@<string>" with the
   82  * appropriate replacement text.  (Note that in some cases the
   83  * replacement text may have zero length.)
   84  *
   85  * This would have been table driven, but the variance in
   86  * replacement strings (and replacement string lengths) made
   87  * that impractical.
   88  */
   89 #define VNL(x)                                                  \
   90         (sizeof(x) - 1)
   91 
   92 #define VO      '{'
   93 #define VC      '}'
   94 
   95 #define MATCH(str)                                              \
   96         ((termchar == '/' && i + VNL(str) == *len) ||           \
   97          (i + VNL(str) < *len &&                                \
   98           cp[i + VNL(str)] == termchar)) &&                     \
   99         !strncmp((str), &cp[i], VNL(str))
  100 
  101 #define SUBSTITUTE(m, s, sl)                                    \
  102         if ((newlen + (sl)) > MAXPATHLEN)                       \
  103                 return (1);                                     \
  104         i += VNL(m);                                            \
  105         if (termchar != '/')                                    \
  106                 i++;                                            \
  107         memcpy(&tmp[newlen], (s), (sl));                        \
  108         newlen += (sl);                                         \
  109         change = 1;                                             \
  110         termchar = '/';
  111 
  112 static int
  113 symlink_magic(struct proc *p, char *cp, int *len)
  114 {
  115         char *tmp;
  116         int change, i, newlen;
  117         int termchar = '/';
  118         char uidtmp[11]; /* XXX elad */
  119 
  120 
  121         tmp = PNBUF_GET();
  122         for (change = i = newlen = 0; i < *len; ) {
  123                 if (cp[i] != '@') {
  124                         tmp[newlen++] = cp[i++];
  125                         continue;
  126                 }
  127 
  128                 i++;
  129 
  130                 /* Check for @{var} syntax. */
  131                 if (cp[i] == VO) {
  132                         termchar = VC;
  133                         i++;
  134                 }
  135 
  136                 /*
  137                  * The following checks should be ordered according
  138                  * to frequency of use.
  139                  */
  140                 if (MATCH("machine_arch")) {
  141                         SUBSTITUTE("machine_arch", MACHINE_ARCH,
  142                             sizeof(MACHINE_ARCH) - 1);
  143                 } else if (MATCH("machine")) {
  144                         SUBSTITUTE("machine", MACHINE,
  145                             sizeof(MACHINE) - 1);
  146                 } else if (MATCH("hostname")) {
  147                         SUBSTITUTE("hostname", hostname,
  148                             hostnamelen);
  149                 } else if (MATCH("osrelease")) {
  150                         SUBSTITUTE("osrelease", osrelease,
  151                             strlen(osrelease));
  152                 } else if (MATCH("emul")) {
  153                         SUBSTITUTE("emul", p->p_emul->e_name,
  154                             strlen(p->p_emul->e_name));
  155                 } else if (MATCH("kernel_ident")) {
  156                         SUBSTITUTE("kernel_ident", kernel_ident,
  157                             strlen(kernel_ident));
  158                 } else if (MATCH("domainname")) {
  159                         SUBSTITUTE("domainname", domainname,
  160                             domainnamelen);
  161                 } else if (MATCH("ostype")) {
  162                         SUBSTITUTE("ostype", ostype,
  163                             strlen(ostype));
  164                 } else if (MATCH("uid")) {
  165                         (void)snprintf(uidtmp, sizeof(uidtmp), "%u",
  166                             kauth_cred_geteuid(kauth_cred_get()));
  167                         SUBSTITUTE("uid", uidtmp, strlen(uidtmp));
  168                 } else if (MATCH("ruid")) {
  169                         (void)snprintf(uidtmp, sizeof(uidtmp), "%u",
  170                             kauth_cred_getuid(kauth_cred_get()));
  171                         SUBSTITUTE("ruid", uidtmp, strlen(uidtmp));
  172                 } else {
  173                         tmp[newlen++] = '@';
  174                         if (termchar == VC)
  175                                 tmp[newlen++] = VO;
  176                 }
  177         }
  178 
  179         if (change) {
  180                 memcpy(cp, tmp, newlen);
  181                 *len = newlen;
  182         }
  183         PNBUF_PUT(tmp);
  184 
  185         return (0);
  186 }
  187 
  188 #undef VNL
  189 #undef VO
  190 #undef VC
  191 #undef MATCH
  192 #undef SUBSTITUTE
  193 
  194 /*
  195  * Convert a pathname into a pointer to a locked vnode.
  196  *
  197  * The FOLLOW flag is set when symbolic links are to be followed
  198  * when they occur at the end of the name translation process.
  199  * Symbolic links are always followed for all other pathname
  200  * components other than the last.
  201  *
  202  * The segflg defines whether the name is to be copied from user
  203  * space or kernel space.
  204  *
  205  * Overall outline of namei:
  206  *
  207  *      copy in name
  208  *      get starting directory
  209  *      while (!done && !error) {
  210  *              call lookup to search path.
  211  *              if symbolic link, massage name in buffer and continue
  212  *      }
  213  */
  214 int
  215 namei(struct nameidata *ndp)
  216 {
  217         struct cwdinfo *cwdi;           /* pointer to cwd state */
  218         char *cp;                       /* pointer into pathname argument */
  219         struct vnode *dp;               /* the directory we are searching */
  220         struct iovec aiov;              /* uio for reading symbolic links */
  221         struct lwp *l = curlwp;         /* thread doing namei() */
  222         struct uio auio;
  223         int error, linklen;
  224         struct componentname *cnp = &ndp->ni_cnd;
  225 
  226 #ifdef DIAGNOSTIC
  227         if (!cnp->cn_cred)
  228                 panic("namei: bad cred/proc");
  229         if (cnp->cn_nameiop & (~OPMASK))
  230                 panic("namei: nameiop contaminated with flags");
  231         if (cnp->cn_flags & OPMASK)
  232                 panic("namei: flags contaminated with nameiops");
  233 #endif
  234 
  235         /*
  236          * Get a buffer for the name to be translated, and copy the
  237          * name into the buffer.
  238          */
  239         if ((cnp->cn_flags & HASBUF) == 0)
  240                 cnp->cn_pnbuf = PNBUF_GET();
  241     emul_retry:
  242         if (ndp->ni_segflg == UIO_SYSSPACE)
  243                 error = copystr(ndp->ni_dirp, cnp->cn_pnbuf,
  244                             MAXPATHLEN, &ndp->ni_pathlen);
  245         else
  246                 error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf,
  247                             MAXPATHLEN, &ndp->ni_pathlen);
  248 
  249         /*
  250          * POSIX.1 requirement: "" is not a valid file name.
  251          */
  252         if (!error && ndp->ni_pathlen == 1)
  253                 error = ENOENT;
  254 
  255         if (error) {
  256                 PNBUF_PUT(cnp->cn_pnbuf);
  257                 ndp->ni_vp = NULL;
  258                 return (error);
  259         }
  260         ndp->ni_loopcnt = 0;
  261 
  262         /*
  263          * Get root directory for the translation.
  264          */
  265         cwdi = l->l_proc->p_cwdi;
  266         rw_enter(&cwdi->cwdi_lock, RW_READER);
  267         dp = cwdi->cwdi_rdir;
  268         if (dp == NULL)
  269                 dp = rootvnode;
  270         ndp->ni_rootdir = dp;
  271 
  272         /*
  273          * Check if starting from root directory or current directory.
  274          */
  275         if (cnp->cn_pnbuf[0] == '/') {
  276                 if (cnp->cn_flags & TRYEMULROOT) {
  277                         if (cnp->cn_flags & EMULROOTSET) {
  278                                 /* Called from (eg) emul_find_interp() */
  279                                 dp = ndp->ni_erootdir;
  280                         } else {
  281                                 if (cwdi->cwdi_edir == NULL
  282                                     || (cnp->cn_pnbuf[1] == '.' 
  283                                            && cnp->cn_pnbuf[2] == '.' 
  284                                            && cnp->cn_pnbuf[3] == '/')) {
  285                                         ndp->ni_erootdir = NULL;
  286                                 } else {
  287                                         dp = cwdi->cwdi_edir;
  288                                         ndp->ni_erootdir = dp;
  289                                 }
  290                         }
  291                 } else if (cnp->cn_flags & NOCHROOT) {
  292                         ndp->ni_rootdir = rootvnode;
  293                 } else {
  294                         ndp->ni_erootdir = NULL;
  295                 }
  296         } else {
  297                 dp = cwdi->cwdi_cdir;
  298                 ndp->ni_erootdir = NULL;
  299         }
  300         VREF(dp);
  301         rw_exit(&cwdi->cwdi_lock);
  302  
  303         if (ktrpoint(KTR_NAMEI)) {
  304                 if (ndp->ni_erootdir != NULL) {
  305                         /*
  306                          * To make any sense, the trace entry need to have the
  307                          * text of the emulation path prepended.
  308                          * Usually we can get this from the current process,
  309                          * but when called from emul_find_interp() it is only
  310                          * in the exec_package - so we get it passed in ni_next
  311                          * (this is a hack).
  312                          */
  313                         const char *emul_path;
  314                         if (cnp->cn_flags & EMULROOTSET)
  315                                 emul_path = ndp->ni_next;
  316                         else
  317                                 emul_path = l->l_proc->p_emul->e_path;
  318                         ktrnamei2(emul_path, strlen(emul_path),
  319                             cnp->cn_pnbuf, ndp->ni_pathlen);
  320                 } else
  321                         ktrnamei(cnp->cn_pnbuf, ndp->ni_pathlen);
  322         }
  323 
  324         vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
  325         /* Loop through symbolic links */
  326         for (;;) {
  327                 if (!dp->v_mount) {
  328                         /* Give up if the directory is no longer mounted */
  329                         vput(dp);
  330                         PNBUF_PUT(cnp->cn_pnbuf);
  331                         return (ENOENT);
  332                 }
  333                 cnp->cn_nameptr = cnp->cn_pnbuf;
  334                 ndp->ni_startdir = dp;
  335                 error = lookup(ndp);
  336                 if (error != 0) {
  337                         if (ndp->ni_dvp) {
  338                                 vput(ndp->ni_dvp);
  339                         }
  340                         if (ndp->ni_erootdir != NULL) {
  341                                 /* Retry the whole thing from the normal root */
  342                                 cnp->cn_flags &= ~TRYEMULROOT;
  343                                 goto emul_retry;
  344                         }
  345                         PNBUF_PUT(cnp->cn_pnbuf);
  346                         return (error);
  347                 }
  348 
  349                 /*
  350                  * Check for symbolic link
  351                  */
  352                 if ((cnp->cn_flags & ISSYMLINK) == 0) {
  353                         if ((cnp->cn_flags & LOCKPARENT) == 0 && ndp->ni_dvp) {
  354                                 if (ndp->ni_dvp == ndp->ni_vp) {
  355                                         vrele(ndp->ni_dvp);
  356                                 } else {
  357                                         vput(ndp->ni_dvp);
  358                                 }
  359                         }
  360                         if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0)
  361                                 PNBUF_PUT(cnp->cn_pnbuf);
  362                         else
  363                                 cnp->cn_flags |= HASBUF;
  364                         return (0);
  365                 }
  366 
  367                 if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
  368                         error = ELOOP;
  369                         break;
  370                 }
  371                 if (ndp->ni_vp->v_mount->mnt_flag & MNT_SYMPERM) {
  372                         error = VOP_ACCESS(ndp->ni_vp, VEXEC, cnp->cn_cred);
  373                         if (error != 0)
  374                                 break;
  375                 }
  376                 if (ndp->ni_pathlen > 1)
  377                         cp = PNBUF_GET();
  378                 else
  379                         cp = cnp->cn_pnbuf;
  380                 aiov.iov_base = cp;
  381                 aiov.iov_len = MAXPATHLEN;
  382                 auio.uio_iov = &aiov;
  383                 auio.uio_iovcnt = 1;
  384                 auio.uio_offset = 0;
  385                 auio.uio_rw = UIO_READ;
  386                 auio.uio_resid = MAXPATHLEN;
  387                 UIO_SETUP_SYSSPACE(&auio);
  388                 error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
  389                 if (error) {
  390 badlink:
  391                         if (ndp->ni_pathlen > 1)
  392                                 PNBUF_PUT(cp);
  393                         break;
  394                 }
  395                 linklen = MAXPATHLEN - auio.uio_resid;
  396                 if (linklen == 0) {
  397                         error = ENOENT;
  398                         goto badlink;
  399                 }
  400 
  401                 /*
  402                  * Do symlink substitution, if appropriate, and
  403                  * check length for potential overflow.
  404                  */
  405                 if ((vfs_magiclinks &&
  406                      symlink_magic(l->l_proc, cp, &linklen)) ||
  407                     (linklen + ndp->ni_pathlen >= MAXPATHLEN)) {
  408                         error = ENAMETOOLONG;
  409                         goto badlink;
  410                 }
  411                 if (ndp->ni_pathlen > 1) {
  412                         memcpy(cp + linklen, ndp->ni_next, ndp->ni_pathlen);
  413                         PNBUF_PUT(cnp->cn_pnbuf);
  414                         cnp->cn_pnbuf = cp;
  415                 } else
  416                         cnp->cn_pnbuf[linklen] = '\0';
  417                 ndp->ni_pathlen += linklen;
  418                 vput(ndp->ni_vp);
  419                 dp = ndp->ni_dvp;
  420 
  421                 /*
  422                  * Check if root directory should replace current directory.
  423                  */
  424                 if (cnp->cn_pnbuf[0] == '/') {
  425                         vput(dp);
  426                         /* Keep absolute symbolic links inside emulation root */
  427                         dp = ndp->ni_erootdir;
  428                         if (dp == NULL || (cnp->cn_pnbuf[1] == '.' 
  429                             && cnp->cn_pnbuf[2] == '.'
  430                             && cnp->cn_pnbuf[3] == '/')) {
  431                                 ndp->ni_erootdir = NULL;
  432                                 dp = ndp->ni_rootdir;
  433                         }
  434                         VREF(dp);
  435                         vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
  436                 }
  437         }
  438         /* Failed to process a symbolic link */
  439         KASSERT(ndp->ni_dvp != ndp->ni_vp);
  440         vput(ndp->ni_dvp);
  441         vput(ndp->ni_vp);
  442         ndp->ni_vp = NULL;
  443         PNBUF_PUT(cnp->cn_pnbuf);
  444         return (error);
  445 }
  446 
  447 /*
  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++)
  466                         hash = hash * 33 + *(const uint8_t *)name;
  467         } else {
  468                 for (; *name != '\0' && *name != '/'; name++)
  469                         hash = hash * 33 + *(const uint8_t *)name;
  470                 *ep = name;
  471         }
  472         return (hash + (hash >> 5));
  473 }
  474 
  475 /*
  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
  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 ".".
  495  *
  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
  503  *          directory vnode returned in ni_dvp, locked.
  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  */
  511 int
  512 lookup(struct nameidata *ndp)
  513 {
  514         const char *cp;                 /* pointer into pathname argument */
  515         struct vnode *dp = 0;           /* the directory we are searching */
  516         struct vnode *tdp;              /* saved dp */
  517         struct mount *mp;               /* mount table entry */
  518         int docache;                    /* == 0 do not cache last component */
  519         int rdonly;                     /* lookup read-only flag bit */
  520         int error = 0;
  521         int slashes;
  522         struct componentname *cnp = &ndp->ni_cnd;
  523         struct lwp *l = curlwp;
  524 
  525         /*
  526          * Setup: break out flag bits into variables.
  527          */
  528         docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE;
  529         if (cnp->cn_nameiop == DELETE)
  530                 docache = 0;
  531         rdonly = cnp->cn_flags & RDONLY;
  532         ndp->ni_dvp = NULL;
  533         cnp->cn_flags &= ~ISSYMLINK;
  534         dp = ndp->ni_startdir;
  535         ndp->ni_startdir = NULLVP;
  536 
  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;
  551                         vput(dp);
  552                         goto bad;
  553                 }
  554 
  555                 /*
  556                  * If we've exhausted the path name, then just return the
  557                  * current node.
  558                  */
  559                 if (cnp->cn_nameptr[0] == '\0') {
  560                         ndp->ni_vp = dp;
  561                         cnp->cn_flags |= ISLASTCN;
  562                         goto terminal;
  563                 }
  564         }
  565 
  566 dirloop:
  567         /*
  568          * Search a new directory.
  569          *
  570          * The cn_hash value is for use by vfs_cache.
  571          * The last component of the filename is left accessible via
  572          * cnp->cn_nameptr for callers that need the name. Callers needing
  573          * the name set the SAVENAME flag. When done, they assume
  574          * responsibility for freeing the pathname buffer.
  575          *
  576          * At this point, our only vnode state is that "dp" is held and locked.
  577          */
  578         cnp->cn_consume = 0;
  579         cp = NULL;
  580         cnp->cn_hash = namei_hash(cnp->cn_nameptr, &cp);
  581         cnp->cn_namelen = cp - cnp->cn_nameptr;
  582         if (cnp->cn_namelen > NAME_MAX) {
  583                 vput(dp);
  584                 error = ENAMETOOLONG;
  585                 ndp->ni_dvp = NULL;
  586                 goto bad;
  587         }
  588 #ifdef NAMEI_DIAGNOSTIC
  589         { char c = *cp;
  590         *(char *)cp = '\0';
  591         printf("{%s}: ", cnp->cn_nameptr);
  592         *(char *)cp = c; }
  593 #endif /* NAMEI_DIAGNOSTIC */
  594         ndp->ni_pathlen -= cnp->cn_namelen;
  595         ndp->ni_next = cp;
  596         /*
  597          * If this component is followed by a slash, then move the pointer to
  598          * the next component forward, and remember that this component must be
  599          * a directory.
  600          */
  601         if (*cp == '/') {
  602                 do {
  603                         cp++;
  604                 } while (*cp == '/');
  605                 slashes = cp - ndp->ni_next;
  606                 ndp->ni_pathlen -= slashes;
  607                 ndp->ni_next = cp;
  608                 cnp->cn_flags |= REQUIREDIR;
  609         } else {
  610                 slashes = 0;
  611                 cnp->cn_flags &= ~REQUIREDIR;
  612         }
  613         /*
  614          * We do special processing on the last component, whether or not it's
  615          * a directory.  Cache all intervening lookups, but not the final one.
  616          */
  617         if (*cp == '\0') {
  618                 if (docache)
  619                         cnp->cn_flags |= MAKEENTRY;
  620                 else
  621                         cnp->cn_flags &= ~MAKEENTRY;
  622                 cnp->cn_flags |= ISLASTCN;
  623         } else {
  624                 cnp->cn_flags |= MAKEENTRY;
  625                 cnp->cn_flags &= ~ISLASTCN;
  626         }
  627         if (cnp->cn_namelen == 2 &&
  628             cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.')
  629                 cnp->cn_flags |= ISDOTDOT;
  630         else
  631                 cnp->cn_flags &= ~ISDOTDOT;
  632 
  633         /*
  634          * Handle "..": two special cases.
  635          * 1. If at root directory (e.g. after chroot)
  636          *    or at absolute root directory
  637          *    then ignore it so can't get out.
  638          * 1a. If at the root of the emulation filesystem go to the real
  639          *    root. So "/../<path>" is always absolute.
  640          * 1b. If we have somehow gotten out of a jail, warn
  641          *    and also ignore it so we can't get farther out.
  642          * 2. If this vnode is the root of a mounted
  643          *    filesystem, then replace it with the
  644          *    vnode which was mounted on so we take the
  645          *    .. in the other file system.
  646          */
  647         if (cnp->cn_flags & ISDOTDOT) {
  648                 struct proc *p = l->l_proc;
  649 
  650                 for (;;) {
  651                         if (dp == ndp->ni_rootdir || dp == rootvnode) {
  652                                 ndp->ni_dvp = dp;
  653                                 ndp->ni_vp = dp;
  654                                 VREF(dp);
  655                                 goto nextname;
  656                         }
  657                         if (ndp->ni_rootdir != rootvnode) {
  658                                 int retval;
  659 
  660                                 VOP_UNLOCK(dp, 0);
  661                                 retval = vn_isunder(dp, ndp->ni_rootdir, l);
  662                                 vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
  663                                 if (!retval) {
  664                                     /* Oops! We got out of jail! */
  665                                     log(LOG_WARNING,
  666                                         "chrooted pid %d uid %d (%s) "
  667                                         "detected outside of its chroot\n",
  668                                         p->p_pid, kauth_cred_geteuid(l->l_cred),
  669                                         p->p_comm);
  670                                     /* Put us at the jail root. */
  671                                     vput(dp);
  672                                     dp = ndp->ni_rootdir;
  673                                     ndp->ni_dvp = dp;
  674                                     ndp->ni_vp = dp;
  675                                     VREF(dp);
  676                                     VREF(dp);
  677                                     vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
  678                                     goto nextname;
  679                                 }
  680                         }
  681                         if ((dp->v_vflag & VV_ROOT) == 0 ||
  682                             (cnp->cn_flags & NOCROSSMOUNT))
  683                                 break;
  684                         tdp = dp;
  685                         dp = dp->v_mount->mnt_vnodecovered;
  686                         vput(tdp);
  687                         VREF(dp);
  688                         vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
  689                 }
  690         }
  691 
  692         /*
  693          * We now have a segment name to search for, and a directory to search.
  694          * Again, our only vnode state is that "dp" is held and locked.
  695          */
  696 unionlookup:
  697         ndp->ni_dvp = dp;
  698         ndp->ni_vp = NULL;
  699         error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp);
  700         if (error != 0) {
  701 #ifdef DIAGNOSTIC
  702                 if (ndp->ni_vp != NULL)
  703                         panic("leaf `%s' should be empty", cnp->cn_nameptr);
  704 #endif /* DIAGNOSTIC */
  705 #ifdef NAMEI_DIAGNOSTIC
  706                 printf("not found\n");
  707 #endif /* NAMEI_DIAGNOSTIC */
  708                 if ((error == ENOENT) &&
  709                     (dp->v_vflag & VV_ROOT) &&
  710                     (dp->v_mount->mnt_flag & MNT_UNION)) {
  711                         tdp = dp;
  712                         dp = dp->v_mount->mnt_vnodecovered;
  713                         vput(tdp);
  714                         VREF(dp);
  715                         vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
  716                         goto unionlookup;
  717                 }
  718 
  719                 if (error != EJUSTRETURN)
  720                         goto bad;
  721 
  722                 /*
  723                  * If this was not the last component, or there were trailing
  724                  * slashes, and we are not going to create a directory,
  725                  * then the name must exist.
  726                  */
  727                 if ((cnp->cn_flags & (REQUIREDIR | CREATEDIR)) == REQUIREDIR) {
  728                         error = ENOENT;
  729                         goto bad;
  730                 }
  731 
  732                 /*
  733                  * If creating and at end of pathname, then can consider
  734                  * allowing file to be created.
  735                  */
  736                 if (rdonly) {
  737                         error = EROFS;
  738                         goto bad;
  739                 }
  740 
  741                 /*
  742                  * We return with ni_vp NULL to indicate that the entry
  743                  * doesn't currently exist, leaving a pointer to the
  744                  * (possibly locked) directory vnode in ndp->ni_dvp.
  745                  */
  746                 if (cnp->cn_flags & SAVESTART) {
  747                         ndp->ni_startdir = ndp->ni_dvp;
  748                         VREF(ndp->ni_startdir);
  749                 }
  750                 return (0);
  751         }
  752 #ifdef NAMEI_DIAGNOSTIC
  753         printf("found\n");
  754 #endif /* NAMEI_DIAGNOSTIC */
  755 
  756         /*
  757          * Take into account any additional components consumed by the
  758          * underlying filesystem.  This will include any trailing slashes after
  759          * the last component consumed.
  760          */
  761         if (cnp->cn_consume > 0) {
  762                 ndp->ni_pathlen -= cnp->cn_consume - slashes;
  763                 ndp->ni_next += cnp->cn_consume - slashes;
  764                 cnp->cn_consume = 0;
  765                 if (ndp->ni_next[0] == '\0')
  766                         cnp->cn_flags |= ISLASTCN;
  767         }
  768 
  769         dp = ndp->ni_vp;
  770 
  771         /*
  772          * "dp" and "ndp->ni_dvp" are both locked and held,
  773          * and may be the same vnode.
  774          */
  775 
  776         /*
  777          * Check to see if the vnode has been mounted on;
  778          * if so find the root of the mounted file system.
  779          */
  780         while (dp->v_type == VDIR && (mp = dp->v_mountedhere) &&
  781                (cnp->cn_flags & NOCROSSMOUNT) == 0) {
  782                 error = vfs_busy(mp, NULL);
  783                 if (error != 0) {
  784                         vput(dp);
  785                         goto bad;
  786                 }
  787                 KASSERT(ndp->ni_dvp != dp);
  788                 VOP_UNLOCK(ndp->ni_dvp, 0);
  789                 vput(dp);
  790                 error = VFS_ROOT(mp, &tdp);
  791                 vfs_unbusy(mp, false, NULL);
  792                 if (error) {
  793                         vn_lock(ndp->ni_dvp, LK_EXCLUSIVE | LK_RETRY);
  794                         goto bad;
  795                 }
  796                 VOP_UNLOCK(tdp, 0);
  797                 ndp->ni_vp = dp = tdp;
  798                 vn_lock(ndp->ni_dvp, LK_EXCLUSIVE | LK_RETRY);
  799                 vn_lock(ndp->ni_vp, LK_EXCLUSIVE | LK_RETRY);
  800         }
  801 
  802         /*
  803          * Check for symbolic link.  Back up over any slashes that we skipped,
  804          * as we will need them again.
  805          */
  806         if ((dp->v_type == VLNK) && (cnp->cn_flags & (FOLLOW|REQUIREDIR))) {
  807                 ndp->ni_pathlen += slashes;
  808                 ndp->ni_next -= slashes;
  809                 cnp->cn_flags |= ISSYMLINK;
  810                 return (0);
  811         }
  812 
  813         /*
  814          * Check for directory, if the component was followed by a series of
  815          * slashes.
  816          */
  817         if ((dp->v_type != VDIR) && (cnp->cn_flags & REQUIREDIR)) {
  818                 error = ENOTDIR;
  819                 KASSERT(dp != ndp->ni_dvp);
  820                 vput(dp);
  821                 goto bad;
  822         }
  823 
  824 nextname:
  825 
  826         /*
  827          * Not a symbolic link.  If this was not the last component, then
  828          * continue at the next component, else return.
  829          */
  830         if (!(cnp->cn_flags & ISLASTCN)) {
  831                 cnp->cn_nameptr = ndp->ni_next;
  832                 if (ndp->ni_dvp == dp) {
  833                         vrele(ndp->ni_dvp);
  834                 } else {
  835                         vput(ndp->ni_dvp);
  836                 }
  837                 goto dirloop;
  838         }
  839 
  840 terminal:
  841         if (dp == ndp->ni_erootdir) {
  842                 /*
  843                  * We are about to return the emulation root.
  844                  * This isn't a good idea because code might repeatedly
  845                  * lookup ".." until the file matches that returned
  846                  * for "/" and loop forever.
  847                  * So convert it to the real root.
  848                  */
  849                 if (ndp->ni_dvp == dp)
  850                         vrele(dp);
  851                 else
  852                         if (ndp->ni_dvp != NULL)
  853                                 vput(ndp->ni_dvp);
  854                 ndp->ni_dvp = NULL;
  855                 vput(dp);
  856                 dp = ndp->ni_rootdir;
  857                 VREF(dp);
  858                 vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
  859                 ndp->ni_vp = dp;
  860         }
  861 
  862         /*
  863          * If the caller requested the parent node (i.e.
  864          * it's a CREATE, DELETE, or RENAME), and we don't have one
  865          * (because this is the root directory), then we must fail.
  866          */
  867         if (ndp->ni_dvp == NULL && cnp->cn_nameiop != LOOKUP) {
  868                 switch (cnp->cn_nameiop) {
  869                 case CREATE:
  870                         error = EEXIST;
  871                         break;
  872                 case DELETE:
  873                 case RENAME:
  874                         error = EBUSY;
  875                         break;
  876                 default:
  877                         KASSERT(0);
  878                 }
  879                 vput(dp);
  880                 goto bad;
  881         }
  882 
  883         /*
  884          * Disallow directory write attempts on read-only lookups.
  885          * Prefers EEXIST over EROFS for the CREATE case.
  886          */
  887         if (rdonly &&
  888             (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
  889                 error = EROFS;
  890                 if (dp != ndp->ni_dvp) {
  891                         vput(dp);
  892                 }
  893                 goto bad;
  894         }
  895         if (ndp->ni_dvp != NULL) {
  896                 if (cnp->cn_flags & SAVESTART) {
  897                         ndp->ni_startdir = ndp->ni_dvp;
  898                         VREF(ndp->ni_startdir);
  899                 }
  900         }
  901         if ((cnp->cn_flags & LOCKLEAF) == 0) {
  902                 VOP_UNLOCK(dp, 0);
  903         }
  904         return (0);
  905 
  906 bad:
  907         ndp->ni_vp = NULL;
  908         return (error);
  909 }
  910 
  911 /*
  912  * Reacquire a path name component.
  913  * dvp is locked on entry and exit.
  914  * *vpp is locked on exit unless it's NULL.
  915  */
  916 int
  917 relookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp)
  918 {
  919         int rdonly;                     /* lookup read-only flag bit */
  920         int error = 0;
  921 #ifdef DEBUG
  922         uint32_t newhash;               /* DEBUG: check name hash */
  923         const char *cp;                 /* DEBUG: check name ptr/len */
  924 #endif /* DEBUG */
  925 
  926         /*
  927          * Setup: break out flag bits into variables.
  928          */
  929         rdonly = cnp->cn_flags & RDONLY;
  930         cnp->cn_flags &= ~ISSYMLINK;
  931 
  932         /*
  933          * Search a new directory.
  934          *
  935          * The cn_hash value is for use by vfs_cache.
  936          * The last component of the filename is left accessible via
  937          * cnp->cn_nameptr for callers that need the name. Callers needing
  938          * the name set the SAVENAME flag. When done, they assume
  939          * responsibility for freeing the pathname buffer.
  940          */
  941 #ifdef DEBUG
  942         cp = NULL;
  943         newhash = namei_hash(cnp->cn_nameptr, &cp);
  944         if ((uint32_t)newhash != (uint32_t)cnp->cn_hash)
  945                 panic("relookup: bad hash");
  946         if (cnp->cn_namelen != cp - cnp->cn_nameptr)
  947                 panic("relookup: bad len");
  948         while (*cp == '/')
  949                 cp++;
  950         if (*cp != 0)
  951                 panic("relookup: not last component");
  952 #endif /* DEBUG */
  953 
  954         /*
  955          * Check for degenerate name (e.g. / or "")
  956          * which is a way of talking about a directory,
  957          * e.g. like "/." or ".".
  958          */
  959         if (cnp->cn_nameptr[0] == '\0')
  960                 panic("relookup: null name");
  961 
  962         if (cnp->cn_flags & ISDOTDOT)
  963                 panic("relookup: lookup on dot-dot");
  964 
  965         /*
  966          * We now have a segment name to search for, and a directory to search.
  967          */
  968         if ((error = VOP_LOOKUP(dvp, vpp, cnp)) != 0) {
  969 #ifdef DIAGNOSTIC
  970                 if (*vpp != NULL)
  971                         panic("leaf `%s' should be empty", cnp->cn_nameptr);
  972 #endif
  973                 if (error != EJUSTRETURN)
  974                         goto bad;
  975         }
  976 
  977 #ifdef DIAGNOSTIC
  978         /*
  979          * Check for symbolic link
  980          */
  981         if (*vpp && (*vpp)->v_type == VLNK && (cnp->cn_flags & FOLLOW))
  982                 panic("relookup: symlink found");
  983 #endif
  984 
  985         /*
  986          * Check for read-only lookups.
  987          */
  988         if (rdonly && cnp->cn_nameiop != LOOKUP) {
  989                 error = EROFS;
  990                 if (*vpp) {
  991                         vput(*vpp);
  992                 }
  993                 goto bad;
  994         }
  995         if (cnp->cn_flags & SAVESTART)
  996                 VREF(dvp);
  997         return (0);
  998 
  999 bad:
 1000         *vpp = NULL;
 1001         return (error);
 1002 }

Cache object: 2bb8a9c971da7a0e838e238e4b5a17e0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.