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