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 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 22 /* All Rights Reserved */ 23 24 25 /* 26 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. 27 * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 28 * Copyright 2015 Joyent, Inc. 29 */ 30 31 /* 32 * Generic vnode operations. 33 */ 34 #include <sys/types.h> 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/errno.h> 38 #include <sys/fcntl.h> 39 #include <sys/flock.h> 40 #include <sys/statvfs.h> 41 #include <sys/vfs.h> 42 #include <sys/vnode.h> 43 #include <sys/proc.h> 44 #include <sys/user.h> 45 #include <sys/unistd.h> 46 #include <sys/cred.h> 47 #include <sys/poll.h> 48 #include <sys/debug.h> 49 #include <sys/cmn_err.h> 50 #include <sys/stream.h> 51 #include <fs/fs_subr.h> 52 #include <fs/fs_reparse.h> 53 #include <sys/door.h> 54 #include <sys/acl.h> 55 #include <sys/share.h> 56 #include <sys/file.h> 57 #include <sys/kmem.h> 58 #include <sys/file.h> 59 #include <sys/nbmlock.h> 60 #include <acl/acl_common.h> 61 #include <sys/pathname.h> 62 63 static callb_cpr_t *frlock_serialize_blocked(flk_cb_when_t, void *); 64 65 /* 66 * Tunable to limit the number of retry to recover from STALE error. 67 */ 68 int fs_estale_retry = 5; 69 70 /* 71 * supports for reparse point door upcall 72 */ 73 static door_handle_t reparsed_door; 74 static kmutex_t reparsed_door_lock; 75 76 /* 77 * The associated operation is not supported by the file system. 78 */ 79 int 80 fs_nosys() 81 { 82 return (ENOSYS); 83 } 84 85 /* 86 * The associated operation is invalid (on this vnode). 87 */ 88 int 89 fs_inval() 90 { 91 return (EINVAL); 92 } 93 94 /* 95 * The associated operation is valid only for directories. 96 */ 97 int 98 fs_notdir() 99 { 100 return (ENOTDIR); 101 } 102 103 /* 104 * Free the file system specific resources. For the file systems that 105 * do not support the forced unmount, it will be a nop function. 106 */ 107 108 /*ARGSUSED*/ 109 void 110 fs_freevfs(vfs_t *vfsp) 111 { 112 } 113 114 /* ARGSUSED */ 115 int 116 fs_nosys_map(struct vnode *vp, 117 offset_t off, 118 struct as *as, 119 caddr_t *addrp, 120 size_t len, 121 uchar_t prot, 122 uchar_t maxprot, 123 uint_t flags, 124 struct cred *cr, 125 caller_context_t *ct) 126 { 127 return (ENOSYS); 128 } 129 130 /* ARGSUSED */ 131 int 132 fs_nosys_addmap(struct vnode *vp, 133 offset_t off, 134 struct as *as, 135 caddr_t addr, 136 size_t len, 137 uchar_t prot, 138 uchar_t maxprot, 139 uint_t flags, 140 struct cred *cr, 141 caller_context_t *ct) 142 { 143 return (ENOSYS); 144 } 145 146 /* ARGSUSED */ 147 int 148 fs_nosys_poll(vnode_t *vp, 149 register short events, 150 int anyyet, 151 register short *reventsp, 152 struct pollhead **phpp, 153 caller_context_t *ct) 154 { 155 return (ENOSYS); 156 } 157 158 159 /* 160 * The file system has nothing to sync to disk. However, the 161 * VFS_SYNC operation must not fail. 162 */ 163 /* ARGSUSED */ 164 int 165 fs_sync(struct vfs *vfspp, short flag, cred_t *cr) 166 { 167 return (0); 168 } 169 170 /* 171 * Does nothing but VOP_FSYNC must not fail. 172 */ 173 /* ARGSUSED */ 174 int 175 fs_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct) 176 { 177 return (0); 178 } 179 180 /* 181 * Does nothing but VOP_PUTPAGE must not fail. 182 */ 183 /* ARGSUSED */ 184 int 185 fs_putpage(vnode_t *vp, offset_t off, size_t len, int flags, cred_t *cr, 186 caller_context_t *ctp) 187 { 188 return (0); 189 } 190 191 /* 192 * Does nothing but VOP_IOCTL must not fail. 193 */ 194 /* ARGSUSED */ 195 int 196 fs_ioctl(vnode_t *vp, int com, intptr_t data, int flag, cred_t *cred, 197 int *rvalp) 198 { 199 return (0); 200 } 201 202 /* 203 * Read/write lock/unlock. Does nothing. 204 */ 205 /* ARGSUSED */ 206 int 207 fs_rwlock(vnode_t *vp, int write_lock, caller_context_t *ctp) 208 { 209 return (-1); 210 } 211 212 /* ARGSUSED */ 213 void 214 fs_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ctp) 215 { 216 } 217 218 /* 219 * Compare two vnodes. 220 */ 221 /*ARGSUSED2*/ 222 int 223 fs_cmp(vnode_t *vp1, vnode_t *vp2, caller_context_t *ct) 224 { 225 return (vp1 == vp2); 226 } 227 228 /* 229 * No-op seek operation. 230 */ 231 /* ARGSUSED */ 232 int 233 fs_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct) 234 { 235 return ((*noffp < 0 || *noffp > MAXOFFSET_T) ? EINVAL : 0); 236 } 237 238 /* 239 * File and record locking. 240 */ 241 /* ARGSUSED */ 242 int 243 fs_frlock(register vnode_t *vp, int cmd, struct flock64 *bfp, int flag, 244 offset_t offset, flk_callback_t *flk_cbp, cred_t *cr, 245 caller_context_t *ct) 246 { 247 int frcmd; 248 int nlmid; 249 int error = 0; 250 boolean_t skip_lock = B_FALSE; 251 flk_callback_t serialize_callback; 252 int serialize = 0; 253 v_mode_t mode; 254 255 switch (cmd) { 256 257 case F_GETLK: 258 case F_O_GETLK: 259 if (flag & F_REMOTELOCK) { 260 frcmd = RCMDLCK; 261 } else if (flag & F_PXFSLOCK) { 262 frcmd = PCMDLCK; 263 } else { 264 frcmd = 0; 265 bfp->l_pid = ttoproc(curthread)->p_pid; 266 bfp->l_sysid = 0; 267 } 268 break; 269 270 case F_OFD_GETLK: 271 /* 272 * TBD we do not support remote OFD locks at this time. 273 */ 274 if (flag & (F_REMOTELOCK | F_PXFSLOCK)) { 275 error = EINVAL; 276 goto done; 277 } 278 skip_lock = B_TRUE; 279 break; 280 281 case F_SETLK_NBMAND: 282 /* 283 * Are NBMAND locks allowed on this file? 284 */ 285 if (!vp->v_vfsp || 286 !(vp->v_vfsp->vfs_flag & VFS_NBMAND)) { 287 error = EINVAL; 288 goto done; 289 } 290 if (vp->v_type != VREG) { 291 error = EINVAL; 292 goto done; 293 } 294 /*FALLTHROUGH*/ 295 296 case F_SETLK: 297 if (flag & F_REMOTELOCK) { 298 frcmd = SETFLCK|RCMDLCK; 299 } else if (flag & F_PXFSLOCK) { 300 frcmd = SETFLCK|PCMDLCK; 301 } else { 302 frcmd = SETFLCK; 303 bfp->l_pid = ttoproc(curthread)->p_pid; 304 bfp->l_sysid = 0; 305 } 306 if (cmd == F_SETLK_NBMAND && 307 (bfp->l_type == F_RDLCK || bfp->l_type == F_WRLCK)) { 308 frcmd |= NBMLCK; 309 } 310 311 if (nbl_need_check(vp)) { 312 nbl_start_crit(vp, RW_WRITER); 313 serialize = 1; 314 if (frcmd & NBMLCK) { 315 mode = (bfp->l_type == F_RDLCK) ? 316 V_READ : V_RDANDWR; 317 if (vn_is_mapped(vp, mode)) { 318 error = EAGAIN; 319 goto done; 320 } 321 } 322 } 323 break; 324 325 case F_SETLKW: 326 if (flag & F_REMOTELOCK) { 327 frcmd = SETFLCK|SLPFLCK|RCMDLCK; 328 } else if (flag & F_PXFSLOCK) { 329 frcmd = SETFLCK|SLPFLCK|PCMDLCK; 330 } else { 331 frcmd = SETFLCK|SLPFLCK; 332 bfp->l_pid = ttoproc(curthread)->p_pid; 333 bfp->l_sysid = 0; 334 } 335 336 if (nbl_need_check(vp)) { 337 nbl_start_crit(vp, RW_WRITER); 338 serialize = 1; 339 } 340 break; 341 342 case F_OFD_SETLK: 343 case F_OFD_SETLKW: 344 case F_FLOCK: 345 case F_FLOCKW: 346 /* 347 * TBD we do not support remote OFD locks at this time. 348 */ 349 if (flag & (F_REMOTELOCK | F_PXFSLOCK)) { 350 error = EINVAL; 351 goto done; 352 } 353 skip_lock = B_TRUE; 354 break; 355 356 case F_HASREMOTELOCKS: 357 nlmid = GETNLMID(bfp->l_sysid); 358 if (nlmid != 0) { /* booted as a cluster */ 359 l_has_rmt(bfp) = 360 cl_flk_has_remote_locks_for_nlmid(vp, nlmid); 361 } else { /* not booted as a cluster */ 362 l_has_rmt(bfp) = flk_has_remote_locks(vp); 363 } 364 365 goto done; 366 367 default: 368 error = EINVAL; 369 goto done; 370 } 371 372 /* 373 * If this is a blocking lock request and we're serializing lock 374 * requests, modify the callback list to leave the critical region 375 * while we're waiting for the lock. 376 */ 377 378 if (serialize && (frcmd & SLPFLCK) != 0) { 379 flk_add_callback(&serialize_callback, 380 frlock_serialize_blocked, vp, flk_cbp); 381 flk_cbp = &serialize_callback; 382 } 383 384 if (!skip_lock) 385 error = reclock(vp, bfp, frcmd, flag, offset, flk_cbp); 386 387 done: 388 if (serialize) 389 nbl_end_crit(vp); 390 391 return (error); 392 } 393 394 /* 395 * Callback when a lock request blocks and we are serializing requests. If 396 * before sleeping, leave the critical region. If after wakeup, reenter 397 * the critical region. 398 */ 399 400 static callb_cpr_t * 401 frlock_serialize_blocked(flk_cb_when_t when, void *infop) 402 { 403 vnode_t *vp = (vnode_t *)infop; 404 405 if (when == FLK_BEFORE_SLEEP) 406 nbl_end_crit(vp); 407 else { 408 nbl_start_crit(vp, RW_WRITER); 409 } 410 411 return (NULL); 412 } 413 414 /* 415 * Allow any flags. 416 */ 417 /* ARGSUSED */ 418 int 419 fs_setfl( 420 vnode_t *vp, 421 int oflags, 422 int nflags, 423 cred_t *cr, 424 caller_context_t *ct) 425 { 426 return (0); 427 } 428 429 /* 430 * Return the answer requested to poll() for non-device files. 431 * Only POLLIN, POLLRDNORM, and POLLOUT are recognized. 432 */ 433 struct pollhead fs_pollhd; 434 435 /* ARGSUSED */ 436 int 437 fs_poll(vnode_t *vp, 438 register short events, 439 int anyyet, 440 register short *reventsp, 441 struct pollhead **phpp, 442 caller_context_t *ct) 443 { 444 *reventsp = 0; 445 if (events & POLLIN) 446 *reventsp |= POLLIN; 447 if (events & POLLRDNORM) 448 *reventsp |= POLLRDNORM; 449 if (events & POLLRDBAND) 450 *reventsp |= POLLRDBAND; 451 if (events & POLLOUT) 452 *reventsp |= POLLOUT; 453 if (events & POLLWRBAND) 454 *reventsp |= POLLWRBAND; 455 *phpp = !anyyet && !*reventsp ? &fs_pollhd : (struct pollhead *)NULL; 456 return (0); 457 } 458 459 /* 460 * POSIX pathconf() support. 461 */ 462 /* ARGSUSED */ 463 int 464 fs_pathconf( 465 vnode_t *vp, 466 int cmd, 467 ulong_t *valp, 468 cred_t *cr, 469 caller_context_t *ct) 470 { 471 register ulong_t val; 472 register int error = 0; 473 struct statvfs64 vfsbuf; 474 475 switch (cmd) { 476 477 case _PC_LINK_MAX: 478 val = MAXLINK; 479 break; 480 481 case _PC_MAX_CANON: 482 val = MAX_CANON; 483 break; 484 485 case _PC_MAX_INPUT: 486 val = MAX_INPUT; 487 break; 488 489 case _PC_NAME_MAX: 490 bzero(&vfsbuf, sizeof (vfsbuf)); 491 if (error = VFS_STATVFS(vp->v_vfsp, &vfsbuf)) 492 break; 493 val = vfsbuf.f_namemax; 494 break; 495 496 case _PC_PATH_MAX: 497 case _PC_SYMLINK_MAX: 498 val = MAXPATHLEN; 499 break; 500 501 case _PC_PIPE_BUF: 502 val = PIPE_BUF; 503 break; 504 505 case _PC_NO_TRUNC: 506 if (vp->v_vfsp->vfs_flag & VFS_NOTRUNC) 507 val = 1; /* NOTRUNC is enabled for vp */ 508 else 509 val = (ulong_t)-1; 510 break; 511 512 case _PC_VDISABLE: 513 val = _POSIX_VDISABLE; 514 break; 515 516 case _PC_CHOWN_RESTRICTED: 517 if (rstchown) 518 val = rstchown; /* chown restricted enabled */ 519 else 520 val = (ulong_t)-1; 521 break; 522 523 case _PC_FILESIZEBITS: 524 525 /* 526 * If ever we come here it means that underlying file system 527 * does not recognise the command and therefore this 528 * configurable limit cannot be determined. We return -1 529 * and don't change errno. 530 */ 531 532 val = (ulong_t)-1; /* large file support */ 533 break; 534 535 case _PC_ACL_ENABLED: 536 val = 0; 537 break; 538 539 case _PC_CASE_BEHAVIOR: 540 val = _CASE_SENSITIVE; 541 if (vfs_has_feature(vp->v_vfsp, VFSFT_CASEINSENSITIVE) == 1) 542 val |= _CASE_INSENSITIVE; 543 if (vfs_has_feature(vp->v_vfsp, VFSFT_NOCASESENSITIVE) == 1) 544 val &= ~_CASE_SENSITIVE; 545 break; 546 547 case _PC_SATTR_ENABLED: 548 case _PC_SATTR_EXISTS: 549 val = 0; 550 break; 551 552 case _PC_ACCESS_FILTERING: 553 val = 0; 554 break; 555 556 default: 557 error = EINVAL; 558 break; 559 } 560 561 if (error == 0) 562 *valp = val; 563 return (error); 564 } 565 566 /* 567 * Dispose of a page. 568 */ 569 /* ARGSUSED */ 570 void 571 fs_dispose( 572 struct vnode *vp, 573 page_t *pp, 574 int fl, 575 int dn, 576 struct cred *cr, 577 caller_context_t *ct) 578 { 579 580 ASSERT(fl == B_FREE || fl == B_INVAL); 581 582 if (fl == B_FREE) 583 page_free(pp, dn); 584 else 585 page_destroy(pp, dn); 586 } 587 588 /* ARGSUSED */ 589 void 590 fs_nodispose( 591 struct vnode *vp, 592 page_t *pp, 593 int fl, 594 int dn, 595 struct cred *cr, 596 caller_context_t *ct) 597 { 598 cmn_err(CE_PANIC, "fs_nodispose invoked"); 599 } 600 601 /* 602 * fabricate acls for file systems that do not support acls. 603 */ 604 /* ARGSUSED */ 605 int 606 fs_fab_acl( 607 vnode_t *vp, 608 vsecattr_t *vsecattr, 609 int flag, 610 cred_t *cr, 611 caller_context_t *ct) 612 { 613 aclent_t *aclentp; 614 struct vattr vattr; 615 int error; 616 size_t aclsize; 617 618 vsecattr->vsa_aclcnt = 0; 619 vsecattr->vsa_aclentsz = 0; 620 vsecattr->vsa_aclentp = NULL; 621 vsecattr->vsa_dfaclcnt = 0; /* Default ACLs are not fabricated */ 622 vsecattr->vsa_dfaclentp = NULL; 623 624 vattr.va_mask = AT_MODE | AT_UID | AT_GID; 625 if (error = VOP_GETATTR(vp, &vattr, 0, cr, ct)) 626 return (error); 627 628 if (vsecattr->vsa_mask & (VSA_ACLCNT | VSA_ACL)) { 629 aclsize = 4 * sizeof (aclent_t); 630 vsecattr->vsa_aclcnt = 4; /* USER, GROUP, OTHER, and CLASS */ 631 vsecattr->vsa_aclentp = kmem_zalloc(aclsize, KM_SLEEP); 632 aclentp = vsecattr->vsa_aclentp; 633 634 aclentp->a_type = USER_OBJ; /* Owner */ 635 aclentp->a_perm = ((ushort_t)(vattr.va_mode & 0700)) >> 6; 636 aclentp->a_id = vattr.va_uid; /* Really undefined */ 637 aclentp++; 638 639 aclentp->a_type = GROUP_OBJ; /* Group */ 640 aclentp->a_perm = ((ushort_t)(vattr.va_mode & 0070)) >> 3; 641 aclentp->a_id = vattr.va_gid; /* Really undefined */ 642 aclentp++; 643 644 aclentp->a_type = OTHER_OBJ; /* Other */ 645 aclentp->a_perm = vattr.va_mode & 0007; 646 aclentp->a_id = (gid_t)-1; /* Really undefined */ 647 aclentp++; 648 649 aclentp->a_type = CLASS_OBJ; /* Class */ 650 aclentp->a_perm = (ushort_t)(0007); 651 aclentp->a_id = (gid_t)-1; /* Really undefined */ 652 } else if (vsecattr->vsa_mask & (VSA_ACECNT | VSA_ACE)) { 653 VERIFY(0 == acl_trivial_create(vattr.va_mode, 654 (vp->v_type == VDIR), (ace_t **)&vsecattr->vsa_aclentp, 655 &vsecattr->vsa_aclcnt)); 656 vsecattr->vsa_aclentsz = vsecattr->vsa_aclcnt * sizeof (ace_t); 657 } 658 659 return (error); 660 } 661 662 /* 663 * Common code for implementing DOS share reservations 664 */ 665 /* ARGSUSED4 */ 666 int 667 fs_shrlock( 668 struct vnode *vp, 669 int cmd, 670 struct shrlock *shr, 671 int flag, 672 cred_t *cr, 673 caller_context_t *ct) 674 { 675 int error; 676 677 /* 678 * Make sure that the file was opened with permissions appropriate 679 * for the request, and make sure the caller isn't trying to sneak 680 * in an NBMAND request. 681 */ 682 if (cmd == F_SHARE) { 683 if (((shr->s_access & F_RDACC) && (flag & FREAD) == 0) || 684 ((shr->s_access & F_WRACC) && (flag & FWRITE) == 0)) 685 return (EBADF); 686 if (shr->s_access & (F_RMACC | F_MDACC)) 687 return (EINVAL); 688 if (shr->s_deny & (F_MANDDNY | F_RMDNY)) 689 return (EINVAL); 690 } 691 if (cmd == F_SHARE_NBMAND) { 692 /* make sure nbmand is allowed on the file */ 693 if (!vp->v_vfsp || 694 !(vp->v_vfsp->vfs_flag & VFS_NBMAND)) { 695 return (EINVAL); 696 } 697 if (vp->v_type != VREG) { 698 return (EINVAL); 699 } 700 } 701 702 nbl_start_crit(vp, RW_WRITER); 703 704 switch (cmd) { 705 706 case F_SHARE_NBMAND: 707 shr->s_deny |= F_MANDDNY; 708 /*FALLTHROUGH*/ 709 case F_SHARE: 710 error = add_share(vp, shr); 711 break; 712 713 case F_UNSHARE: 714 error = del_share(vp, shr); 715 break; 716 717 case F_HASREMOTELOCKS: 718 /* 719 * We are overloading this command to refer to remote 720 * shares as well as remote locks, despite its name. 721 */ 722 shr->s_access = shr_has_remote_shares(vp, shr->s_sysid); 723 error = 0; 724 break; 725 726 default: 727 error = EINVAL; 728 break; 729 } 730 731 nbl_end_crit(vp); 732 return (error); 733 } 734 735 /*ARGSUSED1*/ 736 int 737 fs_vnevent_nosupport(vnode_t *vp, vnevent_t e, vnode_t *dvp, char *fnm, 738 caller_context_t *ct) 739 { 740 ASSERT(vp != NULL); 741 return (ENOTSUP); 742 } 743 744 /*ARGSUSED1*/ 745 int 746 fs_vnevent_support(vnode_t *vp, vnevent_t e, vnode_t *dvp, char *fnm, 747 caller_context_t *ct) 748 { 749 ASSERT(vp != NULL); 750 return (0); 751 } 752 753 /* 754 * return 1 for non-trivial ACL. 755 * 756 * NB: It is not necessary for the caller to VOP_RWLOCK since 757 * we only issue VOP_GETSECATTR. 758 * 759 * Returns 0 == trivial 760 * 1 == NOT Trivial 761 * <0 could not determine. 762 */ 763 int 764 fs_acl_nontrivial(vnode_t *vp, cred_t *cr) 765 { 766 ulong_t acl_styles; 767 ulong_t acl_flavor; 768 vsecattr_t vsecattr; 769 int error; 770 int isnontrivial; 771 772 /* determine the forms of ACLs maintained */ 773 error = VOP_PATHCONF(vp, _PC_ACL_ENABLED, &acl_styles, cr, NULL); 774 775 /* clear bits we don't understand and establish default acl_style */ 776 acl_styles &= (_ACL_ACLENT_ENABLED | _ACL_ACE_ENABLED); 777 if (error || (acl_styles == 0)) 778 acl_styles = _ACL_ACLENT_ENABLED; 779 780 vsecattr.vsa_aclentp = NULL; 781 vsecattr.vsa_dfaclentp = NULL; 782 vsecattr.vsa_aclcnt = 0; 783 vsecattr.vsa_dfaclcnt = 0; 784 785 while (acl_styles) { 786 /* select one of the styles as current flavor */ 787 acl_flavor = 0; 788 if (acl_styles & _ACL_ACLENT_ENABLED) { 789 acl_flavor = _ACL_ACLENT_ENABLED; 790 vsecattr.vsa_mask = VSA_ACLCNT | VSA_DFACLCNT; 791 } else if (acl_styles & _ACL_ACE_ENABLED) { 792 acl_flavor = _ACL_ACE_ENABLED; 793 vsecattr.vsa_mask = VSA_ACECNT | VSA_ACE; 794 } 795 796 ASSERT(vsecattr.vsa_mask && acl_flavor); 797 error = VOP_GETSECATTR(vp, &vsecattr, 0, cr, NULL); 798 if (error == 0) 799 break; 800 801 /* that flavor failed */ 802 acl_styles &= ~acl_flavor; 803 } 804 805 /* if all styles fail then assume trivial */ 806 if (acl_styles == 0) 807 return (0); 808 809 /* process the flavor that worked */ 810 isnontrivial = 0; 811 if (acl_flavor & _ACL_ACLENT_ENABLED) { 812 if (vsecattr.vsa_aclcnt > MIN_ACL_ENTRIES) 813 isnontrivial = 1; 814 if (vsecattr.vsa_aclcnt && vsecattr.vsa_aclentp != NULL) 815 kmem_free(vsecattr.vsa_aclentp, 816 vsecattr.vsa_aclcnt * sizeof (aclent_t)); 817 if (vsecattr.vsa_dfaclcnt && vsecattr.vsa_dfaclentp != NULL) 818 kmem_free(vsecattr.vsa_dfaclentp, 819 vsecattr.vsa_dfaclcnt * sizeof (aclent_t)); 820 } 821 if (acl_flavor & _ACL_ACE_ENABLED) { 822 isnontrivial = ace_trivial(vsecattr.vsa_aclentp, 823 vsecattr.vsa_aclcnt); 824 825 if (vsecattr.vsa_aclcnt && vsecattr.vsa_aclentp != NULL) 826 kmem_free(vsecattr.vsa_aclentp, 827 vsecattr.vsa_aclcnt * sizeof (ace_t)); 828 /* ACE has no vsecattr.vsa_dfaclcnt */ 829 } 830 return (isnontrivial); 831 } 832 833 /* 834 * Check whether we need a retry to recover from STALE error. 835 */ 836 int 837 fs_need_estale_retry(int retry_count) 838 { 839 if (retry_count < fs_estale_retry) 840 return (1); 841 else 842 return (0); 843 } 844 845 846 static int (*fs_av_scan)(vnode_t *, cred_t *, int) = NULL; 847 848 /* 849 * Routine for anti-virus scanner to call to register its scanning routine. 850 */ 851 void 852 fs_vscan_register(int (*av_scan)(vnode_t *, cred_t *, int)) 853 { 854 fs_av_scan = av_scan; 855 } 856 857 /* 858 * Routine for file systems to call to initiate anti-virus scanning. 859 * Scanning will only be done on REGular files (currently). 860 */ 861 int 862 fs_vscan(vnode_t *vp, cred_t *cr, int async) 863 { 864 int ret = 0; 865 866 if (fs_av_scan && vp->v_type == VREG) 867 ret = (*fs_av_scan)(vp, cr, async); 868 869 return (ret); 870 } 871 872 /* 873 * support functions for reparse point 874 */ 875 /* 876 * reparse_vnode_parse 877 * 878 * Read the symlink data of a reparse point specified by the vnode 879 * and return the reparse data as name-value pair in the nvlist. 880 */ 881 int 882 reparse_vnode_parse(vnode_t *vp, nvlist_t *nvl) 883 { 884 int err; 885 char *lkdata; 886 struct uio uio; 887 struct iovec iov; 888 889 if (vp == NULL || nvl == NULL) 890 return (EINVAL); 891 892 lkdata = kmem_alloc(MAXREPARSELEN, KM_SLEEP); 893 894 /* 895 * Set up io vector to read sym link data 896 */ 897 iov.iov_base = lkdata; 898 iov.iov_len = MAXREPARSELEN; 899 uio.uio_iov = &iov; 900 uio.uio_iovcnt = 1; 901 uio.uio_segflg = UIO_SYSSPACE; 902 uio.uio_extflg = UIO_COPY_CACHED; 903 uio.uio_loffset = (offset_t)0; 904 uio.uio_resid = MAXREPARSELEN; 905 906 if ((err = VOP_READLINK(vp, &uio, kcred, NULL)) == 0) { 907 *(lkdata + MAXREPARSELEN - uio.uio_resid) = '\0'; 908 err = reparse_parse(lkdata, nvl); 909 } 910 kmem_free(lkdata, MAXREPARSELEN); /* done with lkdata */ 911 912 return (err); 913 } 914 915 void 916 reparse_point_init() 917 { 918 mutex_init(&reparsed_door_lock, NULL, MUTEX_DEFAULT, NULL); 919 } 920 921 static door_handle_t 922 reparse_door_get_handle() 923 { 924 door_handle_t dh; 925 926 mutex_enter(&reparsed_door_lock); 927 if ((dh = reparsed_door) == NULL) { 928 if (door_ki_open(REPARSED_DOOR, &reparsed_door) != 0) { 929 reparsed_door = NULL; 930 dh = NULL; 931 } else 932 dh = reparsed_door; 933 } 934 mutex_exit(&reparsed_door_lock); 935 return (dh); 936 } 937 938 static void 939 reparse_door_reset_handle() 940 { 941 mutex_enter(&reparsed_door_lock); 942 reparsed_door = NULL; 943 mutex_exit(&reparsed_door_lock); 944 } 945 946 /* 947 * reparse_kderef 948 * 949 * Accepts the service-specific item from the reparse point and returns 950 * the service-specific data requested. The caller specifies the size of 951 * the buffer provided via *bufsz; the routine will fail with EOVERFLOW 952 * if the results will not fit in the buffer, in which case, *bufsz will 953 * contain the number of bytes needed to hold the results. 954 * 955 * if ok return 0 and update *bufsize with length of actual result 956 * else return error code. 957 */ 958 int 959 reparse_kderef(const char *svc_type, const char *svc_data, char *buf, 960 size_t *bufsize) 961 { 962 int err, retries, need_free, retried_doorhd; 963 size_t dlen, res_len; 964 char *darg; 965 door_arg_t door_args; 966 reparsed_door_res_t *resp; 967 door_handle_t rp_door; 968 969 if (svc_type == NULL || svc_data == NULL || buf == NULL || 970 bufsize == NULL) 971 return (EINVAL); 972 973 /* get reparsed's door handle */ 974 if ((rp_door = reparse_door_get_handle()) == NULL) 975 return (EBADF); 976 977 /* setup buffer for door_call args and results */ 978 dlen = strlen(svc_type) + strlen(svc_data) + 2; 979 if (*bufsize < dlen) { 980 darg = kmem_alloc(dlen, KM_SLEEP); 981 need_free = 1; 982 } else { 983 darg = buf; /* use same buffer for door's args & results */ 984 need_free = 0; 985 } 986 987 /* build argument string of door call */ 988 (void) snprintf(darg, dlen, "%s:%s", svc_type, svc_data); 989 990 /* setup args for door call */ 991 door_args.data_ptr = darg; 992 door_args.data_size = dlen; 993 door_args.desc_ptr = NULL; 994 door_args.desc_num = 0; 995 door_args.rbuf = buf; 996 door_args.rsize = *bufsize; 997 998 /* do the door_call */ 999 retried_doorhd = 0; 1000 retries = 0; 1001 door_ki_hold(rp_door); 1002 while ((err = door_ki_upcall_limited(rp_door, &door_args, 1003 NULL, SIZE_MAX, 0)) != 0) { 1004 if (err == EAGAIN || err == EINTR) { 1005 if (++retries < REPARSED_DOORCALL_MAX_RETRY) { 1006 delay(SEC_TO_TICK(1)); 1007 continue; 1008 } 1009 } else if (err == EBADF) { 1010 /* door server goes away... */ 1011 reparse_door_reset_handle(); 1012 1013 if (retried_doorhd == 0) { 1014 door_ki_rele(rp_door); 1015 retried_doorhd++; 1016 rp_door = reparse_door_get_handle(); 1017 if (rp_door != NULL) { 1018 door_ki_hold(rp_door); 1019 continue; 1020 } 1021 } 1022 } 1023 break; 1024 } 1025 1026 if (rp_door) 1027 door_ki_rele(rp_door); 1028 1029 if (need_free) 1030 kmem_free(darg, dlen); /* done with args buffer */ 1031 1032 if (err != 0) 1033 return (err); 1034 1035 resp = (reparsed_door_res_t *)door_args.rbuf; 1036 if ((err = resp->res_status) == 0) { 1037 /* 1038 * have to save the length of the results before the 1039 * bcopy below since it's can be an overlap copy that 1040 * overwrites the reparsed_door_res_t structure at 1041 * the beginning of the buffer. 1042 */ 1043 res_len = (size_t)resp->res_len; 1044 1045 /* deref call is ok */ 1046 if (res_len > *bufsize) 1047 err = EOVERFLOW; 1048 else 1049 bcopy(resp->res_data, buf, res_len); 1050 *bufsize = res_len; 1051 } 1052 if (door_args.rbuf != buf) 1053 kmem_free(door_args.rbuf, door_args.rsize); 1054 1055 return (err); 1056 } 1057