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 }