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