1 /* 2 * Copyright (c) 2000-2001, Boris Popov 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Boris Popov. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $Id: smbfs_vfsops.c,v 1.73.64.1 2005/05/27 02:35:28 lindak Exp $ 33 */ 34 35 /* 36 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 37 * Copyright 2013, Joyent, Inc. All rights reserved. 38 * Copyright (c) 2016 by Delphix. All rights reserved. 39 */ 40 41 #include <sys/systm.h> 42 #include <sys/cred.h> 43 #include <sys/time.h> 44 #include <sys/vfs.h> 45 #include <sys/vnode.h> 46 #include <fs/fs_subr.h> 47 #include <sys/sysmacros.h> 48 #include <sys/kmem.h> 49 #include <sys/mkdev.h> 50 #include <sys/mount.h> 51 #include <sys/statvfs.h> 52 #include <sys/errno.h> 53 #include <sys/debug.h> 54 #include <sys/cmn_err.h> 55 #include <sys/modctl.h> 56 #include <sys/policy.h> 57 #include <sys/atomic.h> 58 #include <sys/zone.h> 59 #include <sys/vfs_opreg.h> 60 #include <sys/mntent.h> 61 #include <sys/priv.h> 62 #include <sys/tsol/label.h> 63 #include <sys/tsol/tndb.h> 64 #include <inet/ip.h> 65 66 #include <netsmb/smb_osdep.h> 67 #include <netsmb/smb.h> 68 #include <netsmb/smb_conn.h> 69 #include <netsmb/smb_subr.h> 70 #include <netsmb/smb_dev.h> 71 72 #include <smbfs/smbfs.h> 73 #include <smbfs/smbfs_node.h> 74 #include <smbfs/smbfs_subr.h> 75 76 /* 77 * Local functions definitions. 78 */ 79 int smbfsinit(int fstyp, char *name); 80 void smbfsfini(); 81 static int smbfs_mount_label_policy(vfs_t *, void *, int, cred_t *); 82 83 /* 84 * SMBFS Mount options table for MS_OPTIONSTR 85 * Note: These are not all the options. 86 * Some options come in via MS_DATA. 87 * Others are generic (see vfs.c) 88 */ 89 static char *intr_cancel[] = { MNTOPT_NOINTR, NULL }; 90 static char *nointr_cancel[] = { MNTOPT_INTR, NULL }; 91 static char *acl_cancel[] = { MNTOPT_NOACL, NULL }; 92 static char *noacl_cancel[] = { MNTOPT_ACL, NULL }; 93 static char *xattr_cancel[] = { MNTOPT_NOXATTR, NULL }; 94 static char *noxattr_cancel[] = { MNTOPT_XATTR, NULL }; 95 96 static mntopt_t mntopts[] = { 97 /* 98 * option name cancel option default arg flags 99 * ufs arg flag 100 */ 101 { MNTOPT_INTR, intr_cancel, NULL, MO_DEFAULT, 0 }, 102 { MNTOPT_NOINTR, nointr_cancel, NULL, 0, 0 }, 103 { MNTOPT_ACL, acl_cancel, NULL, MO_DEFAULT, 0 }, 104 { MNTOPT_NOACL, noacl_cancel, NULL, 0, 0 }, 105 { MNTOPT_XATTR, xattr_cancel, NULL, MO_DEFAULT, 0 }, 106 { MNTOPT_NOXATTR, noxattr_cancel, NULL, 0, 0 } 107 }; 108 109 static mntopts_t smbfs_mntopts = { 110 sizeof (mntopts) / sizeof (mntopt_t), 111 mntopts 112 }; 113 114 static const char fs_type_name[FSTYPSZ] = "smbfs"; 115 116 static vfsdef_t vfw = { 117 VFSDEF_VERSION, 118 (char *)fs_type_name, 119 smbfsinit, /* init routine */ 120 VSW_HASPROTO|VSW_NOTZONESAFE, /* flags */ 121 &smbfs_mntopts /* mount options table prototype */ 122 }; 123 124 static struct modlfs modlfs = { 125 &mod_fsops, 126 "SMBFS filesystem", 127 &vfw 128 }; 129 130 static struct modlinkage modlinkage = { 131 MODREV_1, (void *)&modlfs, NULL 132 }; 133 134 /* 135 * Mutex to protect the following variables: 136 * smbfs_major 137 * smbfs_minor 138 */ 139 extern kmutex_t smbfs_minor_lock; 140 extern int smbfs_major; 141 extern int smbfs_minor; 142 143 /* 144 * Prevent unloads while we have mounts 145 */ 146 uint32_t smbfs_mountcount; 147 148 /* 149 * smbfs vfs operations. 150 */ 151 static int smbfs_mount(vfs_t *, vnode_t *, struct mounta *, cred_t *); 152 static int smbfs_unmount(vfs_t *, int, cred_t *); 153 static int smbfs_root(vfs_t *, vnode_t **); 154 static int smbfs_statvfs(vfs_t *, statvfs64_t *); 155 static int smbfs_sync(vfs_t *, short, cred_t *); 156 static void smbfs_freevfs(vfs_t *); 157 158 /* 159 * Module loading 160 */ 161 162 /* 163 * This routine is invoked automatically when the kernel module 164 * containing this routine is loaded. This allows module specific 165 * initialization to be done when the module is loaded. 166 */ 167 int 168 _init(void) 169 { 170 int error; 171 172 /* 173 * Check compiled-in version of "nsmb" 174 * that we're linked with. (paranoid) 175 */ 176 if (nsmb_version != NSMB_VERSION) { 177 cmn_err(CE_WARN, "_init: nsmb version mismatch"); 178 return (ENOTTY); 179 } 180 181 smbfs_mountcount = 0; 182 183 /* 184 * NFS calls these two in _clntinit 185 * Easier to follow this way. 186 */ 187 if ((error = smbfs_subrinit()) != 0) { 188 cmn_err(CE_WARN, "_init: smbfs_subrinit failed"); 189 return (error); 190 } 191 192 if ((error = smbfs_vfsinit()) != 0) { 193 cmn_err(CE_WARN, "_init: smbfs_vfsinit failed"); 194 smbfs_subrfini(); 195 return (error); 196 } 197 198 if ((error = smbfs_clntinit()) != 0) { 199 cmn_err(CE_WARN, "_init: smbfs_clntinit failed"); 200 smbfs_vfsfini(); 201 smbfs_subrfini(); 202 return (error); 203 } 204 205 error = mod_install((struct modlinkage *)&modlinkage); 206 return (error); 207 } 208 209 /* 210 * Free kernel module resources that were allocated in _init 211 * and remove the linkage information into the kernel 212 */ 213 int 214 _fini(void) 215 { 216 int error; 217 218 /* 219 * If a forcedly unmounted instance is still hanging around, 220 * we cannot allow the module to be unloaded because that would 221 * cause panics once the VFS framework decides it's time to call 222 * into VFS_FREEVFS(). 223 */ 224 if (smbfs_mountcount) 225 return (EBUSY); 226 227 error = mod_remove(&modlinkage); 228 if (error) 229 return (error); 230 231 /* 232 * Free the allocated smbnodes, etc. 233 */ 234 smbfs_clntfini(); 235 236 /* NFS calls these two in _clntfini */ 237 smbfs_vfsfini(); 238 smbfs_subrfini(); 239 240 /* 241 * Free the ops vectors 242 */ 243 smbfsfini(); 244 return (0); 245 } 246 247 /* 248 * Return information about the module 249 */ 250 int 251 _info(struct modinfo *modinfop) 252 { 253 return (mod_info((struct modlinkage *)&modlinkage, modinfop)); 254 } 255 256 /* 257 * Initialize the vfs structure 258 */ 259 260 int smbfsfstyp; 261 vfsops_t *smbfs_vfsops = NULL; 262 263 static const fs_operation_def_t smbfs_vfsops_template[] = { 264 { VFSNAME_MOUNT, { .vfs_mount = smbfs_mount } }, 265 { VFSNAME_UNMOUNT, { .vfs_unmount = smbfs_unmount } }, 266 { VFSNAME_ROOT, { .vfs_root = smbfs_root } }, 267 { VFSNAME_STATVFS, { .vfs_statvfs = smbfs_statvfs } }, 268 { VFSNAME_SYNC, { .vfs_sync = smbfs_sync } }, 269 { VFSNAME_VGET, { .error = fs_nosys } }, 270 { VFSNAME_MOUNTROOT, { .error = fs_nosys } }, 271 { VFSNAME_FREEVFS, { .vfs_freevfs = smbfs_freevfs } }, 272 { NULL, NULL } 273 }; 274 275 int 276 smbfsinit(int fstyp, char *name) 277 { 278 int error; 279 280 error = vfs_setfsops(fstyp, smbfs_vfsops_template, &smbfs_vfsops); 281 if (error != 0) { 282 zcmn_err(GLOBAL_ZONEID, CE_WARN, 283 "smbfsinit: bad vfs ops template"); 284 return (error); 285 } 286 287 error = vn_make_ops(name, smbfs_vnodeops_template, &smbfs_vnodeops); 288 if (error != 0) { 289 (void) vfs_freevfsops_by_type(fstyp); 290 zcmn_err(GLOBAL_ZONEID, CE_WARN, 291 "smbfsinit: bad vnode ops template"); 292 return (error); 293 } 294 295 smbfsfstyp = fstyp; 296 297 return (0); 298 } 299 300 void 301 smbfsfini() 302 { 303 if (smbfs_vfsops) { 304 (void) vfs_freevfsops_by_type(smbfsfstyp); 305 smbfs_vfsops = NULL; 306 } 307 if (smbfs_vnodeops) { 308 vn_freevnodeops(smbfs_vnodeops); 309 smbfs_vnodeops = NULL; 310 } 311 } 312 313 void 314 smbfs_free_smi(smbmntinfo_t *smi) 315 { 316 if (smi == NULL) 317 return; 318 319 if (smi->smi_zone_ref.zref_zone != NULL) 320 zone_rele_ref(&smi->smi_zone_ref, ZONE_REF_SMBFS); 321 322 if (smi->smi_share != NULL) 323 smb_share_rele(smi->smi_share); 324 325 avl_destroy(&smi->smi_hash_avl); 326 rw_destroy(&smi->smi_hash_lk); 327 cv_destroy(&smi->smi_statvfs_cv); 328 mutex_destroy(&smi->smi_lock); 329 330 kmem_free(smi, sizeof (smbmntinfo_t)); 331 } 332 333 /* 334 * smbfs mount vfsop 335 * Set up mount info record and attach it to vfs struct. 336 */ 337 static int 338 smbfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr) 339 { 340 char *data = uap->dataptr; 341 int error; 342 smbnode_t *rtnp = NULL; /* root of this fs */ 343 smbmntinfo_t *smi = NULL; 344 dev_t smbfs_dev; 345 int version; 346 int devfd; 347 zone_t *zone = curproc->p_zone; 348 zone_t *mntzone = NULL; 349 smb_share_t *ssp = NULL; 350 smb_cred_t scred; 351 int flags, sec; 352 353 STRUCT_DECL(smbfs_args, args); /* smbfs mount arguments */ 354 355 if ((error = secpolicy_fs_mount(cr, mvp, vfsp)) != 0) 356 return (error); 357 358 if (mvp->v_type != VDIR) 359 return (ENOTDIR); 360 361 /* 362 * get arguments 363 * 364 * uap->datalen might be different from sizeof (args) 365 * in a compatible situation. 366 */ 367 STRUCT_INIT(args, get_udatamodel()); 368 bzero(STRUCT_BUF(args), SIZEOF_STRUCT(smbfs_args, DATAMODEL_NATIVE)); 369 if (copyin(data, STRUCT_BUF(args), MIN(uap->datalen, 370 SIZEOF_STRUCT(smbfs_args, DATAMODEL_NATIVE)))) 371 return (EFAULT); 372 373 /* 374 * Check mount program version 375 */ 376 version = STRUCT_FGET(args, version); 377 if (version != SMBFS_VERSION) { 378 cmn_err(CE_WARN, "mount version mismatch:" 379 " kernel=%d, mount=%d\n", 380 SMBFS_VERSION, version); 381 return (EINVAL); 382 } 383 384 /* 385 * Deal with re-mount requests. 386 */ 387 if (uap->flags & MS_REMOUNT) { 388 cmn_err(CE_WARN, "MS_REMOUNT not implemented"); 389 return (ENOTSUP); 390 } 391 392 /* 393 * Check for busy 394 */ 395 mutex_enter(&mvp->v_lock); 396 if (!(uap->flags & MS_OVERLAY) && 397 (mvp->v_count != 1 || (mvp->v_flag & VROOT))) { 398 mutex_exit(&mvp->v_lock); 399 return (EBUSY); 400 } 401 mutex_exit(&mvp->v_lock); 402 403 /* 404 * Get the "share" from the netsmb driver (ssp). 405 * It is returned with a "ref" (hold) for us. 406 * Release this hold: at errout below, or in 407 * smbfs_freevfs(). 408 */ 409 devfd = STRUCT_FGET(args, devfd); 410 error = smb_dev2share(devfd, &ssp); 411 if (error) { 412 cmn_err(CE_WARN, "invalid device handle %d (%d)\n", 413 devfd, error); 414 return (error); 415 } 416 417 /* 418 * Use "goto errout" from here on. 419 * See: ssp, smi, rtnp, mntzone 420 */ 421 422 /* 423 * Determine the zone we're being mounted into. 424 */ 425 zone_hold(mntzone = zone); /* start with this assumption */ 426 if (getzoneid() == GLOBAL_ZONEID) { 427 zone_rele(mntzone); 428 mntzone = zone_find_by_path(refstr_value(vfsp->vfs_mntpt)); 429 ASSERT(mntzone != NULL); 430 if (mntzone != zone) { 431 error = EBUSY; 432 goto errout; 433 } 434 } 435 436 /* 437 * Stop the mount from going any further if the zone is going away. 438 */ 439 if (zone_status_get(mntzone) >= ZONE_IS_SHUTTING_DOWN) { 440 error = EBUSY; 441 goto errout; 442 } 443 444 /* 445 * On a Trusted Extensions client, we may have to force read-only 446 * for read-down mounts. 447 */ 448 if (is_system_labeled()) { 449 void *addr; 450 int ipvers = 0; 451 struct smb_vc *vcp; 452 453 vcp = SSTOVC(ssp); 454 addr = smb_vc_getipaddr(vcp, &ipvers); 455 error = smbfs_mount_label_policy(vfsp, addr, ipvers, cr); 456 457 if (error > 0) 458 goto errout; 459 460 if (error == -1) { 461 /* change mount to read-only to prevent write-down */ 462 vfs_setmntopt(vfsp, MNTOPT_RO, NULL, 0); 463 } 464 } 465 466 /* Prevent unload. */ 467 atomic_inc_32(&smbfs_mountcount); 468 469 /* 470 * Create a mount record and link it to the vfs struct. 471 * No more possiblities for errors from here on. 472 * Tear-down of this stuff is in smbfs_free_smi() 473 * 474 * Compare with NFS: nfsrootvp() 475 */ 476 smi = kmem_zalloc(sizeof (*smi), KM_SLEEP); 477 478 mutex_init(&smi->smi_lock, NULL, MUTEX_DEFAULT, NULL); 479 cv_init(&smi->smi_statvfs_cv, NULL, CV_DEFAULT, NULL); 480 481 rw_init(&smi->smi_hash_lk, NULL, RW_DEFAULT, NULL); 482 smbfs_init_hash_avl(&smi->smi_hash_avl); 483 484 smi->smi_share = ssp; 485 ssp = NULL; 486 487 /* 488 * Convert the anonymous zone hold acquired via zone_hold() above 489 * into a zone reference. 490 */ 491 zone_init_ref(&smi->smi_zone_ref); 492 zone_hold_ref(mntzone, &smi->smi_zone_ref, ZONE_REF_SMBFS); 493 zone_rele(mntzone); 494 mntzone = NULL; 495 496 /* 497 * Initialize option defaults 498 */ 499 smi->smi_flags = SMI_LLOCK; 500 smi->smi_acregmin = SEC2HR(SMBFS_ACREGMIN); 501 smi->smi_acregmax = SEC2HR(SMBFS_ACREGMAX); 502 smi->smi_acdirmin = SEC2HR(SMBFS_ACDIRMIN); 503 smi->smi_acdirmax = SEC2HR(SMBFS_ACDIRMAX); 504 505 /* 506 * All "generic" mount options have already been 507 * handled in vfs.c:domount() - see mntopts stuff. 508 * Query generic options using vfs_optionisset(). 509 */ 510 if (vfs_optionisset(vfsp, MNTOPT_INTR, NULL)) 511 smi->smi_flags |= SMI_INT; 512 if (vfs_optionisset(vfsp, MNTOPT_ACL, NULL)) 513 smi->smi_flags |= SMI_ACL; 514 515 /* 516 * Get the mount options that come in as smbfs_args, 517 * starting with args.flags (SMBFS_MF_xxx) 518 */ 519 flags = STRUCT_FGET(args, flags); 520 smi->smi_uid = STRUCT_FGET(args, uid); 521 smi->smi_gid = STRUCT_FGET(args, gid); 522 smi->smi_fmode = STRUCT_FGET(args, file_mode) & 0777; 523 smi->smi_dmode = STRUCT_FGET(args, dir_mode) & 0777; 524 525 /* 526 * Hande the SMBFS_MF_xxx flags. 527 */ 528 if (flags & SMBFS_MF_NOAC) 529 smi->smi_flags |= SMI_NOAC; 530 if (flags & SMBFS_MF_ACREGMIN) { 531 sec = STRUCT_FGET(args, acregmin); 532 if (sec < 0 || sec > SMBFS_ACMINMAX) 533 sec = SMBFS_ACMINMAX; 534 smi->smi_acregmin = SEC2HR(sec); 535 } 536 if (flags & SMBFS_MF_ACREGMAX) { 537 sec = STRUCT_FGET(args, acregmax); 538 if (sec < 0 || sec > SMBFS_ACMAXMAX) 539 sec = SMBFS_ACMAXMAX; 540 smi->smi_acregmax = SEC2HR(sec); 541 } 542 if (flags & SMBFS_MF_ACDIRMIN) { 543 sec = STRUCT_FGET(args, acdirmin); 544 if (sec < 0 || sec > SMBFS_ACMINMAX) 545 sec = SMBFS_ACMINMAX; 546 smi->smi_acdirmin = SEC2HR(sec); 547 } 548 if (flags & SMBFS_MF_ACDIRMAX) { 549 sec = STRUCT_FGET(args, acdirmax); 550 if (sec < 0 || sec > SMBFS_ACMAXMAX) 551 sec = SMBFS_ACMAXMAX; 552 smi->smi_acdirmax = SEC2HR(sec); 553 } 554 555 /* 556 * Get attributes of the remote file system, 557 * i.e. ACL support, named streams, etc. 558 */ 559 smb_credinit(&scred, cr); 560 error = smbfs_smb_qfsattr(smi->smi_share, &smi->smi_fsa, &scred); 561 smb_credrele(&scred); 562 if (error) { 563 SMBVDEBUG("smbfs_smb_qfsattr error %d\n", error); 564 } 565 566 /* 567 * We enable XATTR by default (via smbfs_mntopts) 568 * but if the share does not support named streams, 569 * force the NOXATTR option (also clears XATTR). 570 * Caller will set or clear VFS_XATTR after this. 571 */ 572 if ((smi->smi_fsattr & FILE_NAMED_STREAMS) == 0) 573 vfs_setmntopt(vfsp, MNTOPT_NOXATTR, NULL, 0); 574 575 /* 576 * Ditto ACLs (disable if not supported on this share) 577 */ 578 if ((smi->smi_fsattr & FILE_PERSISTENT_ACLS) == 0) { 579 vfs_setmntopt(vfsp, MNTOPT_NOACL, NULL, 0); 580 smi->smi_flags &= ~SMI_ACL; 581 } 582 583 /* 584 * Assign a unique device id to the mount 585 */ 586 mutex_enter(&smbfs_minor_lock); 587 do { 588 smbfs_minor = (smbfs_minor + 1) & MAXMIN32; 589 smbfs_dev = makedevice(smbfs_major, smbfs_minor); 590 } while (vfs_devismounted(smbfs_dev)); 591 mutex_exit(&smbfs_minor_lock); 592 593 vfsp->vfs_dev = smbfs_dev; 594 vfs_make_fsid(&vfsp->vfs_fsid, smbfs_dev, smbfsfstyp); 595 vfsp->vfs_data = (caddr_t)smi; 596 vfsp->vfs_fstype = smbfsfstyp; 597 vfsp->vfs_bsize = MAXBSIZE; 598 vfsp->vfs_bcount = 0; 599 600 smi->smi_vfsp = vfsp; 601 smbfs_zonelist_add(smi); /* undo in smbfs_freevfs */ 602 603 /* PSARC 2007/227 VFS Feature Registration */ 604 vfs_set_feature(vfsp, VFSFT_XVATTR); 605 vfs_set_feature(vfsp, VFSFT_SYSATTR_VIEWS); 606 607 /* 608 * Create the root vnode, which we need in unmount 609 * for the call to smbfs_check_table(), etc. 610 * Release this hold in smbfs_unmount. 611 */ 612 rtnp = smbfs_node_findcreate(smi, "\\", 1, NULL, 0, 0, 613 &smbfs_fattr0); 614 ASSERT(rtnp != NULL); 615 rtnp->r_vnode->v_type = VDIR; 616 rtnp->r_vnode->v_flag |= VROOT; 617 smi->smi_root = rtnp; 618 619 /* 620 * NFS does other stuff here too: 621 * async worker threads 622 * init kstats 623 * 624 * End of code from NFS nfsrootvp() 625 */ 626 return (0); 627 628 errout: 629 vfsp->vfs_data = NULL; 630 if (smi != NULL) 631 smbfs_free_smi(smi); 632 633 if (mntzone != NULL) 634 zone_rele(mntzone); 635 636 if (ssp != NULL) 637 smb_share_rele(ssp); 638 639 return (error); 640 } 641 642 /* 643 * vfs operations 644 */ 645 static int 646 smbfs_unmount(vfs_t *vfsp, int flag, cred_t *cr) 647 { 648 smbmntinfo_t *smi; 649 smbnode_t *rtnp; 650 651 smi = VFTOSMI(vfsp); 652 653 if (secpolicy_fs_unmount(cr, vfsp) != 0) 654 return (EPERM); 655 656 if ((flag & MS_FORCE) == 0) { 657 smbfs_rflush(vfsp, cr); 658 659 /* 660 * If there are any active vnodes on this file system, 661 * (other than the root vnode) then the file system is 662 * busy and can't be umounted. 663 */ 664 if (smbfs_check_table(vfsp, smi->smi_root)) 665 return (EBUSY); 666 667 /* 668 * We normally hold a ref to the root vnode, so 669 * check for references beyond the one we expect: 670 * smbmntinfo_t -> smi_root 671 * Note that NFS does not hold the root vnode. 672 */ 673 if (smi->smi_root && 674 smi->smi_root->r_vnode->v_count > 1) 675 return (EBUSY); 676 } 677 678 /* 679 * common code for both forced and non-forced 680 * 681 * Setting VFS_UNMOUNTED prevents new operations. 682 * Operations already underway may continue, 683 * but not for long. 684 */ 685 vfsp->vfs_flag |= VFS_UNMOUNTED; 686 687 /* 688 * Shutdown any outstanding I/O requests on this share, 689 * and force a tree disconnect. The share object will 690 * continue to hang around until smb_share_rele(). 691 * This should also cause most active nodes to be 692 * released as their operations fail with EIO. 693 */ 694 smb_share_kill(smi->smi_share); 695 696 /* 697 * If we hold the root VP (and we normally do) 698 * then it's safe to release it now. 699 */ 700 if (smi->smi_root) { 701 rtnp = smi->smi_root; 702 smi->smi_root = NULL; 703 VN_RELE(rtnp->r_vnode); /* release root vnode */ 704 } 705 706 /* 707 * Remove all nodes from the node hash tables. 708 * This (indirectly) calls: smbfs_addfree, smbinactive, 709 * which will try to flush dirty pages, etc. so 710 * don't destroy the underlying share just yet. 711 * 712 * Also, with a forced unmount, some nodes may 713 * remain active, and those will get cleaned up 714 * after their last vn_rele. 715 */ 716 smbfs_destroy_table(vfsp); 717 718 /* 719 * Delete our kstats... 720 * 721 * Doing it here, rather than waiting until 722 * smbfs_freevfs so these are not visible 723 * after the unmount. 724 */ 725 if (smi->smi_io_kstats) { 726 kstat_delete(smi->smi_io_kstats); 727 smi->smi_io_kstats = NULL; 728 } 729 if (smi->smi_ro_kstats) { 730 kstat_delete(smi->smi_ro_kstats); 731 smi->smi_ro_kstats = NULL; 732 } 733 734 /* 735 * The rest happens in smbfs_freevfs() 736 */ 737 return (0); 738 } 739 740 741 /* 742 * find root of smbfs 743 */ 744 static int 745 smbfs_root(vfs_t *vfsp, vnode_t **vpp) 746 { 747 smbmntinfo_t *smi; 748 vnode_t *vp; 749 750 smi = VFTOSMI(vfsp); 751 752 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 753 return (EPERM); 754 755 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 756 return (EIO); 757 758 /* 759 * The root vp is created in mount and held 760 * until unmount, so this is paranoia. 761 */ 762 if (smi->smi_root == NULL) 763 return (EIO); 764 765 /* Just take a reference and return it. */ 766 vp = SMBTOV(smi->smi_root); 767 VN_HOLD(vp); 768 *vpp = vp; 769 770 return (0); 771 } 772 773 /* 774 * Get file system statistics. 775 */ 776 static int 777 smbfs_statvfs(vfs_t *vfsp, statvfs64_t *sbp) 778 { 779 int error; 780 smbmntinfo_t *smi = VFTOSMI(vfsp); 781 smb_share_t *ssp = smi->smi_share; 782 statvfs64_t stvfs; 783 hrtime_t now; 784 smb_cred_t scred; 785 786 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 787 return (EPERM); 788 789 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 790 return (EIO); 791 792 mutex_enter(&smi->smi_lock); 793 794 /* 795 * Use cached result if still valid. 796 */ 797 recheck: 798 now = gethrtime(); 799 if (now < smi->smi_statfstime) { 800 error = 0; 801 goto cache_hit; 802 } 803 804 /* 805 * FS attributes are stale, so someone 806 * needs to do an OTW call to get them. 807 * Serialize here so only one thread 808 * does the OTW call. 809 */ 810 if (smi->smi_status & SM_STATUS_STATFS_BUSY) { 811 smi->smi_status |= SM_STATUS_STATFS_WANT; 812 if (!cv_wait_sig(&smi->smi_statvfs_cv, &smi->smi_lock)) { 813 mutex_exit(&smi->smi_lock); 814 return (EINTR); 815 } 816 /* Hope status is valid now. */ 817 goto recheck; 818 } 819 smi->smi_status |= SM_STATUS_STATFS_BUSY; 820 mutex_exit(&smi->smi_lock); 821 822 /* 823 * Do the OTW call. Note: lock NOT held. 824 */ 825 smb_credinit(&scred, NULL); 826 bzero(&stvfs, sizeof (stvfs)); 827 error = smbfs_smb_statfs(ssp, &stvfs, &scred); 828 smb_credrele(&scred); 829 if (error) { 830 SMBVDEBUG("statfs error=%d\n", error); 831 } else { 832 833 /* 834 * Set a few things the OTW call didn't get. 835 */ 836 stvfs.f_frsize = stvfs.f_bsize; 837 stvfs.f_favail = stvfs.f_ffree; 838 stvfs.f_fsid = (unsigned long)vfsp->vfs_fsid.val[0]; 839 bcopy(fs_type_name, stvfs.f_basetype, FSTYPSZ); 840 stvfs.f_flag = vf_to_stf(vfsp->vfs_flag); 841 stvfs.f_namemax = smi->smi_fsa.fsa_maxname; 842 843 /* 844 * Save the result, update lifetime 845 */ 846 now = gethrtime(); 847 smi->smi_statfstime = now + 848 (SM_MAX_STATFSTIME * (hrtime_t)NANOSEC); 849 smi->smi_statvfsbuf = stvfs; /* struct assign! */ 850 } 851 852 mutex_enter(&smi->smi_lock); 853 if (smi->smi_status & SM_STATUS_STATFS_WANT) 854 cv_broadcast(&smi->smi_statvfs_cv); 855 smi->smi_status &= ~(SM_STATUS_STATFS_BUSY | SM_STATUS_STATFS_WANT); 856 857 /* 858 * Copy the statvfs data to caller's buf. 859 * Note: struct assignment 860 */ 861 cache_hit: 862 if (error == 0) 863 *sbp = smi->smi_statvfsbuf; 864 mutex_exit(&smi->smi_lock); 865 return (error); 866 } 867 868 static kmutex_t smbfs_syncbusy; 869 870 /* 871 * Flush dirty smbfs files for file system vfsp. 872 * If vfsp == NULL, all smbfs files are flushed. 873 */ 874 /*ARGSUSED*/ 875 static int 876 smbfs_sync(vfs_t *vfsp, short flag, cred_t *cr) 877 { 878 /* 879 * Cross-zone calls are OK here, since this translates to a 880 * VOP_PUTPAGE(B_ASYNC), which gets picked up by the right zone. 881 */ 882 if (!(flag & SYNC_ATTR) && mutex_tryenter(&smbfs_syncbusy) != 0) { 883 smbfs_rflush(vfsp, cr); 884 mutex_exit(&smbfs_syncbusy); 885 } 886 887 return (0); 888 } 889 890 /* 891 * Initialization routine for VFS routines. Should only be called once 892 */ 893 int 894 smbfs_vfsinit(void) 895 { 896 mutex_init(&smbfs_syncbusy, NULL, MUTEX_DEFAULT, NULL); 897 return (0); 898 } 899 900 /* 901 * Shutdown routine for VFS routines. Should only be called once 902 */ 903 void 904 smbfs_vfsfini(void) 905 { 906 mutex_destroy(&smbfs_syncbusy); 907 } 908 909 void 910 smbfs_freevfs(vfs_t *vfsp) 911 { 912 smbmntinfo_t *smi; 913 914 /* free up the resources */ 915 smi = VFTOSMI(vfsp); 916 917 /* 918 * By this time we should have already deleted the 919 * smi kstats in the unmount code. If they are still around 920 * something is wrong 921 */ 922 ASSERT(smi->smi_io_kstats == NULL); 923 924 smbfs_zonelist_remove(smi); 925 926 smbfs_free_smi(smi); 927 928 /* 929 * Allow _fini() to succeed now, if so desired. 930 */ 931 atomic_dec_32(&smbfs_mountcount); 932 } 933 934 /* 935 * smbfs_mount_label_policy: 936 * Determine whether the mount is allowed according to MAC check, 937 * by comparing (where appropriate) label of the remote server 938 * against the label of the zone being mounted into. 939 * 940 * Returns: 941 * 0 : access allowed 942 * -1 : read-only access allowed (i.e., read-down) 943 * >0 : error code, such as EACCES 944 * 945 * NB: 946 * NFS supports Cipso labels by parsing the vfs_resource 947 * to see what the Solaris server global zone has shared. 948 * We can't support that for CIFS since resource names 949 * contain share names, not paths. 950 */ 951 static int 952 smbfs_mount_label_policy(vfs_t *vfsp, void *ipaddr, int addr_type, cred_t *cr) 953 { 954 bslabel_t *server_sl, *mntlabel; 955 zone_t *mntzone = NULL; 956 ts_label_t *zlabel; 957 tsol_tpc_t *tp; 958 ts_label_t *tsl = NULL; 959 int retv; 960 961 /* 962 * Get the zone's label. Each zone on a labeled system has a label. 963 */ 964 mntzone = zone_find_by_any_path(refstr_value(vfsp->vfs_mntpt), B_FALSE); 965 zlabel = mntzone->zone_slabel; 966 ASSERT(zlabel != NULL); 967 label_hold(zlabel); 968 969 retv = EACCES; /* assume the worst */ 970 971 /* 972 * Next, get the assigned label of the remote server. 973 */ 974 tp = find_tpc(ipaddr, addr_type, B_FALSE); 975 if (tp == NULL) 976 goto out; /* error getting host entry */ 977 978 if (tp->tpc_tp.tp_doi != zlabel->tsl_doi) 979 goto rel_tpc; /* invalid domain */ 980 if ((tp->tpc_tp.host_type != UNLABELED)) 981 goto rel_tpc; /* invalid hosttype */ 982 983 server_sl = &tp->tpc_tp.tp_def_label; 984 mntlabel = label2bslabel(zlabel); 985 986 /* 987 * Now compare labels to complete the MAC check. If the labels 988 * are equal or if the requestor is in the global zone and has 989 * NET_MAC_AWARE, then allow read-write access. (Except for 990 * mounts into the global zone itself; restrict these to 991 * read-only.) 992 * 993 * If the requestor is in some other zone, but their label 994 * dominates the server, then allow read-down. 995 * 996 * Otherwise, access is denied. 997 */ 998 if (blequal(mntlabel, server_sl) || 999 (crgetzoneid(cr) == GLOBAL_ZONEID && 1000 getpflags(NET_MAC_AWARE, cr) != 0)) { 1001 if ((mntzone == global_zone) || 1002 !blequal(mntlabel, server_sl)) 1003 retv = -1; /* read-only */ 1004 else 1005 retv = 0; /* access OK */ 1006 } else if (bldominates(mntlabel, server_sl)) { 1007 retv = -1; /* read-only */ 1008 } else { 1009 retv = EACCES; 1010 } 1011 1012 if (tsl != NULL) 1013 label_rele(tsl); 1014 1015 rel_tpc: 1016 /*LINTED*/ 1017 TPC_RELE(tp); 1018 out: 1019 if (mntzone) 1020 zone_rele(mntzone); 1021 label_rele(zlabel); 1022 return (retv); 1023 } 1024