1 /* $OpenBSD: vfs_lookup.c,v 1.63 2016/04/29 14:40:36 beck Exp $ */ 2 /* $NetBSD: vfs_lookup.c,v 1.17 1996/02/09 19:00:59 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1982, 1986, 1989, 1993 6 * The Regents of the University of California. All rights reserved. 7 * (c) UNIX System Laboratories, Inc. 8 * All or some portions of this file are derived from material licensed 9 * to the University of California by American Telephone and Telegraph 10 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 11 * the permission of UNIX System Laboratories, Inc. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * @(#)vfs_lookup.c 8.6 (Berkeley) 11/21/94 38 */ 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/syslimits.h> 43 #include <sys/time.h> 44 #include <sys/namei.h> 45 #include <sys/vnode.h> 46 #include <sys/lock.h> 47 #include <sys/mount.h> 48 #include <sys/errno.h> 49 #include <sys/pool.h> 50 #include <sys/filedesc.h> 51 #include <sys/proc.h> 52 #include <sys/pledge.h> 53 #include <sys/file.h> 54 #include <sys/fcntl.h> 55 #include <sys/types.h> 56 #include <sys/malloc.h> 57 58 #ifdef KTRACE 59 #include <sys/ktrace.h> 60 #endif 61 62 63 void 64 push_component(struct nameidata *ndp, char *cp, size_t cplen) 65 { 66 KASSERT(cplen < MAXPATHLEN); 67 if (ndp->ni_p_size - ndp->ni_p_length <= cplen) { 68 char *tmp = malloc(ndp->ni_p_size + MAXPATHLEN, M_TEMP, M_WAITOK); 69 memcpy(tmp, ndp->ni_p_path, ndp->ni_p_length); 70 ndp->ni_p_next = tmp + (ndp->ni_p_next - ndp->ni_p_path); 71 ndp->ni_p_prev = tmp + (ndp->ni_p_prev - ndp->ni_p_path); 72 free(ndp->ni_p_path, M_TEMP, ndp->ni_p_size); 73 ndp->ni_p_path = tmp; 74 ndp->ni_p_size += MAXPATHLEN; 75 } 76 memcpy(ndp->ni_p_next, cp, cplen); 77 ndp->ni_p_prev = ndp->ni_p_next; 78 ndp->ni_p_next += cplen; 79 ndp->ni_p_length += cplen; 80 *ndp->ni_p_next = '\0'; 81 #ifdef NAMEI_DIAGNOSTIC_PLEDGE 82 printf("push: ndp->ni_p_path = %s\n", ndp->ni_p_path); 83 #endif 84 } 85 86 void 87 pop_symlink(struct nameidata *ndp) 88 { 89 KASSERT(ndp->ni_p_next != ndp->ni_p_prev); 90 ndp->ni_p_length = ndp->ni_p_prev - ndp->ni_p_path; 91 ndp->ni_p_next = ndp->ni_p_prev; 92 *ndp->ni_p_next = '\0'; 93 #ifdef NAMEI_DIAGNOSTIC_PLEDGE 94 printf("pop: ndp->ni_p_path = %s\n", ndp->ni_p_path); 95 #endif 96 } 97 98 void 99 ndinitat(struct nameidata *ndp, u_long op, u_long flags, 100 enum uio_seg segflg, int dirfd, const char *namep, struct proc *p) 101 { 102 memset(ndp, 0, sizeof(*ndp)); 103 (ndp)->ni_cnd.cn_nameiop = op; 104 (ndp)->ni_cnd.cn_flags = flags; 105 (ndp)->ni_segflg = segflg; 106 (ndp)->ni_dirfd = dirfd; 107 (ndp)->ni_dirp = namep; 108 (ndp)->ni_cnd.cn_proc = p; 109 } 110 111 /* 112 * Convert a pathname into a pointer to a vnode. 113 * 114 * The FOLLOW flag is set when symbolic links are to be followed 115 * when they occur at the end of the name translation process. 116 * Symbolic links are always followed for all other pathname 117 * components other than the last. 118 * 119 * If the LOCKLEAF flag is set, a locked vnode is returned. 120 * 121 * The segflg defines whether the name is to be copied from user 122 * space or kernel space. 123 * 124 * Overall outline of namei: 125 * 126 * copy in name 127 * get starting directory 128 * while (!done && !error) { 129 * call lookup to search path. 130 * if symbolic link, massage name in buffer and continue 131 * } 132 */ 133 int 134 namei(struct nameidata *ndp) 135 { 136 struct filedesc *fdp; /* pointer to file descriptor state */ 137 char *cp; /* pointer into pathname argument */ 138 struct vnode *dp; /* the directory we are searching */ 139 struct iovec aiov; /* uio for reading symbolic links */ 140 struct uio auio; 141 int error, linklen; 142 struct componentname *cnp = &ndp->ni_cnd; 143 struct proc *p = cnp->cn_proc; 144 145 /* 146 * Should be 0, if not someone didn't init ndp with NDINIT, 147 * go find and murder the offender messily. 148 */ 149 KASSERT (ndp->ni_p_path == NULL && ndp->ni_p_size == 0); 150 151 ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_proc->p_ucred; 152 #ifdef DIAGNOSTIC 153 if (!cnp->cn_cred || !cnp->cn_proc) 154 panic ("namei: bad cred/proc"); 155 if (cnp->cn_nameiop & (~OPMASK)) 156 panic ("namei: nameiop contaminated with flags"); 157 if (cnp->cn_flags & OPMASK) 158 panic ("namei: flags contaminated with nameiops"); 159 #endif 160 fdp = cnp->cn_proc->p_fd; 161 162 /* 163 * Get a buffer for the name to be translated, and copy the 164 * name into the buffer. 165 */ 166 if ((cnp->cn_flags & HASBUF) == 0) 167 cnp->cn_pnbuf = pool_get(&namei_pool, PR_WAITOK); 168 if (ndp->ni_segflg == UIO_SYSSPACE) 169 error = copystr(ndp->ni_dirp, cnp->cn_pnbuf, 170 MAXPATHLEN, &ndp->ni_pathlen); 171 else 172 error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf, 173 MAXPATHLEN, &ndp->ni_pathlen); 174 175 /* 176 * Fail on null pathnames 177 */ 178 if (error == 0 && ndp->ni_pathlen == 1) 179 error = ENOENT; 180 181 if (error) { 182 fail: 183 pool_put(&namei_pool, cnp->cn_pnbuf); 184 ndp->ni_vp = NULL; 185 return (error); 186 } 187 188 #ifdef KTRACE 189 if (KTRPOINT(cnp->cn_proc, KTR_NAMEI)) 190 ktrnamei(cnp->cn_proc, cnp->cn_pnbuf); 191 #endif 192 193 /* 194 * Strip trailing slashes, as requested 195 */ 196 if (cnp->cn_flags & STRIPSLASHES) { 197 char *end = cnp->cn_pnbuf + ndp->ni_pathlen - 2; 198 199 cp = end; 200 while (cp >= cnp->cn_pnbuf && (*cp == '/')) 201 cp--; 202 203 /* Still some remaining characters in the buffer */ 204 if (cp >= cnp->cn_pnbuf) { 205 ndp->ni_pathlen -= (end - cp); 206 *(cp + 1) = '\0'; 207 } 208 } 209 210 ndp->ni_loopcnt = 0; 211 212 /* 213 * Get starting point for the translation. 214 */ 215 if ((ndp->ni_rootdir = fdp->fd_rdir) == NULL) 216 ndp->ni_rootdir = rootvnode; 217 218 error = pledge_namei(p, ndp, cnp->cn_pnbuf); 219 if (error) 220 goto fail; 221 222 /* 223 * Decide if we need to call pledge_namei_wlpath after namei lookup, if 224 * so give namei a place to store a path for it to look at. 225 */ 226 if (!ISSET(p->p_p->ps_flags, PS_COREDUMP) && 227 ISSET(p->p_p->ps_flags, PS_PLEDGE) && p->p_p->ps_pledgepaths) { 228 ndp->ni_p_path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 229 ndp->ni_p_next = ndp->ni_p_prev = ndp->ni_p_path; 230 ndp->ni_p_size = MAXPATHLEN; 231 ndp->ni_p_length = 0; 232 } else { 233 ndp->ni_p_path = NULL; 234 ndp->ni_p_size = 0; 235 } 236 237 /* 238 * Check if starting from root directory or current directory. 239 */ 240 if (cnp->cn_pnbuf[0] == '/') { 241 dp = ndp->ni_rootdir; 242 vref(dp); 243 if (ndp->ni_p_path != NULL) { 244 *ndp->ni_p_path = '/'; 245 ndp->ni_p_next++; 246 *ndp->ni_p_next = '\0'; 247 ndp->ni_p_length = 1; 248 } 249 } else if (ndp->ni_dirfd == AT_FDCWD) { 250 dp = fdp->fd_cdir; 251 vref(dp); 252 } else { 253 struct file *fp = fd_getfile(fdp, ndp->ni_dirfd); 254 if (fp == NULL) { 255 free(ndp->ni_p_path, M_TEMP, ndp->ni_p_size); 256 pool_put(&namei_pool, cnp->cn_pnbuf); 257 return (EBADF); 258 } 259 dp = (struct vnode *)fp->f_data; 260 if (fp->f_type != DTYPE_VNODE || dp->v_type != VDIR) { 261 free(ndp->ni_p_path, M_TEMP, ndp->ni_p_size); 262 pool_put(&namei_pool, cnp->cn_pnbuf); 263 return (ENOTDIR); 264 } 265 vref(dp); 266 } 267 for (;;) { 268 if (!dp->v_mount) { 269 /* Give up if the directory is no longer mounted */ 270 free(ndp->ni_p_path, M_TEMP, ndp->ni_p_size); 271 pool_put(&namei_pool, cnp->cn_pnbuf); 272 return (ENOENT); 273 } 274 cnp->cn_nameptr = cnp->cn_pnbuf; 275 ndp->ni_startdir = dp; 276 if ((error = vfs_lookup(ndp)) != 0) { 277 free(ndp->ni_p_path, M_TEMP, ndp->ni_p_size); 278 pool_put(&namei_pool, cnp->cn_pnbuf); 279 return (error); 280 } 281 /* 282 * If not a symbolic link, return search result. 283 */ 284 if ((cnp->cn_flags & ISSYMLINK) == 0) { 285 error = pledge_namei_wlpath(p, ndp); 286 if (error) { 287 #ifdef NAMEI_DIAGNOSTIC_PLEDGE 288 printf("pledge_namei error %d for path %s\n", error, ndp->ni_p_path); 289 #endif 290 free(ndp->ni_p_path, M_TEMP, ndp->ni_p_size); 291 pool_put(&namei_pool, cnp->cn_pnbuf); 292 if (ndp->ni_vp) 293 vput(ndp->ni_vp); 294 ndp->ni_vp = NULL; 295 return(error); 296 } 297 free(ndp->ni_p_path, M_TEMP, ndp->ni_p_size); 298 if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0) 299 pool_put(&namei_pool, cnp->cn_pnbuf); 300 else 301 cnp->cn_flags |= HASBUF; 302 return(0); 303 } 304 if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN)) 305 VOP_UNLOCK(ndp->ni_dvp, p); 306 if (ndp->ni_loopcnt++ >= SYMLOOP_MAX) { 307 error = ELOOP; 308 break; 309 } 310 if (ndp->ni_pathlen > 1) 311 cp = pool_get(&namei_pool, PR_WAITOK); 312 else 313 cp = cnp->cn_pnbuf; 314 aiov.iov_base = cp; 315 aiov.iov_len = MAXPATHLEN; 316 auio.uio_iov = &aiov; 317 auio.uio_iovcnt = 1; 318 auio.uio_offset = 0; 319 auio.uio_rw = UIO_READ; 320 auio.uio_segflg = UIO_SYSSPACE; 321 auio.uio_procp = cnp->cn_proc; 322 auio.uio_resid = MAXPATHLEN; 323 error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred); 324 if (error) { 325 badlink: 326 if (ndp->ni_pathlen > 1) 327 pool_put(&namei_pool, cp); 328 break; 329 } 330 linklen = MAXPATHLEN - auio.uio_resid; 331 if (linklen == 0) { 332 error = ENOENT; 333 goto badlink; 334 } 335 if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { 336 error = ENAMETOOLONG; 337 goto badlink; 338 } 339 if (ndp->ni_pathlen > 1) { 340 memcpy(cp + linklen, ndp->ni_next, ndp->ni_pathlen); 341 pool_put(&namei_pool, cnp->cn_pnbuf); 342 cnp->cn_pnbuf = cp; 343 } else 344 cnp->cn_pnbuf[linklen] = '\0'; 345 ndp->ni_pathlen += linklen; 346 vput(ndp->ni_vp); 347 dp = ndp->ni_dvp; 348 /* 349 * Check if root directory should replace current directory. 350 */ 351 if (cnp->cn_pnbuf[0] == '/') { 352 vrele(dp); 353 dp = ndp->ni_rootdir; 354 vref(dp); 355 if (ndp->ni_p_path != NULL) { 356 ndp->ni_p_next = ndp->ni_p_prev = ndp->ni_p_path; 357 *ndp->ni_p_path = '/'; 358 ndp->ni_p_next++; 359 *ndp->ni_p_next = '\0'; 360 ndp->ni_p_length = 1; 361 } 362 } 363 } 364 pool_put(&namei_pool, cnp->cn_pnbuf); 365 free(ndp->ni_p_path, M_TEMP, ndp->ni_p_size); 366 vrele(ndp->ni_dvp); 367 vput(ndp->ni_vp); 368 ndp->ni_vp = NULL; 369 return (error); 370 } 371 372 /* 373 * Search a pathname. 374 * This is a very central and rather complicated routine. 375 * 376 * The pathname is pointed to by ni_cnd.cn_nameptr and is of length 377 * ni_pathlen. The starting directory is taken from ni_startdir. The 378 * pathname is descended until done, or a symbolic link is encountered. 379 * If the path is completed the flag ISLASTCN is set in ni_cnd.cn_flags. 380 * If a symbolic link need interpretation is encountered, the flag ISSYMLINK 381 * is set in ni_cnd.cn_flags. 382 * 383 * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on 384 * whether the name is to be looked up, created, renamed, or deleted. 385 * When CREATE, RENAME, or DELETE is specified, information usable in 386 * creating, renaming, or deleting a directory entry may be calculated. 387 * If flag has LOCKPARENT or'ed into it, the parent directory is returned 388 * locked. If flag has WANTPARENT or'ed into it, the parent directory is 389 * returned unlocked. Otherwise the parent directory is not returned. If 390 * the target of the pathname exists and LOCKLEAF is or'ed into the flag 391 * the target is returned locked, otherwise it is returned unlocked. 392 * When creating or renaming and LOCKPARENT is specified, the target may not 393 * be ".". When deleting and LOCKPARENT is specified, the target may be ".". 394 * 395 * Overall outline of lookup: 396 * 397 * dirloop: 398 * identify next component of name at ndp->ni_ptr 399 * handle degenerate case where name is null string 400 * if .. and crossing mount points and on mounted filesys, find parent 401 * call VOP_LOOKUP routine for next component name 402 * directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set 403 * component vnode returned in ni_vp (if it exists), locked. 404 * if result vnode is mounted on and crossing mount points, 405 * find mounted on vnode 406 * if more components of name, do next level at dirloop 407 * return the answer in ni_vp, locked if LOCKLEAF set 408 * if LOCKPARENT set, return locked parent in ni_dvp 409 * if WANTPARENT set, return unlocked parent in ni_dvp 410 */ 411 int 412 vfs_lookup(struct nameidata *ndp) 413 { 414 char *cp; /* pointer into pathname argument */ 415 struct vnode *dp = 0; /* the directory we are searching */ 416 struct vnode *tdp; /* saved dp */ 417 struct mount *mp; /* mount table entry */ 418 int docache; /* == 0 do not cache last component */ 419 int wantparent; /* 1 => wantparent or lockparent flag */ 420 int rdonly; /* lookup read-only flag bit */ 421 int error = 0; 422 int dpunlocked = 0; /* dp has already been unlocked */ 423 int slashes; 424 struct componentname *cnp = &ndp->ni_cnd; 425 struct proc *p = cnp->cn_proc; 426 /* 427 * Setup: break out flag bits into variables. 428 */ 429 wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT); 430 docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE; 431 if (cnp->cn_nameiop == DELETE || 432 (wantparent && cnp->cn_nameiop != CREATE)) 433 docache = 0; 434 rdonly = cnp->cn_flags & RDONLY; 435 ndp->ni_dvp = NULL; 436 cnp->cn_flags &= ~ISSYMLINK; 437 dp = ndp->ni_startdir; 438 ndp->ni_startdir = NULLVP; 439 vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p); 440 441 /* 442 * If we have a leading string of slashes, remove them, and just make 443 * sure the current node is a directory. 444 */ 445 cp = cnp->cn_nameptr; 446 if (*cp == '/') { 447 do { 448 cp++; 449 } while (*cp == '/'); 450 ndp->ni_pathlen -= cp - cnp->cn_nameptr; 451 cnp->cn_nameptr = cp; 452 453 if (dp->v_type != VDIR) { 454 error = ENOTDIR; 455 goto bad; 456 } 457 458 /* 459 * If we've exhausted the path name, then just return the 460 * current node. If the caller requested the parent node (i.e. 461 * it's a CREATE, DELETE, or RENAME), and we don't have one 462 * (because this is the root directory), then we must fail. 463 */ 464 if (cnp->cn_nameptr[0] == '\0') { 465 if (ndp->ni_dvp == NULL && wantparent) { 466 error = EISDIR; 467 goto bad; 468 } 469 ndp->ni_vp = dp; 470 cnp->cn_flags |= ISLASTCN; 471 goto terminal; 472 } 473 } 474 475 dirloop: 476 /* 477 * Search a new directory. 478 * 479 * The last component of the filename is left accessible via 480 * cnp->cn_nameptr for callers that need the name. Callers needing 481 * the name set the SAVENAME flag. When done, they assume 482 * responsibility for freeing the pathname buffer. 483 */ 484 cnp->cn_consume = 0; 485 486 /* XXX: Figure out the length of the last component. */ 487 cp = cnp->cn_nameptr; 488 while (*cp && (*cp != '/')) 489 cp++; 490 cnp->cn_namelen = cp - cnp->cn_nameptr; 491 if (cnp->cn_namelen > NAME_MAX) { 492 error = ENAMETOOLONG; 493 goto bad; 494 } 495 496 #ifdef NAMEI_DIAGNOSTIC 497 #ifdef NAMEI_DIAGNOSTIC_PLEDGE 498 if (p && p->p_p && p->p_p->ps_pledgepaths) 499 #endif 500 { char c = *cp; 501 *cp = '\0'; 502 printf("{%s}: ", cnp->cn_nameptr); 503 *cp = c; } 504 #endif 505 if (ndp->ni_p_path != NULL) 506 push_component(ndp, cnp->cn_nameptr, cnp->cn_namelen); 507 508 ndp->ni_pathlen -= cnp->cn_namelen; 509 ndp->ni_next = cp; 510 /* 511 * If this component is followed by a slash, then move the pointer to 512 * the next component forward, and remember that this component must be 513 * a directory. 514 */ 515 if (*cp == '/') { 516 do { 517 cp++; 518 } while (*cp == '/'); 519 slashes = cp - ndp->ni_next; 520 ndp->ni_pathlen -= slashes; 521 ndp->ni_next = cp; 522 cnp->cn_flags |= REQUIREDIR; 523 } else { 524 slashes = 0; 525 cnp->cn_flags &= ~REQUIREDIR; 526 } 527 /* 528 * We do special processing on the last component, whether or not it's 529 * a directory. Cache all intervening lookups, but not the final one. 530 */ 531 if (*cp == '\0') { 532 if (docache) 533 cnp->cn_flags |= MAKEENTRY; 534 else 535 cnp->cn_flags &= ~MAKEENTRY; 536 cnp->cn_flags |= ISLASTCN; 537 } else { 538 cnp->cn_flags |= MAKEENTRY; 539 cnp->cn_flags &= ~ISLASTCN; 540 } 541 if (cnp->cn_namelen == 2 && 542 cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.') 543 cnp->cn_flags |= ISDOTDOT; 544 else 545 cnp->cn_flags &= ~ISDOTDOT; 546 547 /* 548 * Handle "..": two special cases. 549 * 1. If at root directory (e.g. after chroot) 550 * or at absolute root directory 551 * then ignore it so can't get out. 552 * 2. If this vnode is the root of a mounted 553 * filesystem, then replace it with the 554 * vnode which was mounted on so we take the 555 * .. in the other file system. 556 */ 557 if (cnp->cn_flags & ISDOTDOT) { 558 for (;;) { 559 if (dp == ndp->ni_rootdir || dp == rootvnode) { 560 ndp->ni_dvp = dp; 561 ndp->ni_vp = dp; 562 vref(dp); 563 goto nextname; 564 } 565 if ((dp->v_flag & VROOT) == 0 || 566 (cnp->cn_flags & NOCROSSMOUNT)) 567 break; 568 tdp = dp; 569 dp = dp->v_mount->mnt_vnodecovered; 570 vput(tdp); 571 vref(dp); 572 vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p); 573 } 574 } 575 576 /* 577 * We now have a segment name to search for, and a directory to search. 578 */ 579 ndp->ni_dvp = dp; 580 ndp->ni_vp = NULL; 581 cnp->cn_flags &= ~PDIRUNLOCK; 582 583 if ((error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) != 0) { 584 #ifdef DIAGNOSTIC 585 if (ndp->ni_vp != NULL) 586 panic("leaf should be empty"); 587 #endif 588 #ifdef NAMEI_DIAGNOSTIC 589 #ifdef NAMEI_DIAGNOSTIC_PLEDGE 590 if (p && p->p_p && p->p_p->ps_pledgepaths) 591 #endif 592 printf("not found\n"); 593 #endif 594 if (error != EJUSTRETURN) 595 goto bad; 596 /* 597 * If this was not the last component, or there were trailing 598 * slashes, then the name must exist. 599 */ 600 if (cnp->cn_flags & REQUIREDIR) { 601 error = ENOENT; 602 goto bad; 603 } 604 /* 605 * If creating and at end of pathname, then can consider 606 * allowing file to be created. 607 */ 608 if (rdonly || (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY)) { 609 error = EROFS; 610 goto bad; 611 } 612 /* 613 * We return with ni_vp NULL to indicate that the entry 614 * doesn't currently exist, leaving a pointer to the 615 * (possibly locked) directory inode in ndp->ni_dvp. 616 */ 617 if (cnp->cn_flags & SAVESTART) { 618 ndp->ni_startdir = ndp->ni_dvp; 619 vref(ndp->ni_startdir); 620 } 621 return (0); 622 } 623 #ifdef NAMEI_DIAGNOSTIC 624 #ifdef NAMEI_DIAGNOSTIC_PLEDGE 625 if (p && p->p_p && p->p_p->ps_pledgepaths) 626 #endif 627 printf("found\n"); 628 #endif 629 630 /* 631 * Take into account any additional components consumed by the 632 * underlying filesystem. This will include any trailing slashes after 633 * the last component consumed. 634 */ 635 if (cnp->cn_consume > 0) { 636 if (cnp->cn_consume >= slashes) { 637 cnp->cn_flags &= ~REQUIREDIR; 638 } 639 640 ndp->ni_pathlen -= cnp->cn_consume - slashes; 641 ndp->ni_next += cnp->cn_consume - slashes; 642 cnp->cn_consume = 0; 643 if (ndp->ni_next[0] == '\0') 644 cnp->cn_flags |= ISLASTCN; 645 } 646 647 dp = ndp->ni_vp; 648 /* 649 * Check to see if the vnode has been mounted on; 650 * if so find the root of the mounted file system. 651 */ 652 while (dp->v_type == VDIR && (mp = dp->v_mountedhere) && 653 (cnp->cn_flags & NOCROSSMOUNT) == 0) { 654 if (vfs_busy(mp, VB_READ|VB_WAIT)) 655 continue; 656 VOP_UNLOCK(dp, p); 657 error = VFS_ROOT(mp, &tdp); 658 vfs_unbusy(mp); 659 if (error) { 660 dpunlocked = 1; 661 goto bad2; 662 } 663 vrele(dp); 664 ndp->ni_vp = dp = tdp; 665 } 666 667 /* 668 * Check for symbolic link. Back up over any slashes that we skipped, 669 * as we will need them again. 670 */ 671 if ((dp->v_type == VLNK) && (cnp->cn_flags & (FOLLOW|REQUIREDIR))) { 672 ndp->ni_pathlen += slashes; 673 ndp->ni_next -= slashes; 674 cnp->cn_flags |= ISSYMLINK; 675 if (ndp->ni_p_path != NULL) 676 pop_symlink(ndp); 677 return (0); 678 } 679 680 /* 681 * Check for directory, if the component was followed by a series of 682 * slashes. 683 */ 684 if ((dp->v_type != VDIR) && (cnp->cn_flags & REQUIREDIR)) { 685 error = ENOTDIR; 686 goto bad2; 687 } 688 689 nextname: 690 /* 691 * Not a symbolic link. If this was not the last component, then 692 * continue at the next component, else return. 693 */ 694 if (!(cnp->cn_flags & ISLASTCN)) { 695 cnp->cn_nameptr = ndp->ni_next; 696 vrele(ndp->ni_dvp); 697 if (ndp->ni_p_path != NULL) 698 push_component(ndp, "/", 1); 699 goto dirloop; 700 } 701 702 terminal: 703 /* 704 * Check for read-only file systems. 705 */ 706 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) { 707 /* 708 * Disallow directory write attempts on read-only 709 * file systems. 710 */ 711 if (rdonly || (dp->v_mount->mnt_flag & MNT_RDONLY) || 712 (wantparent && 713 (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY))) { 714 error = EROFS; 715 goto bad2; 716 } 717 } 718 if (ndp->ni_dvp != NULL) { 719 if (cnp->cn_flags & SAVESTART) { 720 ndp->ni_startdir = ndp->ni_dvp; 721 vref(ndp->ni_startdir); 722 } 723 if (!wantparent) 724 vrele(ndp->ni_dvp); 725 } 726 if ((cnp->cn_flags & LOCKLEAF) == 0) 727 VOP_UNLOCK(dp, p); 728 return (0); 729 730 bad2: 731 if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN) && 732 ((cnp->cn_flags & PDIRUNLOCK) == 0)) 733 VOP_UNLOCK(ndp->ni_dvp, p); 734 vrele(ndp->ni_dvp); 735 bad: 736 if (dpunlocked) 737 vrele(dp); 738 else 739 vput(dp); 740 ndp->ni_vp = NULL; 741 return (error); 742 } 743 744 /* 745 * Reacquire a path name component. 746 */ 747 int 748 vfs_relookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp) 749 { 750 struct proc *p = cnp->cn_proc; 751 struct vnode *dp = 0; /* the directory we are searching */ 752 int wantparent; /* 1 => wantparent or lockparent flag */ 753 int rdonly; /* lookup read-only flag bit */ 754 int error = 0; 755 #ifdef NAMEI_DIAGNOSTIC 756 char *cp; /* DEBUG: check name ptr/len */ 757 #endif 758 759 /* 760 * Setup: break out flag bits into variables. 761 */ 762 wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT); 763 rdonly = cnp->cn_flags & RDONLY; 764 cnp->cn_flags &= ~ISSYMLINK; 765 dp = dvp; 766 vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p); 767 768 /* dirloop: */ 769 /* 770 * Search a new directory. 771 * 772 * The last component of the filename is left accessible via 773 * cnp->cn_nameptr for callers that need the name. Callers needing 774 * the name set the SAVENAME flag. When done, they assume 775 * responsibility for freeing the pathname buffer. 776 */ 777 778 #ifdef NAMEI_DIAGNOSTIC 779 #ifdef NAMEI_DIAGNOSTIC_PLEDGE 780 if (p && p->p_p && p->p_p->ps_pledgepaths) 781 #endif 782 { 783 /* XXX: Figure out the length of the last component. */ 784 cp = cnp->cn_nameptr; 785 while (*cp && (*cp != '/')) { 786 cp++; 787 } 788 if (cnp->cn_namelen != cp - cnp->cn_nameptr) 789 panic("relookup: bad len"); 790 if (*cp != 0) 791 panic("relookup: not last component"); 792 printf("{%s}: ", cnp->cn_nameptr); 793 } 794 #endif 795 796 /* 797 * Check for degenerate name (e.g. / or "") 798 * which is a way of talking about a directory, 799 * e.g. like "/." or ".". 800 */ 801 if (cnp->cn_nameptr[0] == '\0') 802 panic("relookup: null name"); 803 804 if (cnp->cn_flags & ISDOTDOT) 805 panic ("relookup: lookup on dot-dot"); 806 807 /* 808 * We now have a segment name to search for, and a directory to search. 809 */ 810 if ((error = VOP_LOOKUP(dp, vpp, cnp)) != 0) { 811 #ifdef DIAGNOSTIC 812 if (*vpp != NULL) 813 panic("leaf should be empty"); 814 #endif 815 if (error != EJUSTRETURN) 816 goto bad; 817 /* 818 * If creating and at end of pathname, then can consider 819 * allowing file to be created. 820 */ 821 if (rdonly || (dvp->v_mount->mnt_flag & MNT_RDONLY)) { 822 error = EROFS; 823 goto bad; 824 } 825 /* ASSERT(dvp == ndp->ni_startdir) */ 826 if (cnp->cn_flags & SAVESTART) 827 vref(dvp); 828 /* 829 * We return with ni_vp NULL to indicate that the entry 830 * doesn't currently exist, leaving a pointer to the 831 * (possibly locked) directory inode in ndp->ni_dvp. 832 */ 833 return (0); 834 } 835 dp = *vpp; 836 837 #ifdef DIAGNOSTIC 838 /* 839 * Check for symbolic link 840 */ 841 if (dp->v_type == VLNK && (cnp->cn_flags & FOLLOW)) 842 panic ("relookup: symlink found."); 843 #endif 844 845 /* 846 * Check for read-only file systems. 847 */ 848 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) { 849 /* 850 * Disallow directory write attempts on read-only 851 * file systems. 852 */ 853 if (rdonly || (dp->v_mount->mnt_flag & MNT_RDONLY) || 854 (wantparent && 855 (dvp->v_mount->mnt_flag & MNT_RDONLY))) { 856 error = EROFS; 857 goto bad2; 858 } 859 } 860 /* ASSERT(dvp == ndp->ni_startdir) */ 861 if (cnp->cn_flags & SAVESTART) 862 vref(dvp); 863 if (!wantparent) 864 vrele(dvp); 865 if ((cnp->cn_flags & LOCKLEAF) == 0) 866 VOP_UNLOCK(dp, p); 867 return (0); 868 869 bad2: 870 if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN)) 871 VOP_UNLOCK(dvp, p); 872 vrele(dvp); 873 bad: 874 vput(dp); 875 *vpp = NULL; 876 return (error); 877 } 878