1 /* 2 * Copyright (c) 1982, 1986, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * %sccs.include.redist.c% 11 * 12 * @(#)vfs_lookup.c 8.9 (Berkeley) 05/20/95 13 */ 14 15 #include <sys/param.h> 16 #include <sys/syslimits.h> 17 #include <sys/time.h> 18 #include <sys/namei.h> 19 #include <sys/vnode.h> 20 #include <sys/mount.h> 21 #include <sys/errno.h> 22 #include <sys/malloc.h> 23 #include <sys/filedesc.h> 24 #include <sys/proc.h> 25 26 #ifdef KTRACE 27 #include <sys/ktrace.h> 28 #endif 29 30 /* 31 * Convert a pathname into a pointer to a locked inode. 32 * 33 * The FOLLOW flag is set when symbolic links are to be followed 34 * when they occur at the end of the name translation process. 35 * Symbolic links are always followed for all other pathname 36 * components other than the last. 37 * 38 * The segflg defines whether the name is to be copied from user 39 * space or kernel space. 40 * 41 * Overall outline of namei: 42 * 43 * copy in name 44 * get starting directory 45 * while (!done && !error) { 46 * call lookup to search path. 47 * if symbolic link, massage name in buffer and continue 48 * } 49 */ 50 int 51 namei(ndp) 52 register struct nameidata *ndp; 53 { 54 register struct filedesc *fdp; /* pointer to file descriptor state */ 55 register char *cp; /* pointer into pathname argument */ 56 register struct vnode *dp; /* the directory we are searching */ 57 struct iovec aiov; /* uio for reading symbolic links */ 58 struct uio auio; 59 int error, linklen; 60 struct componentname *cnp = &ndp->ni_cnd; 61 struct proc *p = cnp->cn_proc; 62 63 ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_proc->p_ucred; 64 #ifdef DIAGNOSTIC 65 if (!cnp->cn_cred || !cnp->cn_proc) 66 panic ("namei: bad cred/proc"); 67 if (cnp->cn_nameiop & (~OPMASK)) 68 panic ("namei: nameiop contaminated with flags"); 69 if (cnp->cn_flags & OPMASK) 70 panic ("namei: flags contaminated with nameiops"); 71 #endif 72 fdp = cnp->cn_proc->p_fd; 73 74 /* 75 * Get a buffer for the name to be translated, and copy the 76 * name into the buffer. 77 */ 78 if ((cnp->cn_flags & HASBUF) == 0) 79 MALLOC(cnp->cn_pnbuf, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK); 80 if (ndp->ni_segflg == UIO_SYSSPACE) 81 error = copystr(ndp->ni_dirp, cnp->cn_pnbuf, 82 MAXPATHLEN, &ndp->ni_pathlen); 83 else 84 error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf, 85 MAXPATHLEN, &ndp->ni_pathlen); 86 if (error) { 87 free(cnp->cn_pnbuf, M_NAMEI); 88 ndp->ni_vp = NULL; 89 return (error); 90 } 91 ndp->ni_loopcnt = 0; 92 #ifdef KTRACE 93 if (KTRPOINT(cnp->cn_proc, KTR_NAMEI)) 94 ktrnamei(cnp->cn_proc->p_tracep, cnp->cn_pnbuf); 95 #endif 96 97 /* 98 * Get starting point for the translation. 99 */ 100 if ((ndp->ni_rootdir = fdp->fd_rdir) == NULL) 101 ndp->ni_rootdir = rootvnode; 102 dp = fdp->fd_cdir; 103 VREF(dp); 104 for (;;) { 105 /* 106 * Check if root directory should replace current directory. 107 * Done at start of translation and after symbolic link. 108 */ 109 cnp->cn_nameptr = cnp->cn_pnbuf; 110 if (*(cnp->cn_nameptr) == '/') { 111 vrele(dp); 112 while (*(cnp->cn_nameptr) == '/') { 113 cnp->cn_nameptr++; 114 ndp->ni_pathlen--; 115 } 116 dp = ndp->ni_rootdir; 117 VREF(dp); 118 } 119 ndp->ni_startdir = dp; 120 if (error = lookup(ndp)) { 121 FREE(cnp->cn_pnbuf, M_NAMEI); 122 return (error); 123 } 124 /* 125 * Check for symbolic link 126 */ 127 if ((cnp->cn_flags & ISSYMLINK) == 0) { 128 if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0) 129 FREE(cnp->cn_pnbuf, M_NAMEI); 130 else 131 cnp->cn_flags |= HASBUF; 132 return (0); 133 } 134 if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1) 135 VOP_UNLOCK(ndp->ni_dvp, 0, p); 136 if (ndp->ni_loopcnt++ >= MAXSYMLINKS) { 137 error = ELOOP; 138 break; 139 } 140 if (ndp->ni_pathlen > 1) 141 MALLOC(cp, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 142 else 143 cp = cnp->cn_pnbuf; 144 aiov.iov_base = cp; 145 aiov.iov_len = MAXPATHLEN; 146 auio.uio_iov = &aiov; 147 auio.uio_iovcnt = 1; 148 auio.uio_offset = 0; 149 auio.uio_rw = UIO_READ; 150 auio.uio_segflg = UIO_SYSSPACE; 151 auio.uio_procp = (struct proc *)0; 152 auio.uio_resid = MAXPATHLEN; 153 if (error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred)) { 154 if (ndp->ni_pathlen > 1) 155 free(cp, M_NAMEI); 156 break; 157 } 158 linklen = MAXPATHLEN - auio.uio_resid; 159 if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { 160 if (ndp->ni_pathlen > 1) 161 free(cp, M_NAMEI); 162 error = ENAMETOOLONG; 163 break; 164 } 165 if (ndp->ni_pathlen > 1) { 166 bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen); 167 FREE(cnp->cn_pnbuf, M_NAMEI); 168 cnp->cn_pnbuf = cp; 169 } else 170 cnp->cn_pnbuf[linklen] = '\0'; 171 ndp->ni_pathlen += linklen; 172 vput(ndp->ni_vp); 173 dp = ndp->ni_dvp; 174 } 175 FREE(cnp->cn_pnbuf, M_NAMEI); 176 vrele(ndp->ni_dvp); 177 vput(ndp->ni_vp); 178 ndp->ni_vp = NULL; 179 return (error); 180 } 181 182 /* 183 * Search a pathname. 184 * This is a very central and rather complicated routine. 185 * 186 * The pathname is pointed to by ni_ptr and is of length ni_pathlen. 187 * The starting directory is taken from ni_startdir. The pathname is 188 * descended until done, or a symbolic link is encountered. The variable 189 * ni_more is clear if the path is completed; it is set to one if a 190 * symbolic link needing interpretation is encountered. 191 * 192 * The flag argument is LOOKUP, CREATE, RENAME, or DELETE depending on 193 * whether the name is to be looked up, created, renamed, or deleted. 194 * When CREATE, RENAME, or DELETE is specified, information usable in 195 * creating, renaming, or deleting a directory entry may be calculated. 196 * If flag has LOCKPARENT or'ed into it, the parent directory is returned 197 * locked. If flag has WANTPARENT or'ed into it, the parent directory is 198 * returned unlocked. Otherwise the parent directory is not returned. If 199 * the target of the pathname exists and LOCKLEAF is or'ed into the flag 200 * the target is returned locked, otherwise it is returned unlocked. 201 * When creating or renaming and LOCKPARENT is specified, the target may not 202 * be ".". When deleting and LOCKPARENT is specified, the target may be ".". 203 * 204 * Overall outline of lookup: 205 * 206 * dirloop: 207 * identify next component of name at ndp->ni_ptr 208 * handle degenerate case where name is null string 209 * if .. and crossing mount points and on mounted filesys, find parent 210 * call VOP_LOOKUP routine for next component name 211 * directory vnode returned in ni_dvp, unlocked unless LOCKPARENT set 212 * component vnode returned in ni_vp (if it exists), locked. 213 * if result vnode is mounted on and crossing mount points, 214 * find mounted on vnode 215 * if more components of name, do next level at dirloop 216 * return the answer in ni_vp, locked if LOCKLEAF set 217 * if LOCKPARENT set, return locked parent in ni_dvp 218 * if WANTPARENT set, return unlocked parent in ni_dvp 219 */ 220 int 221 lookup(ndp) 222 register struct nameidata *ndp; 223 { 224 register char *cp; /* pointer into pathname argument */ 225 register struct vnode *dp = 0; /* the directory we are searching */ 226 struct vnode *tdp; /* saved dp */ 227 struct mount *mp; /* mount table entry */ 228 int docache; /* == 0 do not cache last component */ 229 int wantparent; /* 1 => wantparent or lockparent flag */ 230 int rdonly; /* lookup read-only flag bit */ 231 int error = 0; 232 struct componentname *cnp = &ndp->ni_cnd; 233 struct proc *p = cnp->cn_proc; 234 235 /* 236 * Setup: break out flag bits into variables. 237 */ 238 wantparent = cnp->cn_flags & (LOCKPARENT | WANTPARENT); 239 docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE; 240 if (cnp->cn_nameiop == DELETE || 241 (wantparent && cnp->cn_nameiop != CREATE)) 242 docache = 0; 243 rdonly = cnp->cn_flags & RDONLY; 244 ndp->ni_dvp = NULL; 245 cnp->cn_flags &= ~ISSYMLINK; 246 dp = ndp->ni_startdir; 247 ndp->ni_startdir = NULLVP; 248 vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p); 249 250 dirloop: 251 /* 252 * Search a new directory. 253 * 254 * The cn_hash value is for use by vfs_cache. 255 * The last component of the filename is left accessible via 256 * cnp->cn_nameptr for callers that need the name. Callers needing 257 * the name set the SAVENAME flag. When done, they assume 258 * responsibility for freeing the pathname buffer. 259 */ 260 cnp->cn_consume = 0; 261 cnp->cn_hash = 0; 262 for (cp = cnp->cn_nameptr; *cp != 0 && *cp != '/'; cp++) 263 cnp->cn_hash += (unsigned char)*cp; 264 cnp->cn_namelen = cp - cnp->cn_nameptr; 265 if (cnp->cn_namelen > NAME_MAX) { 266 error = ENAMETOOLONG; 267 goto bad; 268 } 269 #ifdef NAMEI_DIAGNOSTIC 270 { char c = *cp; 271 *cp = '\0'; 272 printf("{%s}: ", cnp->cn_nameptr); 273 *cp = c; } 274 #endif 275 ndp->ni_pathlen -= cnp->cn_namelen; 276 ndp->ni_next = cp; 277 cnp->cn_flags |= MAKEENTRY; 278 if (*cp == '\0' && docache == 0) 279 cnp->cn_flags &= ~MAKEENTRY; 280 if (cnp->cn_namelen == 2 && 281 cnp->cn_nameptr[1] == '.' && cnp->cn_nameptr[0] == '.') 282 cnp->cn_flags |= ISDOTDOT; 283 else 284 cnp->cn_flags &= ~ISDOTDOT; 285 if (*ndp->ni_next == 0) 286 cnp->cn_flags |= ISLASTCN; 287 else 288 cnp->cn_flags &= ~ISLASTCN; 289 290 291 /* 292 * Check for degenerate name (e.g. / or "") 293 * which is a way of talking about a directory, 294 * e.g. like "/." or ".". 295 */ 296 if (cnp->cn_nameptr[0] == '\0') { 297 if (dp->v_type != VDIR) { 298 error = ENOTDIR; 299 goto bad; 300 } 301 if (cnp->cn_nameiop != LOOKUP) { 302 error = EISDIR; 303 goto bad; 304 } 305 if (wantparent) { 306 ndp->ni_dvp = dp; 307 VREF(dp); 308 } 309 ndp->ni_vp = dp; 310 if (!(cnp->cn_flags & (LOCKPARENT | LOCKLEAF))) 311 VOP_UNLOCK(dp, 0, p); 312 if (cnp->cn_flags & SAVESTART) 313 panic("lookup: SAVESTART"); 314 return (0); 315 } 316 317 /* 318 * Handle "..": two special cases. 319 * 1. If at root directory (e.g. after chroot) 320 * or at absolute root directory 321 * then ignore it so can't get out. 322 * 2. If this vnode is the root of a mounted 323 * filesystem, then replace it with the 324 * vnode which was mounted on so we take the 325 * .. in the other file system. 326 */ 327 if (cnp->cn_flags & ISDOTDOT) { 328 for (;;) { 329 if (dp == ndp->ni_rootdir || dp == rootvnode) { 330 ndp->ni_dvp = dp; 331 ndp->ni_vp = dp; 332 VREF(dp); 333 goto nextname; 334 } 335 if ((dp->v_flag & VROOT) == 0 || 336 (cnp->cn_flags & NOCROSSMOUNT)) 337 break; 338 tdp = dp; 339 dp = dp->v_mount->mnt_vnodecovered; 340 vput(tdp); 341 VREF(dp); 342 vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p); 343 } 344 } 345 346 /* 347 * We now have a segment name to search for, and a directory to search. 348 */ 349 unionlookup: 350 ndp->ni_dvp = dp; 351 if (error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) { 352 #ifdef DIAGNOSTIC 353 if (ndp->ni_vp != NULL) 354 panic("leaf should be empty"); 355 #endif 356 #ifdef NAMEI_DIAGNOSTIC 357 printf("not found\n"); 358 #endif 359 if ((error == ENOENT) && 360 (dp->v_flag & VROOT) && 361 (dp->v_mount->mnt_flag & MNT_UNION)) { 362 tdp = dp; 363 dp = dp->v_mount->mnt_vnodecovered; 364 vput(tdp); 365 VREF(dp); 366 vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p); 367 goto unionlookup; 368 } 369 370 if (error != EJUSTRETURN) 371 goto bad; 372 /* 373 * If creating and at end of pathname, then can consider 374 * allowing file to be created. 375 */ 376 if (rdonly || (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY)) { 377 error = EROFS; 378 goto bad; 379 } 380 /* 381 * We return with ni_vp NULL to indicate that the entry 382 * doesn't currently exist, leaving a pointer to the 383 * (possibly locked) directory inode in ndp->ni_dvp. 384 */ 385 if (cnp->cn_flags & SAVESTART) { 386 ndp->ni_startdir = ndp->ni_dvp; 387 VREF(ndp->ni_startdir); 388 } 389 return (0); 390 } 391 #ifdef NAMEI_DIAGNOSTIC 392 printf("found\n"); 393 #endif 394 395 /* 396 * Take into account any additional components consumed by 397 * the underlying filesystem. 398 */ 399 if (cnp->cn_consume > 0) { 400 cnp->cn_nameptr += cnp->cn_consume; 401 ndp->ni_next += cnp->cn_consume; 402 ndp->ni_pathlen -= cnp->cn_consume; 403 cnp->cn_consume = 0; 404 } 405 406 dp = ndp->ni_vp; 407 /* 408 * Check to see if the vnode has been mounted on; 409 * if so find the root of the mounted file system. 410 */ 411 while (dp->v_type == VDIR && (mp = dp->v_mountedhere) && 412 (cnp->cn_flags & NOCROSSMOUNT) == 0) { 413 if (vfs_busy(mp, 0, 0, p)) 414 continue; 415 error = VFS_ROOT(mp, &tdp); 416 vfs_unbusy(mp, p); 417 if (error) 418 goto bad2; 419 vput(dp); 420 ndp->ni_vp = dp = tdp; 421 } 422 423 /* 424 * Check for symbolic link 425 */ 426 if ((dp->v_type == VLNK) && 427 ((cnp->cn_flags & FOLLOW) || *ndp->ni_next == '/')) { 428 cnp->cn_flags |= ISSYMLINK; 429 return (0); 430 } 431 432 nextname: 433 /* 434 * Not a symbolic link. If more pathname, 435 * continue at next component, else return. 436 */ 437 if (*ndp->ni_next == '/') { 438 cnp->cn_nameptr = ndp->ni_next; 439 while (*cnp->cn_nameptr == '/') { 440 cnp->cn_nameptr++; 441 ndp->ni_pathlen--; 442 } 443 vrele(ndp->ni_dvp); 444 goto dirloop; 445 } 446 /* 447 * Check for read-only file systems. 448 */ 449 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) { 450 /* 451 * Disallow directory write attempts on read-only 452 * file systems. 453 */ 454 if (rdonly || (dp->v_mount->mnt_flag & MNT_RDONLY) || 455 (wantparent && 456 (ndp->ni_dvp->v_mount->mnt_flag & MNT_RDONLY))) { 457 error = EROFS; 458 goto bad2; 459 } 460 } 461 if (cnp->cn_flags & SAVESTART) { 462 ndp->ni_startdir = ndp->ni_dvp; 463 VREF(ndp->ni_startdir); 464 } 465 if (!wantparent) 466 vrele(ndp->ni_dvp); 467 if ((cnp->cn_flags & LOCKLEAF) == 0) 468 VOP_UNLOCK(dp, 0, p); 469 return (0); 470 471 bad2: 472 if ((cnp->cn_flags & LOCKPARENT) && *ndp->ni_next == '\0') 473 VOP_UNLOCK(ndp->ni_dvp, 0, p); 474 vrele(ndp->ni_dvp); 475 bad: 476 vput(dp); 477 ndp->ni_vp = NULL; 478 return (error); 479 } 480 481 /* 482 * relookup - lookup a path name component 483 * Used by lookup to re-aquire things. 484 */ 485 int 486 relookup(dvp, vpp, cnp) 487 struct vnode *dvp, **vpp; 488 struct componentname *cnp; 489 { 490 struct proc *p = cnp->cn_proc; 491 struct vnode *dp = 0; /* the directory we are searching */ 492 int docache; /* == 0 do not cache last component */ 493 int wantparent; /* 1 => wantparent or lockparent flag */ 494 int rdonly; /* lookup read-only flag bit */ 495 int error = 0; 496 #ifdef NAMEI_DIAGNOSTIC 497 int newhash; /* DEBUG: check name hash */ 498 char *cp; /* DEBUG: check name ptr/len */ 499 #endif 500 501 /* 502 * Setup: break out flag bits into variables. 503 */ 504 wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT); 505 docache = (cnp->cn_flags & NOCACHE) ^ NOCACHE; 506 if (cnp->cn_nameiop == DELETE || 507 (wantparent && cnp->cn_nameiop != CREATE)) 508 docache = 0; 509 rdonly = cnp->cn_flags & RDONLY; 510 cnp->cn_flags &= ~ISSYMLINK; 511 dp = dvp; 512 vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p); 513 514 /* dirloop: */ 515 /* 516 * Search a new directory. 517 * 518 * The cn_hash value is for use by vfs_cache. 519 * The last component of the filename is left accessible via 520 * cnp->cn_nameptr for callers that need the name. Callers needing 521 * the name set the SAVENAME flag. When done, they assume 522 * responsibility for freeing the pathname buffer. 523 */ 524 #ifdef NAMEI_DIAGNOSTIC 525 for (newhash = 0, cp = cnp->cn_nameptr; *cp != 0 && *cp != '/'; cp++) 526 newhash += (unsigned char)*cp; 527 if (newhash != cnp->cn_hash) 528 panic("relookup: bad hash"); 529 if (cnp->cn_namelen != cp - cnp->cn_nameptr) 530 panic ("relookup: bad len"); 531 if (*cp != 0) 532 panic("relookup: not last component"); 533 printf("{%s}: ", cnp->cn_nameptr); 534 #endif 535 536 /* 537 * Check for degenerate name (e.g. / or "") 538 * which is a way of talking about a directory, 539 * e.g. like "/." or ".". 540 */ 541 if (cnp->cn_nameptr[0] == '\0') { 542 if (cnp->cn_nameiop != LOOKUP || wantparent) { 543 error = EISDIR; 544 goto bad; 545 } 546 if (dp->v_type != VDIR) { 547 error = ENOTDIR; 548 goto bad; 549 } 550 if (!(cnp->cn_flags & LOCKLEAF)) 551 VOP_UNLOCK(dp, 0, p); 552 *vpp = dp; 553 if (cnp->cn_flags & SAVESTART) 554 panic("lookup: SAVESTART"); 555 return (0); 556 } 557 558 if (cnp->cn_flags & ISDOTDOT) 559 panic ("relookup: lookup on dot-dot"); 560 561 /* 562 * We now have a segment name to search for, and a directory to search. 563 */ 564 if (error = VOP_LOOKUP(dp, vpp, cnp)) { 565 #ifdef DIAGNOSTIC 566 if (*vpp != NULL) 567 panic("leaf should be empty"); 568 #endif 569 if (error != EJUSTRETURN) 570 goto bad; 571 /* 572 * If creating and at end of pathname, then can consider 573 * allowing file to be created. 574 */ 575 if (rdonly || (dvp->v_mount->mnt_flag & MNT_RDONLY)) { 576 error = EROFS; 577 goto bad; 578 } 579 /* ASSERT(dvp == ndp->ni_startdir) */ 580 if (cnp->cn_flags & SAVESTART) 581 VREF(dvp); 582 /* 583 * We return with ni_vp NULL to indicate that the entry 584 * doesn't currently exist, leaving a pointer to the 585 * (possibly locked) directory inode in ndp->ni_dvp. 586 */ 587 return (0); 588 } 589 dp = *vpp; 590 591 #ifdef DIAGNOSTIC 592 /* 593 * Check for symbolic link 594 */ 595 if (dp->v_type == VLNK && (cnp->cn_flags & FOLLOW)) 596 panic ("relookup: symlink found.\n"); 597 #endif 598 599 /* 600 * Check for read-only file systems. 601 */ 602 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) { 603 /* 604 * Disallow directory write attempts on read-only 605 * file systems. 606 */ 607 if (rdonly || (dp->v_mount->mnt_flag & MNT_RDONLY) || 608 (wantparent && 609 (dvp->v_mount->mnt_flag & MNT_RDONLY))) { 610 error = EROFS; 611 goto bad2; 612 } 613 } 614 /* ASSERT(dvp == ndp->ni_startdir) */ 615 if (cnp->cn_flags & SAVESTART) 616 VREF(dvp); 617 618 if (!wantparent) 619 vrele(dvp); 620 if ((cnp->cn_flags & LOCKLEAF) == 0) 621 VOP_UNLOCK(dp, 0, p); 622 return (0); 623 624 bad2: 625 if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN)) 626 VOP_UNLOCK(dvp, 0, p); 627 vrele(dvp); 628 bad: 629 vput(dp); 630 *vpp = NULL; 631 return (error); 632 } 633