1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 24 * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. 25 * Copyright (c) 2015, Joyent, Inc. 26 */ 27 28 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 29 /* All Rights Reserved */ 30 31 /* 32 * University Copyright- Copyright (c) 1982, 1986, 1988 33 * The Regents of the University of California 34 * All Rights Reserved 35 * 36 * University Acknowledgment- Portions of this document are derived from 37 * software developed by the University of California, Berkeley, and its 38 * contributors. 39 */ 40 41 #include <sys/types.h> 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/cpuvar.h> 45 #include <sys/errno.h> 46 #include <sys/cred.h> 47 #include <sys/user.h> 48 #include <sys/uio.h> 49 #include <sys/vfs.h> 50 #include <sys/vnode.h> 51 #include <sys/pathname.h> 52 #include <sys/proc.h> 53 #include <sys/vtrace.h> 54 #include <sys/sysmacros.h> 55 #include <sys/debug.h> 56 #include <sys/dirent.h> 57 #include <c2/audit.h> 58 #include <sys/zone.h> 59 #include <sys/dnlc.h> 60 #include <sys/fs/snode.h> 61 62 /* Controls whether paths are stored with vnodes. */ 63 int vfs_vnode_path = 1; 64 65 int 66 lookupname( 67 char *fnamep, 68 enum uio_seg seg, 69 int followlink, 70 vnode_t **dirvpp, 71 vnode_t **compvpp) 72 { 73 return (lookupnameatcred(fnamep, seg, followlink, dirvpp, compvpp, NULL, 74 CRED())); 75 } 76 77 /* 78 * Lookup the user file name, 79 * Handle allocation and freeing of pathname buffer, return error. 80 */ 81 int 82 lookupnameatcred( 83 char *fnamep, /* user pathname */ 84 enum uio_seg seg, /* addr space that name is in */ 85 int followlink, /* follow sym links */ 86 vnode_t **dirvpp, /* ret for ptr to parent dir vnode */ 87 vnode_t **compvpp, /* ret for ptr to component vnode */ 88 vnode_t *startvp, /* start path search from vp */ 89 cred_t *cr) /* credential */ 90 { 91 char namebuf[TYPICALMAXPATHLEN]; 92 struct pathname lookpn; 93 int error; 94 95 error = pn_get_buf(fnamep, seg, &lookpn, namebuf, sizeof (namebuf)); 96 if (error == 0) { 97 error = lookuppnatcred(&lookpn, NULL, followlink, 98 dirvpp, compvpp, startvp, cr); 99 } 100 if (error == ENAMETOOLONG) { 101 /* 102 * This thread used a pathname > TYPICALMAXPATHLEN bytes long. 103 */ 104 if (error = pn_get(fnamep, seg, &lookpn)) 105 return (error); 106 error = lookuppnatcred(&lookpn, NULL, followlink, 107 dirvpp, compvpp, startvp, cr); 108 pn_free(&lookpn); 109 } 110 111 return (error); 112 } 113 114 int 115 lookupnameat(char *fnamep, enum uio_seg seg, int followlink, 116 vnode_t **dirvpp, vnode_t **compvpp, vnode_t *startvp) 117 { 118 return (lookupnameatcred(fnamep, seg, followlink, dirvpp, compvpp, 119 startvp, CRED())); 120 } 121 122 int 123 lookuppn( 124 struct pathname *pnp, 125 struct pathname *rpnp, 126 int followlink, 127 vnode_t **dirvpp, 128 vnode_t **compvpp) 129 { 130 return (lookuppnatcred(pnp, rpnp, followlink, dirvpp, compvpp, NULL, 131 CRED())); 132 } 133 134 /* 135 * Lookup the user file name from a given vp, using a specific credential. 136 */ 137 int 138 lookuppnatcred( 139 struct pathname *pnp, /* pathname to lookup */ 140 struct pathname *rpnp, /* if non-NULL, return resolved path */ 141 int followlink, /* (don't) follow sym links */ 142 vnode_t **dirvpp, /* ptr for parent vnode */ 143 vnode_t **compvpp, /* ptr for entry vnode */ 144 vnode_t *startvp, /* start search from this vp */ 145 cred_t *cr) /* user credential */ 146 { 147 vnode_t *vp; /* current directory vp */ 148 vnode_t *rootvp; 149 proc_t *p = curproc; 150 151 if (pnp->pn_pathlen == 0) 152 return (ENOENT); 153 154 mutex_enter(&p->p_lock); /* for u_rdir and u_cdir */ 155 if ((rootvp = PTOU(p)->u_rdir) == NULL) 156 rootvp = rootdir; 157 else if (rootvp != rootdir) /* no need to VN_HOLD rootdir */ 158 VN_HOLD(rootvp); 159 160 if (pnp->pn_path[0] == '/') { 161 vp = rootvp; 162 } else { 163 vp = (startvp == NULL) ? PTOU(p)->u_cdir : startvp; 164 } 165 VN_HOLD(vp); 166 mutex_exit(&p->p_lock); 167 168 /* 169 * Skip over leading slashes 170 */ 171 if (pnp->pn_path[0] == '/') { 172 do { 173 pnp->pn_path++; 174 pnp->pn_pathlen--; 175 } while (pnp->pn_path[0] == '/'); 176 } 177 178 return (lookuppnvp(pnp, rpnp, followlink, dirvpp, 179 compvpp, rootvp, vp, cr)); 180 } 181 182 int 183 lookuppnat(struct pathname *pnp, struct pathname *rpnp, 184 int followlink, vnode_t **dirvpp, vnode_t **compvpp, 185 vnode_t *startvp) 186 { 187 return (lookuppnatcred(pnp, rpnp, followlink, dirvpp, compvpp, startvp, 188 CRED())); 189 } 190 191 /* Private flag to do our getcwd() dirty work */ 192 #define LOOKUP_CHECKREAD 0x10 193 #define LOOKUP_MASK (~LOOKUP_CHECKREAD) 194 195 /* 196 * Starting at current directory, translate pathname pnp to end. 197 * Leave pathname of final component in pnp, return the vnode 198 * for the final component in *compvpp, and return the vnode 199 * for the parent of the final component in dirvpp. 200 * 201 * This is the central routine in pathname translation and handles 202 * multiple components in pathnames, separating them at /'s. It also 203 * implements mounted file systems and processes symbolic links. 204 * 205 * vp is the vnode where the directory search should start. 206 * 207 * Reference counts: vp must be held prior to calling this function. rootvp 208 * should only be held if rootvp != rootdir. 209 */ 210 int 211 lookuppnvp( 212 struct pathname *pnp, /* pathname to lookup */ 213 struct pathname *rpnp, /* if non-NULL, return resolved path */ 214 int flags, /* follow symlinks */ 215 vnode_t **dirvpp, /* ptr for parent vnode */ 216 vnode_t **compvpp, /* ptr for entry vnode */ 217 vnode_t *rootvp, /* rootvp */ 218 vnode_t *vp, /* directory to start search at */ 219 cred_t *cr) /* user's credential */ 220 { 221 vnode_t *cvp; /* current component vp */ 222 char component[MAXNAMELEN]; /* buffer for component (incl null) */ 223 int error; 224 int nlink; 225 int lookup_flags; 226 struct pathname presrvd; /* case preserved name */ 227 struct pathname *pp = NULL; 228 vnode_t *startvp; 229 vnode_t *zonevp = curproc->p_zone->zone_rootvp; /* zone root */ 230 int must_be_directory = 0; 231 boolean_t retry_with_kcred; 232 uint32_t auditing = AU_AUDITING(); 233 234 CPU_STATS_ADDQ(CPU, sys, namei, 1); 235 nlink = 0; 236 cvp = NULL; 237 if (rpnp) 238 rpnp->pn_pathlen = 0; 239 240 lookup_flags = dirvpp ? LOOKUP_DIR : 0; 241 if (flags & FIGNORECASE) { 242 lookup_flags |= FIGNORECASE; 243 pn_alloc(&presrvd); 244 pp = &presrvd; 245 } 246 247 if (auditing) 248 audit_anchorpath(pnp, vp == rootvp); 249 250 /* 251 * Eliminate any trailing slashes in the pathname. 252 * If there are any, we must follow all symlinks. 253 * Also, we must guarantee that the last component is a directory. 254 */ 255 if (pn_fixslash(pnp)) { 256 flags |= FOLLOW; 257 must_be_directory = 1; 258 } 259 260 startvp = vp; 261 next: 262 retry_with_kcred = B_FALSE; 263 264 /* 265 * Make sure we have a directory. 266 */ 267 if (vp->v_type != VDIR) { 268 error = ENOTDIR; 269 goto bad; 270 } 271 272 if (rpnp && VN_CMP(vp, rootvp)) 273 (void) pn_set(rpnp, "/"); 274 275 /* 276 * Process the next component of the pathname. 277 */ 278 if (error = pn_getcomponent(pnp, component)) { 279 goto bad; 280 } 281 282 /* 283 * Handle "..": two special cases. 284 * 1. If we're at the root directory (e.g. after chroot or 285 * zone_enter) then change ".." to "." so we can't get 286 * out of this subtree. 287 * 2. If this vnode is the root of a mounted file system, 288 * then replace it with the vnode that was mounted on 289 * so that we take the ".." in the other file system. 290 */ 291 if (component[0] == '.' && component[1] == '.' && component[2] == 0) { 292 checkforroot: 293 if (VN_CMP(vp, rootvp) || VN_CMP(vp, zonevp)) { 294 component[1] = '\0'; 295 } else if (vp->v_flag & VROOT) { 296 vfs_t *vfsp; 297 cvp = vp; 298 299 /* 300 * While we deal with the vfs pointer from the vnode 301 * the filesystem could have been forcefully unmounted 302 * and the vnode's v_vfsp could have been invalidated 303 * by VFS_UNMOUNT. Hence, we cache v_vfsp and use it 304 * with vfs_rlock_wait/vfs_unlock. 305 * It is safe to use the v_vfsp even it is freed by 306 * VFS_UNMOUNT because vfs_rlock_wait/vfs_unlock 307 * do not dereference v_vfsp. It is just used as a 308 * magic cookie. 309 * One more corner case here is the memory getting 310 * reused for another vfs structure. In this case 311 * lookuppnvp's vfs_rlock_wait will succeed, domount's 312 * vfs_lock will fail and domount will bail out with an 313 * error (EBUSY). 314 */ 315 vfsp = cvp->v_vfsp; 316 317 /* 318 * This lock is used to synchronize 319 * mounts/unmounts and lookups. 320 * Threads doing mounts/unmounts hold the 321 * writers version vfs_lock_wait(). 322 */ 323 324 vfs_rlock_wait(vfsp); 325 326 /* 327 * If this vnode is on a file system that 328 * has been forcibly unmounted, 329 * we can't proceed. Cancel this operation 330 * and return EIO. 331 * 332 * vfs_vnodecovered is NULL if unmounted. 333 * Currently, nfs uses VFS_UNMOUNTED to 334 * check if it's a forced-umount. Keep the 335 * same checking here as well even though it 336 * may not be needed. 337 */ 338 if (((vp = cvp->v_vfsp->vfs_vnodecovered) == NULL) || 339 (cvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)) { 340 vfs_unlock(vfsp); 341 VN_RELE(cvp); 342 if (pp) 343 pn_free(pp); 344 return (EIO); 345 } 346 VN_HOLD(vp); 347 vfs_unlock(vfsp); 348 VN_RELE(cvp); 349 cvp = NULL; 350 /* 351 * Crossing mount points. For eg: We are doing 352 * a lookup of ".." for file systems root vnode 353 * mounted here, and VOP_LOOKUP() (with covered vnode) 354 * will be on underlying file systems mount point 355 * vnode. Set retry_with_kcred flag as we might end 356 * up doing VOP_LOOKUP() with kcred if required. 357 */ 358 retry_with_kcred = B_TRUE; 359 goto checkforroot; 360 } 361 } 362 363 /* 364 * LOOKUP_CHECKREAD is a private flag used by vnodetopath() to indicate 365 * that we need to have read permission on every directory in the entire 366 * path. This is used to ensure that a forward-lookup of a cached value 367 * has the same effect as a reverse-lookup when the cached value cannot 368 * be found. 369 */ 370 if ((flags & LOOKUP_CHECKREAD) && 371 (error = VOP_ACCESS(vp, VREAD, 0, cr, NULL)) != 0) 372 goto bad; 373 374 /* 375 * Perform a lookup in the current directory. 376 */ 377 error = VOP_LOOKUP(vp, component, &cvp, pnp, lookup_flags, 378 rootvp, cr, NULL, NULL, pp); 379 380 /* 381 * Retry with kcred - If crossing mount points & error is EACCES. 382 * 383 * If we are crossing mount points here and doing ".." lookup, 384 * VOP_LOOKUP() might fail if the underlying file systems 385 * mount point has no execute permission. In cases like these, 386 * we retry VOP_LOOKUP() by giving as much privilage as possible 387 * by passing kcred credentials. 388 * 389 * In case of hierarchical file systems, passing kcred still may 390 * or may not work. 391 * For eg: UFS FS --> Mount NFS FS --> Again mount UFS on some 392 * directory inside NFS FS. 393 */ 394 if ((error == EACCES) && retry_with_kcred) 395 error = VOP_LOOKUP(vp, component, &cvp, pnp, lookup_flags, 396 rootvp, zone_kcred(), NULL, NULL, pp); 397 398 if (error) { 399 cvp = NULL; 400 /* 401 * On error, return hard error if 402 * (a) we're not at the end of the pathname yet, or 403 * (b) the caller didn't want the parent directory, or 404 * (c) we failed for some reason other than a missing entry. 405 */ 406 if (pn_pathleft(pnp) || dirvpp == NULL || error != ENOENT) 407 goto bad; 408 if (auditing) { /* directory access */ 409 if (error = audit_savepath(pnp, vp, vp, error, cr)) 410 goto bad_noaudit; 411 } 412 413 pn_setlast(pnp); 414 /* 415 * We inform the caller that the desired entry must be 416 * a directory by adding a '/' to the component name. 417 */ 418 if (must_be_directory && (error = pn_addslash(pnp)) != 0) 419 goto bad; 420 *dirvpp = vp; 421 if (compvpp != NULL) 422 *compvpp = NULL; 423 if (rootvp != rootdir) 424 VN_RELE(rootvp); 425 if (pp) 426 pn_free(pp); 427 return (0); 428 } 429 430 /* 431 * Traverse mount points. 432 * XXX why don't we need to hold a read lock here (call vn_vfsrlock)? 433 * What prevents a concurrent update to v_vfsmountedhere? 434 * Possible answer: if mounting, we might not see the mount 435 * if it is concurrently coming into existence, but that's 436 * really not much different from the thread running a bit slower. 437 * If unmounting, we may get into traverse() when we shouldn't, 438 * but traverse() will catch this case for us. 439 * (For this to work, fetching v_vfsmountedhere had better 440 * be atomic!) 441 */ 442 if (vn_mountedvfs(cvp) != NULL) { 443 if ((error = traverse(&cvp)) != 0) 444 goto bad; 445 } 446 447 /* 448 * If we hit a symbolic link and there is more path to be 449 * translated or this operation does not wish to apply 450 * to a link, then place the contents of the link at the 451 * front of the remaining pathname. 452 */ 453 if (cvp->v_type == VLNK && ((flags & FOLLOW) || pn_pathleft(pnp))) { 454 struct pathname linkpath; 455 456 if (cvp->v_vfsp->vfs_flag & VFS_NOFOLLOW) { 457 /* 458 * mounts with the nofollow option set never resolve 459 * symlinks. They are treated as dangling symlink, 460 * always returning ENOENT 461 */ 462 error = ENOENT; 463 goto bad; 464 } 465 466 if (++nlink > MAXSYMLINKS) { 467 error = ELOOP; 468 goto bad; 469 } 470 pn_alloc(&linkpath); 471 if (error = pn_getsymlink(cvp, &linkpath, cr)) { 472 pn_free(&linkpath); 473 goto bad; 474 } 475 476 if (auditing) 477 audit_symlink(pnp, &linkpath); 478 479 if (pn_pathleft(&linkpath) == 0) 480 (void) pn_set(&linkpath, "."); 481 error = pn_insert(pnp, &linkpath, strlen(component)); 482 pn_free(&linkpath); 483 if (error) 484 goto bad; 485 VN_RELE(cvp); 486 cvp = NULL; 487 if (pnp->pn_pathlen == 0) { 488 error = ENOENT; 489 goto bad; 490 } 491 if (pnp->pn_path[0] == '/') { 492 do { 493 pnp->pn_path++; 494 pnp->pn_pathlen--; 495 } while (pnp->pn_path[0] == '/'); 496 VN_RELE(vp); 497 vp = rootvp; 498 VN_HOLD(vp); 499 } 500 if (auditing) 501 audit_anchorpath(pnp, vp == rootvp); 502 if (pn_fixslash(pnp)) { 503 flags |= FOLLOW; 504 must_be_directory = 1; 505 } 506 goto next; 507 } 508 509 /* 510 * If rpnp is non-NULL, remember the resolved path name therein. 511 * Do not include "." components. Collapse occurrences of 512 * "previous/..", so long as "previous" is not itself "..". 513 * Exhausting rpnp results in error ENAMETOOLONG. 514 */ 515 if (rpnp && strcmp(component, ".") != 0) { 516 size_t len; 517 518 if (strcmp(component, "..") == 0 && 519 rpnp->pn_pathlen != 0 && 520 !((rpnp->pn_pathlen > 2 && 521 strncmp(rpnp->pn_path+rpnp->pn_pathlen-3, "/..", 3) == 0) || 522 (rpnp->pn_pathlen == 2 && 523 strncmp(rpnp->pn_path, "..", 2) == 0))) { 524 while (rpnp->pn_pathlen && 525 rpnp->pn_path[rpnp->pn_pathlen-1] != '/') 526 rpnp->pn_pathlen--; 527 if (rpnp->pn_pathlen > 1) 528 rpnp->pn_pathlen--; 529 rpnp->pn_path[rpnp->pn_pathlen] = '\0'; 530 } else { 531 if (rpnp->pn_pathlen != 0 && 532 rpnp->pn_path[rpnp->pn_pathlen-1] != '/') 533 rpnp->pn_path[rpnp->pn_pathlen++] = '/'; 534 if (flags & FIGNORECASE) { 535 /* 536 * Return the case-preserved name 537 * within the resolved path. 538 */ 539 error = copystr(pp->pn_buf, 540 rpnp->pn_path + rpnp->pn_pathlen, 541 rpnp->pn_bufsize - rpnp->pn_pathlen, &len); 542 } else { 543 error = copystr(component, 544 rpnp->pn_path + rpnp->pn_pathlen, 545 rpnp->pn_bufsize - rpnp->pn_pathlen, &len); 546 } 547 if (error) /* copystr() returns ENAMETOOLONG */ 548 goto bad; 549 rpnp->pn_pathlen += (len - 1); 550 ASSERT(rpnp->pn_bufsize > rpnp->pn_pathlen); 551 } 552 } 553 554 /* 555 * If no more components, return last directory (if wanted) and 556 * last component (if wanted). 557 */ 558 if (pn_pathleft(pnp) == 0) { 559 /* 560 * If there was a trailing slash in the pathname, 561 * make sure the last component is a directory. 562 */ 563 if (must_be_directory && cvp->v_type != VDIR) { 564 error = ENOTDIR; 565 goto bad; 566 } 567 if (dirvpp != NULL) { 568 /* 569 * Check that we have the real parent and not 570 * an alias of the last component. 571 */ 572 if (vn_compare(vp, cvp)) { 573 if (auditing) 574 (void) audit_savepath(pnp, cvp, vp, 575 EINVAL, cr); 576 pn_setlast(pnp); 577 VN_RELE(vp); 578 VN_RELE(cvp); 579 if (rootvp != rootdir) 580 VN_RELE(rootvp); 581 if (pp) 582 pn_free(pp); 583 return (EINVAL); 584 } 585 *dirvpp = vp; 586 } else 587 VN_RELE(vp); 588 if (auditing) 589 (void) audit_savepath(pnp, cvp, vp, 0, cr); 590 if (pnp->pn_path == pnp->pn_buf) 591 (void) pn_set(pnp, "."); 592 else 593 pn_setlast(pnp); 594 if (rpnp) { 595 if (VN_CMP(cvp, rootvp)) 596 (void) pn_set(rpnp, "/"); 597 else if (rpnp->pn_pathlen == 0) 598 (void) pn_set(rpnp, "."); 599 } 600 601 if (compvpp != NULL) 602 *compvpp = cvp; 603 else 604 VN_RELE(cvp); 605 if (rootvp != rootdir) 606 VN_RELE(rootvp); 607 if (pp) 608 pn_free(pp); 609 return (0); 610 } 611 612 /* 613 * Skip over slashes from end of last component. 614 */ 615 while (pnp->pn_path[0] == '/') { 616 pnp->pn_path++; 617 pnp->pn_pathlen--; 618 } 619 620 /* 621 * Searched through another level of directory: 622 * release previous directory handle and save new (result 623 * of lookup) as current directory. 624 */ 625 VN_RELE(vp); 626 vp = cvp; 627 cvp = NULL; 628 goto next; 629 630 bad: 631 if (auditing) /* reached end of path */ 632 (void) audit_savepath(pnp, cvp, vp, error, cr); 633 bad_noaudit: 634 /* 635 * Error. Release vnodes and return. 636 */ 637 if (cvp) 638 VN_RELE(cvp); 639 /* 640 * If the error was ESTALE and the current directory to look in 641 * was the root for this lookup, the root for a mounted file 642 * system, or the starting directory for lookups, then 643 * return ENOENT instead of ESTALE. In this case, no recovery 644 * is possible by the higher level. If ESTALE was returned for 645 * some intermediate directory along the path, then recovery 646 * is potentially possible and retrying from the higher level 647 * will either correct the situation by purging stale cache 648 * entries or eventually get back to the point where no recovery 649 * is possible. 650 */ 651 if (error == ESTALE && 652 (VN_CMP(vp, rootvp) || (vp->v_flag & VROOT) || vp == startvp)) 653 error = ENOENT; 654 VN_RELE(vp); 655 if (rootvp != rootdir) 656 VN_RELE(rootvp); 657 if (pp) 658 pn_free(pp); 659 return (error); 660 } 661 662 /* 663 * Traverse a mount point. Routine accepts a vnode pointer as a reference 664 * parameter and performs the indirection, releasing the original vnode. 665 */ 666 int 667 traverse(vnode_t **cvpp) 668 { 669 int error = 0; 670 vnode_t *cvp; 671 vnode_t *tvp; 672 vfs_t *vfsp; 673 674 cvp = *cvpp; 675 676 /* 677 * If this vnode is mounted on, then we transparently indirect 678 * to the vnode which is the root of the mounted file system. 679 * Before we do this we must check that an unmount is not in 680 * progress on this vnode. 681 */ 682 683 for (;;) { 684 /* 685 * Try to read lock the vnode. If this fails because 686 * the vnode is already write locked, then check to 687 * see whether it is the current thread which locked 688 * the vnode. If it is not, then read lock the vnode 689 * by waiting to acquire the lock. 690 * 691 * The code path in domount() is an example of support 692 * which needs to look up two pathnames and locks one 693 * of them in between the two lookups. 694 */ 695 error = vn_vfsrlock(cvp); 696 if (error) { 697 if (!vn_vfswlock_held(cvp)) 698 error = vn_vfsrlock_wait(cvp); 699 if (error != 0) { 700 /* 701 * lookuppn() expects a held vnode to be 702 * returned because it promptly calls 703 * VN_RELE after the error return 704 */ 705 *cvpp = cvp; 706 return (error); 707 } 708 } 709 710 /* 711 * Reached the end of the mount chain? 712 */ 713 vfsp = vn_mountedvfs(cvp); 714 if (vfsp == NULL) { 715 vn_vfsunlock(cvp); 716 break; 717 } 718 719 /* 720 * The read lock must be held across the call to VFS_ROOT() to 721 * prevent a concurrent unmount from destroying the vfs. 722 */ 723 error = VFS_ROOT(vfsp, &tvp); 724 vn_vfsunlock(cvp); 725 726 if (error) 727 break; 728 729 VN_RELE(cvp); 730 731 cvp = tvp; 732 } 733 734 *cvpp = cvp; 735 return (error); 736 } 737 738 /* 739 * Return the lowermost vnode if this is a mountpoint. 740 */ 741 static vnode_t * 742 vn_under(vnode_t *vp) 743 { 744 vnode_t *uvp; 745 vfs_t *vfsp; 746 747 while (vp->v_flag & VROOT) { 748 749 vfsp = vp->v_vfsp; 750 vfs_rlock_wait(vfsp); 751 if ((uvp = vfsp->vfs_vnodecovered) == NULL || 752 (vfsp->vfs_flag & VFS_UNMOUNTED)) { 753 vfs_unlock(vfsp); 754 break; 755 } 756 VN_HOLD(uvp); 757 vfs_unlock(vfsp); 758 VN_RELE(vp); 759 vp = uvp; 760 } 761 762 return (vp); 763 } 764 765 static int 766 vnode_match(vnode_t *v1, vnode_t *v2, cred_t *cr) 767 { 768 vattr_t v1attr, v2attr; 769 770 /* 771 * If we have a device file, check to see if is a cloned open of the 772 * same device. For self-cloning devices, the major numbers will match. 773 * For devices cloned through the 'clone' driver, the minor number of 774 * the source device will be the same as the major number of the cloned 775 * device. 776 */ 777 if ((v1->v_type == VCHR || v1->v_type == VBLK) && 778 v1->v_type == v2->v_type) { 779 if ((spec_is_selfclone(v1) || spec_is_selfclone(v2)) && 780 getmajor(v1->v_rdev) == getmajor(v2->v_rdev)) 781 return (1); 782 783 if (spec_is_clone(v1) && 784 getmajor(v1->v_rdev) == getminor(v2->v_rdev)) 785 return (1); 786 787 if (spec_is_clone(v2) && 788 getmajor(v2->v_rdev) == getminor(v1->v_rdev)) 789 return (1); 790 } 791 792 v1attr.va_mask = v2attr.va_mask = AT_TYPE; 793 794 /* 795 * This check for symbolic links handles the pseudo-symlinks in procfs. 796 * These particular links have v_type of VDIR, but the attributes have a 797 * type of VLNK. We need to avoid these links because otherwise if we 798 * are currently in '/proc/self/fd', then '/proc/self/cwd' will compare 799 * as the same vnode. 800 */ 801 if (VOP_GETATTR(v1, &v1attr, 0, cr, NULL) != 0 || 802 VOP_GETATTR(v2, &v2attr, 0, cr, NULL) != 0 || 803 v1attr.va_type == VLNK || v2attr.va_type == VLNK) 804 return (0); 805 806 v1attr.va_mask = v2attr.va_mask = AT_TYPE | AT_FSID | AT_NODEID; 807 808 if (VOP_GETATTR(v1, &v1attr, ATTR_REAL, cr, NULL) != 0 || 809 VOP_GETATTR(v2, &v2attr, ATTR_REAL, cr, NULL) != 0) 810 return (0); 811 812 return (v1attr.va_fsid == v2attr.va_fsid && 813 v1attr.va_nodeid == v2attr.va_nodeid); 814 } 815 816 817 /* 818 * Find the entry in the directory corresponding to the target vnode. 819 */ 820 int 821 dirfindvp(vnode_t *vrootp, vnode_t *dvp, vnode_t *tvp, cred_t *cr, char *dbuf, 822 size_t dlen, dirent64_t **rdp) 823 { 824 size_t dbuflen; 825 struct iovec iov; 826 struct uio uio; 827 int error; 828 int eof; 829 vnode_t *cmpvp; 830 struct dirent64 *dp; 831 pathname_t pnp; 832 833 ASSERT(dvp->v_type == VDIR); 834 835 /* 836 * This is necessary because of the strange semantics of VOP_LOOKUP(). 837 */ 838 bzero(&pnp, sizeof (pnp)); 839 840 eof = 0; 841 842 uio.uio_iov = &iov; 843 uio.uio_iovcnt = 1; 844 uio.uio_segflg = UIO_SYSSPACE; 845 uio.uio_fmode = 0; 846 uio.uio_extflg = UIO_COPY_CACHED; 847 uio.uio_loffset = 0; 848 849 if ((error = VOP_ACCESS(dvp, VREAD, 0, cr, NULL)) != 0) 850 return (error); 851 852 while (!eof) { 853 uio.uio_resid = dlen; 854 iov.iov_base = dbuf; 855 iov.iov_len = dlen; 856 857 (void) VOP_RWLOCK(dvp, V_WRITELOCK_FALSE, NULL); 858 error = VOP_READDIR(dvp, &uio, cr, &eof, NULL, 0); 859 VOP_RWUNLOCK(dvp, V_WRITELOCK_FALSE, NULL); 860 861 dbuflen = dlen - uio.uio_resid; 862 863 if (error || dbuflen == 0) 864 break; 865 866 dp = (dirent64_t *)dbuf; 867 while ((intptr_t)dp < (intptr_t)dbuf + dbuflen) { 868 /* 869 * Ignore '.' and '..' entries 870 */ 871 if (strcmp(dp->d_name, ".") == 0 || 872 strcmp(dp->d_name, "..") == 0) { 873 dp = (dirent64_t *)((intptr_t)dp + 874 dp->d_reclen); 875 continue; 876 } 877 878 error = VOP_LOOKUP(dvp, dp->d_name, &cmpvp, &pnp, 0, 879 vrootp, cr, NULL, NULL, NULL); 880 881 /* 882 * We only want to bail out if there was an error other 883 * than ENOENT. Otherwise, it could be that someone 884 * just removed an entry since the readdir() call, and 885 * the entry we want is further on in the directory. 886 */ 887 if (error == 0) { 888 if (vnode_match(tvp, cmpvp, cr)) { 889 VN_RELE(cmpvp); 890 *rdp = dp; 891 return (0); 892 } 893 894 VN_RELE(cmpvp); 895 } else if (error != ENOENT) { 896 return (error); 897 } 898 899 dp = (dirent64_t *)((intptr_t)dp + dp->d_reclen); 900 } 901 } 902 903 /* 904 * Something strange has happened, this directory does not contain the 905 * specified vnode. This should never happen in the normal case, since 906 * we ensured that dvp is the parent of vp. This is possible in some 907 * rare conditions (races and the special .zfs directory). 908 */ 909 if (error == 0) { 910 error = VOP_LOOKUP(dvp, ".zfs", &cmpvp, &pnp, 0, vrootp, cr, 911 NULL, NULL, NULL); 912 if (error == 0) { 913 if (vnode_match(tvp, cmpvp, cr)) { 914 (void) strcpy(dp->d_name, ".zfs"); 915 dp->d_reclen = strlen(".zfs"); 916 dp->d_off = 2; 917 dp->d_ino = 1; 918 *rdp = dp; 919 } else { 920 error = ENOENT; 921 } 922 VN_RELE(cmpvp); 923 } 924 } 925 926 return (error); 927 } 928 929 /* 930 * Given a global path (from rootdir), and a vnode that is the current root, 931 * return the portion of the path that is beneath the current root or NULL on 932 * failure. The path MUST be a resolved path (no '..' entries or symlinks), 933 * otherwise this function will fail. 934 */ 935 static char * 936 localpath(char *path, struct vnode *vrootp, cred_t *cr) 937 { 938 vnode_t *vp; 939 vnode_t *cvp; 940 char component[MAXNAMELEN]; 941 char *ret = NULL; 942 pathname_t pn; 943 944 /* 945 * We use vn_compare() instead of VN_CMP() in order to detect lofs 946 * mounts and stacked vnodes. 947 */ 948 if (vn_compare(vrootp, rootdir)) 949 return (path); 950 951 if (pn_get(path, UIO_SYSSPACE, &pn) != 0) 952 return (NULL); 953 954 vp = rootdir; 955 VN_HOLD(vp); 956 957 if (vn_ismntpt(vp) && traverse(&vp) != 0) { 958 VN_RELE(vp); 959 pn_free(&pn); 960 return (NULL); 961 } 962 963 while (pn_pathleft(&pn)) { 964 pn_skipslash(&pn); 965 966 if (pn_getcomponent(&pn, component) != 0) 967 break; 968 969 if (VOP_LOOKUP(vp, component, &cvp, &pn, 0, rootdir, cr, 970 NULL, NULL, NULL) != 0) 971 break; 972 VN_RELE(vp); 973 vp = cvp; 974 975 if (vn_ismntpt(vp) && traverse(&vp) != 0) 976 break; 977 978 if (vn_compare(vp, vrootp)) { 979 ret = path + (pn.pn_path - pn.pn_buf); 980 break; 981 } 982 } 983 984 VN_RELE(vp); 985 pn_free(&pn); 986 987 return (ret); 988 } 989 990 /* 991 * Given a directory, return the full, resolved path. This looks up "..", 992 * searches for the given vnode in the parent, appends the component, etc. It 993 * is used to implement vnodetopath() and getcwd() when the cached path fails. 994 */ 995 static int 996 dirtopath(vnode_t *vrootp, vnode_t *vp, char *buf, size_t buflen, int flags, 997 cred_t *cr) 998 { 999 pathname_t pn, rpn, emptypn; 1000 vnode_t *cmpvp, *pvp = NULL; 1001 vnode_t *startvp = vp; 1002 int err = 0, vprivs; 1003 size_t complen; 1004 char *dbuf; 1005 dirent64_t *dp; 1006 char *bufloc; 1007 size_t dlen = DIRENT64_RECLEN(MAXPATHLEN); 1008 refstr_t *mntpt; 1009 1010 /* Operation only allowed on directories */ 1011 ASSERT(vp->v_type == VDIR); 1012 1013 /* We must have at least enough space for "/" */ 1014 if (buflen < 2) 1015 return (ENAMETOOLONG); 1016 1017 /* Start at end of string with terminating null */ 1018 bufloc = &buf[buflen - 1]; 1019 *bufloc = '\0'; 1020 1021 pn_alloc(&pn); 1022 pn_alloc(&rpn); 1023 dbuf = kmem_alloc(dlen, KM_SLEEP); 1024 bzero(&emptypn, sizeof (emptypn)); 1025 1026 /* 1027 * Begin with an additional reference on vp. This will be decremented 1028 * during the loop. 1029 */ 1030 VN_HOLD(vp); 1031 1032 for (;;) { 1033 /* 1034 * Return if we've reached the root. If the buffer is empty, 1035 * return '/'. We explicitly don't use vn_compare(), since it 1036 * compares the real vnodes. A lofs mount of '/' would produce 1037 * incorrect results otherwise. 1038 */ 1039 if (VN_CMP(vrootp, vp)) { 1040 if (*bufloc == '\0') 1041 *--bufloc = '/'; 1042 break; 1043 } 1044 1045 /* 1046 * If we've reached the VFS root, something has gone wrong. We 1047 * should have reached the root in the above check. The only 1048 * explantation is that 'vp' is not contained withing the given 1049 * root, in which case we return EPERM. 1050 */ 1051 if (VN_CMP(rootdir, vp)) { 1052 err = EPERM; 1053 goto out; 1054 } 1055 1056 /* 1057 * Shortcut: see if this vnode is a mountpoint. If so, 1058 * grab the path information from the vfs_t. 1059 */ 1060 if (vp->v_flag & VROOT) { 1061 1062 mntpt = vfs_getmntpoint(vp->v_vfsp); 1063 if ((err = pn_set(&pn, (char *)refstr_value(mntpt))) 1064 == 0) { 1065 refstr_rele(mntpt); 1066 rpn.pn_path = rpn.pn_buf; 1067 1068 /* 1069 * Ensure the mountpoint still exists. 1070 */ 1071 VN_HOLD(vrootp); 1072 if (vrootp != rootdir) 1073 VN_HOLD(vrootp); 1074 if (lookuppnvp(&pn, &rpn, flags, NULL, 1075 &cmpvp, vrootp, vrootp, cr) == 0) { 1076 1077 if (VN_CMP(vp, cmpvp)) { 1078 VN_RELE(cmpvp); 1079 1080 complen = strlen(rpn.pn_path); 1081 bufloc -= complen; 1082 if (bufloc < buf) { 1083 err = ERANGE; 1084 goto out; 1085 } 1086 bcopy(rpn.pn_path, bufloc, 1087 complen); 1088 break; 1089 } else { 1090 VN_RELE(cmpvp); 1091 } 1092 } 1093 } else { 1094 refstr_rele(mntpt); 1095 } 1096 } 1097 1098 /* 1099 * Shortcut: see if this vnode has correct v_path. If so, 1100 * we have the work done. 1101 */ 1102 mutex_enter(&vp->v_lock); 1103 if (vp->v_path != NULL) { 1104 1105 if ((err = pn_set(&pn, vp->v_path)) == 0) { 1106 mutex_exit(&vp->v_lock); 1107 rpn.pn_path = rpn.pn_buf; 1108 1109 /* 1110 * Ensure the v_path pointing to correct vnode 1111 */ 1112 VN_HOLD(vrootp); 1113 if (vrootp != rootdir) 1114 VN_HOLD(vrootp); 1115 if (lookuppnvp(&pn, &rpn, flags, NULL, 1116 &cmpvp, vrootp, vrootp, cr) == 0) { 1117 1118 if (VN_CMP(vp, cmpvp)) { 1119 VN_RELE(cmpvp); 1120 1121 complen = strlen(rpn.pn_path); 1122 bufloc -= complen; 1123 if (bufloc < buf) { 1124 err = ERANGE; 1125 goto out; 1126 } 1127 bcopy(rpn.pn_path, bufloc, 1128 complen); 1129 break; 1130 } else { 1131 VN_RELE(cmpvp); 1132 } 1133 } 1134 } else { 1135 mutex_exit(&vp->v_lock); 1136 } 1137 } else { 1138 mutex_exit(&vp->v_lock); 1139 } 1140 1141 /* 1142 * Shortcuts failed, search for this vnode in its parent. If 1143 * this is a mountpoint, then get the vnode underneath. 1144 */ 1145 if (vp->v_flag & VROOT) 1146 vp = vn_under(vp); 1147 if ((err = VOP_LOOKUP(vp, "..", &pvp, &emptypn, 0, vrootp, cr, 1148 NULL, NULL, NULL)) != 0) 1149 goto out; 1150 1151 /* 1152 * With extended attributes, it's possible for a directory to 1153 * have a parent that is a regular file. Check for that here. 1154 */ 1155 if (pvp->v_type != VDIR) { 1156 err = ENOTDIR; 1157 goto out; 1158 } 1159 1160 /* 1161 * If this is true, something strange has happened. This is 1162 * only true if we are the root of a filesystem, which should 1163 * have been caught by the check above. 1164 */ 1165 if (VN_CMP(pvp, vp)) { 1166 err = ENOENT; 1167 goto out; 1168 } 1169 1170 /* 1171 * Check if we have read and search privilege so, that 1172 * we can lookup the path in the directory 1173 */ 1174 vprivs = (flags & LOOKUP_CHECKREAD) ? VREAD | VEXEC : VEXEC; 1175 if ((err = VOP_ACCESS(pvp, vprivs, 0, cr, NULL)) != 0) { 1176 goto out; 1177 } 1178 1179 /* 1180 * Search the parent directory for the entry corresponding to 1181 * this vnode. 1182 */ 1183 if ((err = dirfindvp(vrootp, pvp, vp, cr, dbuf, dlen, &dp)) 1184 != 0) 1185 goto out; 1186 complen = strlen(dp->d_name); 1187 bufloc -= complen; 1188 if (bufloc <= buf) { 1189 err = ENAMETOOLONG; 1190 goto out; 1191 } 1192 bcopy(dp->d_name, bufloc, complen); 1193 1194 /* Prepend a slash to the current path. */ 1195 *--bufloc = '/'; 1196 1197 /* And continue with the next component */ 1198 VN_RELE(vp); 1199 vp = pvp; 1200 pvp = NULL; 1201 } 1202 1203 /* 1204 * Place the path at the beginning of the buffer. 1205 */ 1206 if (bufloc != buf) 1207 ovbcopy(bufloc, buf, buflen - (bufloc - buf)); 1208 1209 out: 1210 /* 1211 * If the error was ESTALE and the current directory to look in 1212 * was the root for this lookup, the root for a mounted file 1213 * system, or the starting directory for lookups, then 1214 * return ENOENT instead of ESTALE. In this case, no recovery 1215 * is possible by the higher level. If ESTALE was returned for 1216 * some intermediate directory along the path, then recovery 1217 * is potentially possible and retrying from the higher level 1218 * will either correct the situation by purging stale cache 1219 * entries or eventually get back to the point where no recovery 1220 * is possible. 1221 */ 1222 if (err == ESTALE && 1223 (VN_CMP(vp, vrootp) || (vp->v_flag & VROOT) || vp == startvp)) 1224 err = ENOENT; 1225 1226 kmem_free(dbuf, dlen); 1227 VN_RELE(vp); 1228 if (pvp) 1229 VN_RELE(pvp); 1230 pn_free(&pn); 1231 pn_free(&rpn); 1232 1233 return (err); 1234 } 1235 1236 /* 1237 * The additional flag, LOOKUP_CHECKREAD, is used to enforce artificial 1238 * constraints in order to be standards compliant. For example, if we have 1239 * the cached path of '/foo/bar', and '/foo' has permissions 100 (execute 1240 * only), then we can legitimately look up the path to the current working 1241 * directory without needing read permission. Existing standards tests, 1242 * however, assume that we are determining the path by repeatedly looking up 1243 * "..". We need to keep this behavior in order to maintain backwards 1244 * compatibility. 1245 */ 1246 static int 1247 vnodetopath_common(vnode_t *vrootp, vnode_t *vp, char *buf, size_t buflen, 1248 cred_t *cr, int flags) 1249 { 1250 pathname_t pn, rpn; 1251 int ret; 1252 vnode_t *compvp, *realvp; 1253 proc_t *p = curproc; 1254 int doclose = 0; 1255 1256 /* 1257 * If vrootp is NULL, get the root for curproc. Callers with any other 1258 * requirements should pass in a different vrootp. 1259 */ 1260 if (vrootp == NULL) { 1261 mutex_enter(&p->p_lock); 1262 if ((vrootp = PTOU(p)->u_rdir) == NULL) 1263 vrootp = rootdir; 1264 VN_HOLD(vrootp); 1265 mutex_exit(&p->p_lock); 1266 } else { 1267 VN_HOLD(vrootp); 1268 } 1269 1270 /* 1271 * This is to get around an annoying artifact of the /proc filesystem, 1272 * which is the behavior of {cwd/root}. Trying to resolve this path 1273 * will result in /proc/pid/cwd instead of whatever the real working 1274 * directory is. We can't rely on VOP_REALVP(), since that will break 1275 * lofs. The only difference between procfs and lofs is that opening 1276 * the file will return the underling vnode in the case of procfs. 1277 */ 1278 if (vp->v_type == VDIR && VOP_REALVP(vp, &realvp, NULL) == 0 && 1279 realvp != vp) { 1280 VN_HOLD(vp); 1281 if (VOP_OPEN(&vp, FREAD, cr, NULL) == 0) 1282 doclose = 1; 1283 else 1284 VN_RELE(vp); 1285 } 1286 1287 pn_alloc(&pn); 1288 1289 /* 1290 * Check to see if we have a cached path in the vnode. 1291 */ 1292 mutex_enter(&vp->v_lock); 1293 if (vp->v_path != NULL) { 1294 (void) pn_set(&pn, vp->v_path); 1295 mutex_exit(&vp->v_lock); 1296 1297 pn_alloc(&rpn); 1298 1299 /* We should only cache absolute paths */ 1300 ASSERT(pn.pn_buf[0] == '/'); 1301 1302 /* 1303 * If we are in a zone or a chroot environment, then we have to 1304 * take additional steps, since the path to the root might not 1305 * be readable with the current credentials, even though the 1306 * process can legitmately access the file. In this case, we 1307 * do the following: 1308 * 1309 * lookuppnvp() with all privileges to get the resolved path. 1310 * call localpath() to get the local portion of the path, and 1311 * continue as normal. 1312 * 1313 * If the the conversion to a local path fails, then we continue 1314 * as normal. This is a heuristic to make process object file 1315 * paths available from within a zone. Because lofs doesn't 1316 * support page operations, the vnode stored in the seg_t is 1317 * actually the underlying real vnode, not the lofs node itself. 1318 * Most of the time, the lofs path is the same as the underlying 1319 * vnode (for example, /usr/lib/libc.so.1). 1320 */ 1321 if (vrootp != rootdir) { 1322 char *local = NULL; 1323 VN_HOLD(rootdir); 1324 if (lookuppnvp(&pn, &rpn, FOLLOW, 1325 NULL, &compvp, rootdir, rootdir, kcred) == 0) { 1326 local = localpath(rpn.pn_path, vrootp, 1327 kcred); 1328 VN_RELE(compvp); 1329 } 1330 1331 /* 1332 * The original pn was changed through lookuppnvp(). 1333 * Set it to local for next validation attempt. 1334 */ 1335 if (local) { 1336 (void) pn_set(&pn, local); 1337 } else { 1338 goto notcached; 1339 } 1340 } 1341 1342 /* 1343 * We should have a local path at this point, so start the 1344 * search from the root of the current process. 1345 */ 1346 VN_HOLD(vrootp); 1347 if (vrootp != rootdir) 1348 VN_HOLD(vrootp); 1349 ret = lookuppnvp(&pn, &rpn, FOLLOW | flags, NULL, 1350 &compvp, vrootp, vrootp, cr); 1351 if (ret == 0) { 1352 /* 1353 * Check to see if the returned vnode is the same as 1354 * the one we expect. If not, give up. 1355 */ 1356 if (!vn_compare(vp, compvp) && 1357 !vnode_match(vp, compvp, cr)) { 1358 VN_RELE(compvp); 1359 goto notcached; 1360 } 1361 1362 VN_RELE(compvp); 1363 1364 /* 1365 * Return the result. 1366 */ 1367 if (buflen <= rpn.pn_pathlen) 1368 goto notcached; 1369 1370 bcopy(rpn.pn_path, buf, rpn.pn_pathlen + 1); 1371 pn_free(&pn); 1372 pn_free(&rpn); 1373 VN_RELE(vrootp); 1374 if (doclose) { 1375 (void) VOP_CLOSE(vp, FREAD, 1, 0, cr, NULL); 1376 VN_RELE(vp); 1377 } 1378 return (0); 1379 } 1380 1381 notcached: 1382 pn_free(&rpn); 1383 } else { 1384 mutex_exit(&vp->v_lock); 1385 } 1386 1387 pn_free(&pn); 1388 1389 if (vp->v_type != VDIR) { 1390 ret = ENOENT; 1391 } else { 1392 ret = dirtopath(vrootp, vp, buf, buflen, flags, cr); 1393 } 1394 1395 VN_RELE(vrootp); 1396 if (doclose) { 1397 (void) VOP_CLOSE(vp, FREAD, 1, 0, cr, NULL); 1398 VN_RELE(vp); 1399 } 1400 1401 return (ret); 1402 } 1403 1404 int 1405 vnodetopath(vnode_t *vrootp, vnode_t *vp, char *buf, size_t buflen, cred_t *cr) 1406 { 1407 return (vnodetopath_common(vrootp, vp, buf, buflen, cr, 0)); 1408 } 1409 1410 int 1411 dogetcwd(char *buf, size_t buflen) 1412 { 1413 int ret; 1414 vnode_t *vp; 1415 vnode_t *compvp; 1416 refstr_t *cwd, *oldcwd; 1417 const char *value; 1418 pathname_t rpnp, pnp; 1419 proc_t *p = curproc; 1420 1421 /* 1422 * Check to see if there is a cached version of the cwd. If so, lookup 1423 * the cached value and make sure it is the same vnode. 1424 */ 1425 mutex_enter(&p->p_lock); 1426 if ((cwd = PTOU(p)->u_cwd) != NULL) 1427 refstr_hold(cwd); 1428 vp = PTOU(p)->u_cdir; 1429 VN_HOLD(vp); 1430 mutex_exit(&p->p_lock); 1431 1432 /* 1433 * Make sure we have permission to access the current directory. 1434 */ 1435 if ((ret = VOP_ACCESS(vp, VEXEC, 0, CRED(), NULL)) != 0) { 1436 if (cwd != NULL) 1437 refstr_rele(cwd); 1438 VN_RELE(vp); 1439 return (ret); 1440 } 1441 1442 if (cwd) { 1443 value = refstr_value(cwd); 1444 if ((ret = pn_get((char *)value, UIO_SYSSPACE, &pnp)) != 0) { 1445 refstr_rele(cwd); 1446 VN_RELE(vp); 1447 return (ret); 1448 } 1449 1450 pn_alloc(&rpnp); 1451 1452 if (lookuppn(&pnp, &rpnp, NO_FOLLOW, NULL, &compvp) == 0) { 1453 1454 if (VN_CMP(vp, compvp) && 1455 strcmp(value, rpnp.pn_path) == 0) { 1456 VN_RELE(compvp); 1457 VN_RELE(vp); 1458 pn_free(&pnp); 1459 pn_free(&rpnp); 1460 if (strlen(value) + 1 > buflen) { 1461 refstr_rele(cwd); 1462 return (ENAMETOOLONG); 1463 } 1464 bcopy(value, buf, strlen(value) + 1); 1465 refstr_rele(cwd); 1466 return (0); 1467 } 1468 1469 VN_RELE(compvp); 1470 } 1471 1472 pn_free(&rpnp); 1473 pn_free(&pnp); 1474 1475 refstr_rele(cwd); 1476 } 1477 1478 ret = vnodetopath_common(NULL, vp, buf, buflen, CRED(), 1479 LOOKUP_CHECKREAD); 1480 1481 VN_RELE(vp); 1482 1483 /* 1484 * Store the new cwd and replace the existing cached copy. 1485 */ 1486 if (ret == 0) 1487 cwd = refstr_alloc(buf); 1488 else 1489 cwd = NULL; 1490 1491 mutex_enter(&p->p_lock); 1492 oldcwd = PTOU(p)->u_cwd; 1493 PTOU(p)->u_cwd = cwd; 1494 mutex_exit(&p->p_lock); 1495 1496 if (oldcwd) 1497 refstr_rele(oldcwd); 1498 1499 return (ret); 1500 } 1501