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         /* PSARC 2007/227 VFS Feature Registration */
 602         vfs_set_feature(vfsp, VFSFT_XVATTR);
 603         vfs_set_feature(vfsp, VFSFT_SYSATTR_VIEWS);
 604 
 605         /*
 606          * Create the root vnode, which we need in unmount
 607          * for the call to smbfs_check_table(), etc.
 608          * Release this hold in smbfs_unmount.
 609          */
 610         rtnp = smbfs_node_findcreate(smi, "\\", 1, NULL, 0, 0,
 611             &smbfs_fattr0);
 612         ASSERT(rtnp != NULL);
 613         rtnp->r_vnode->v_type = VDIR;
 614         rtnp->r_vnode->v_flag |= VROOT;
 615         smi->smi_root = rtnp;
 616 
 617         /*
 618          * NFS does other stuff here too:
 619          *   async worker threads
 620          *   init kstats
 621          *
 622          * End of code from NFS nfsrootvp()
 623          */
 624         return (0);
 625 
 626 errout:
 627         vfsp->vfs_data = NULL;
 628         if (smi != NULL)
 629                 smbfs_free_smi(smi);
 630 
 631         if (mntzone != NULL)
 632                 zone_rele(mntzone);
 633 
 634         if (ssp != NULL)
 635                 smb_share_rele(ssp);
 636 
 637         return (error);
 638 }
 639 
 640 /*
 641  * vfs operations
 642  */
 643 static int
 644 smbfs_unmount(vfs_t *vfsp, int flag, cred_t *cr)
 645 {
 646         smbmntinfo_t    *smi;
 647         smbnode_t       *rtnp;
 648 
 649         smi = VFTOSMI(vfsp);
 650 
 651         if (secpolicy_fs_unmount(cr, vfsp) != 0)
 652                 return (EPERM);
 653 
 654         if ((flag & MS_FORCE) == 0) {
 655                 smbfs_rflush(vfsp, cr);
 656 
 657                 /*
 658                  * If there are any active vnodes on this file system,
 659                  * (other than the root vnode) then the file system is
 660                  * busy and can't be umounted.
 661                  */
 662                 if (smbfs_check_table(vfsp, smi->smi_root))
 663                         return (EBUSY);
 664 
 665                 /*
 666                  * We normally hold a ref to the root vnode, so
 667                  * check for references beyond the one we expect:
 668                  *   smbmntinfo_t -> smi_root
 669                  * Note that NFS does not hold the root vnode.
 670                  */
 671                 if (smi->smi_root &&
 672                     smi->smi_root->r_vnode->v_count > 1)
 673                         return (EBUSY);
 674         }
 675 
 676         /*
 677          * common code for both forced and non-forced
 678          *
 679          * Setting VFS_UNMOUNTED prevents new operations.
 680          * Operations already underway may continue,
 681          * but not for long.
 682          */
 683         vfsp->vfs_flag |= VFS_UNMOUNTED;
 684 
 685         /*
 686          * Shutdown any outstanding I/O requests on this share,
 687          * and force a tree disconnect.  The share object will
 688          * continue to hang around until smb_share_rele().
 689          * This should also cause most active nodes to be
 690          * released as their operations fail with EIO.
 691          */
 692         smb_share_kill(smi->smi_share);
 693 
 694         /*
 695          * If we hold the root VP (and we normally do)
 696          * then it's safe to release it now.
 697          */
 698         if (smi->smi_root) {
 699                 rtnp = smi->smi_root;
 700                 smi->smi_root = NULL;
 701                 VN_RELE(rtnp->r_vnode);      /* release root vnode */
 702         }
 703 
 704         /*
 705          * Remove all nodes from the node hash tables.
 706          * This (indirectly) calls: smbfs_addfree, smbinactive,
 707          * which will try to flush dirty pages, etc. so
 708          * don't destroy the underlying share just yet.
 709          *
 710          * Also, with a forced unmount, some nodes may
 711          * remain active, and those will get cleaned up
 712          * after their last vn_rele.
 713          */
 714         smbfs_destroy_table(vfsp);
 715 
 716         /*
 717          * Delete our kstats...
 718          *
 719          * Doing it here, rather than waiting until
 720          * smbfs_freevfs so these are not visible
 721          * after the unmount.
 722          */
 723         if (smi->smi_io_kstats) {
 724                 kstat_delete(smi->smi_io_kstats);
 725                 smi->smi_io_kstats = NULL;
 726         }
 727         if (smi->smi_ro_kstats) {
 728                 kstat_delete(smi->smi_ro_kstats);
 729                 smi->smi_ro_kstats = NULL;
 730         }
 731 
 732         /*
 733          * The rest happens in smbfs_freevfs()
 734          */
 735         return (0);
 736 }
 737 
 738 
 739 /*
 740  * find root of smbfs
 741  */
 742 static int
 743 smbfs_root(vfs_t *vfsp, vnode_t **vpp)
 744 {
 745         smbmntinfo_t    *smi;
 746         vnode_t         *vp;
 747 
 748         smi = VFTOSMI(vfsp);
 749 
 750         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
 751                 return (EPERM);
 752 
 753         if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
 754                 return (EIO);
 755 
 756         /*
 757          * The root vp is created in mount and held
 758          * until unmount, so this is paranoia.
 759          */
 760         if (smi->smi_root == NULL)
 761                 return (EIO);
 762 
 763         /* Just take a reference and return it. */
 764         vp = SMBTOV(smi->smi_root);
 765         VN_HOLD(vp);
 766         *vpp = vp;
 767 
 768         return (0);
 769 }
 770 
 771 /*
 772  * Get file system statistics.
 773  */
 774 static int
 775 smbfs_statvfs(vfs_t *vfsp, statvfs64_t *sbp)
 776 {
 777         int             error;
 778         smbmntinfo_t    *smi = VFTOSMI(vfsp);
 779         smb_share_t     *ssp = smi->smi_share;
 780         statvfs64_t     stvfs;
 781         hrtime_t now;
 782         smb_cred_t      scred;
 783 
 784         if (curproc->p_zone != smi->smi_zone_ref.zref_zone)
 785                 return (EPERM);
 786 
 787         if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED)
 788                 return (EIO);
 789 
 790         mutex_enter(&smi->smi_lock);
 791 
 792         /*
 793          * Use cached result if still valid.
 794          */
 795 recheck:
 796         now = gethrtime();
 797         if (now < smi->smi_statfstime) {
 798                 error = 0;
 799                 goto cache_hit;
 800         }
 801 
 802         /*
 803          * FS attributes are stale, so someone
 804          * needs to do an OTW call to get them.
 805          * Serialize here so only one thread
 806          * does the OTW call.
 807          */
 808         if (smi->smi_status & SM_STATUS_STATFS_BUSY) {
 809                 smi->smi_status |= SM_STATUS_STATFS_WANT;
 810                 if (!cv_wait_sig(&smi->smi_statvfs_cv, &smi->smi_lock)) {
 811                         mutex_exit(&smi->smi_lock);
 812                         return (EINTR);
 813                 }
 814                 /* Hope status is valid now. */
 815                 goto recheck;
 816         }
 817         smi->smi_status |= SM_STATUS_STATFS_BUSY;
 818         mutex_exit(&smi->smi_lock);
 819 
 820         /*
 821          * Do the OTW call.  Note: lock NOT held.
 822          */
 823         smb_credinit(&scred, NULL);
 824         bzero(&stvfs, sizeof (stvfs));
 825         error = smbfs_smb_statfs(ssp, &stvfs, &scred);
 826         smb_credrele(&scred);
 827         if (error) {
 828                 SMBVDEBUG("statfs error=%d\n", error);
 829         } else {
 830 
 831                 /*
 832                  * Set a few things the OTW call didn't get.
 833                  */
 834                 stvfs.f_frsize = stvfs.f_bsize;
 835                 stvfs.f_favail = stvfs.f_ffree;
 836                 stvfs.f_fsid = (unsigned long)vfsp->vfs_fsid.val[0];
 837                 bcopy(fs_type_name, stvfs.f_basetype, FSTYPSZ);
 838                 stvfs.f_flag    = vf_to_stf(vfsp->vfs_flag);
 839                 stvfs.f_namemax = smi->smi_fsa.fsa_maxname;
 840 
 841                 /*
 842                  * Save the result, update lifetime
 843                  */
 844                 now = gethrtime();
 845                 smi->smi_statfstime = now +
 846                     (SM_MAX_STATFSTIME * (hrtime_t)NANOSEC);
 847                 smi->smi_statvfsbuf = stvfs; /* struct assign! */
 848         }
 849 
 850         mutex_enter(&smi->smi_lock);
 851         if (smi->smi_status & SM_STATUS_STATFS_WANT)
 852                 cv_broadcast(&smi->smi_statvfs_cv);
 853         smi->smi_status &= ~(SM_STATUS_STATFS_BUSY | SM_STATUS_STATFS_WANT);
 854 
 855         /*
 856          * Copy the statvfs data to caller's buf.
 857          * Note: struct assignment
 858          */
 859 cache_hit:
 860         if (error == 0)
 861                 *sbp = smi->smi_statvfsbuf;
 862         mutex_exit(&smi->smi_lock);
 863         return (error);
 864 }
 865 
 866 static kmutex_t smbfs_syncbusy;
 867 
 868 /*
 869  * Flush dirty smbfs files for file system vfsp.
 870  * If vfsp == NULL, all smbfs files are flushed.
 871  */
 872 /*ARGSUSED*/
 873 static int
 874 smbfs_sync(vfs_t *vfsp, short flag, cred_t *cr)
 875 {
 876         /*
 877          * Cross-zone calls are OK here, since this translates to a
 878          * VOP_PUTPAGE(B_ASYNC), which gets picked up by the right zone.
 879          */
 880         if (!(flag & SYNC_ATTR) && mutex_tryenter(&smbfs_syncbusy) != 0) {
 881                 smbfs_rflush(vfsp, cr);
 882                 mutex_exit(&smbfs_syncbusy);
 883         }
 884 
 885         return (0);
 886 }
 887 
 888 /*
 889  * Initialization routine for VFS routines.  Should only be called once
 890  */
 891 int
 892 smbfs_vfsinit(void)
 893 {
 894         mutex_init(&smbfs_syncbusy, NULL, MUTEX_DEFAULT, NULL);
 895         return (0);
 896 }
 897 
 898 /*
 899  * Shutdown routine for VFS routines.  Should only be called once
 900  */
 901 void
 902 smbfs_vfsfini(void)
 903 {
 904         mutex_destroy(&smbfs_syncbusy);
 905 }
 906 
 907 void
 908 smbfs_freevfs(vfs_t *vfsp)
 909 {
 910         smbmntinfo_t    *smi;
 911 
 912         /* free up the resources */
 913         smi = VFTOSMI(vfsp);
 914 
 915         /*
 916          * By this time we should have already deleted the
 917          * smi kstats in the unmount code.  If they are still around
 918          * something is wrong
 919          */
 920         ASSERT(smi->smi_io_kstats == NULL);
 921 
 922         smbfs_zonelist_remove(smi);
 923 
 924         smbfs_free_smi(smi);
 925 
 926         /*
 927          * Allow _fini() to succeed now, if so desired.
 928          */
 929         atomic_dec_32(&smbfs_mountcount);
 930 }
 931 
 932 /*
 933  * smbfs_mount_label_policy:
 934  *      Determine whether the mount is allowed according to MAC check,
 935  *      by comparing (where appropriate) label of the remote server
 936  *      against the label of the zone being mounted into.
 937  *
 938  *      Returns:
 939  *               0 :    access allowed
 940  *              -1 :    read-only access allowed (i.e., read-down)
 941  *              >0 : error code, such as EACCES
 942  *
 943  * NB:
 944  * NFS supports Cipso labels by parsing the vfs_resource
 945  * to see what the Solaris server global zone has shared.
 946  * We can't support that for CIFS since resource names
 947  * contain share names, not paths.
 948  */
 949 static int
 950 smbfs_mount_label_policy(vfs_t *vfsp, void *ipaddr, int addr_type, cred_t *cr)
 951 {
 952         bslabel_t       *server_sl, *mntlabel;
 953         zone_t          *mntzone = NULL;
 954         ts_label_t      *zlabel;
 955         tsol_tpc_t      *tp;
 956         ts_label_t      *tsl = NULL;
 957         int             retv;
 958 
 959         /*
 960          * Get the zone's label.  Each zone on a labeled system has a label.
 961          */
 962         mntzone = zone_find_by_any_path(refstr_value(vfsp->vfs_mntpt), B_FALSE);
 963         zlabel = mntzone->zone_slabel;
 964         ASSERT(zlabel != NULL);
 965         label_hold(zlabel);
 966 
 967         retv = EACCES;                          /* assume the worst */
 968 
 969         /*
 970          * Next, get the assigned label of the remote server.
 971          */
 972         tp = find_tpc(ipaddr, addr_type, B_FALSE);
 973         if (tp == NULL)
 974                 goto out;                       /* error getting host entry */
 975 
 976         if (tp->tpc_tp.tp_doi != zlabel->tsl_doi)
 977                 goto rel_tpc;                   /* invalid domain */
 978         if ((tp->tpc_tp.host_type != UNLABELED))
 979                 goto rel_tpc;                   /* invalid hosttype */
 980 
 981         server_sl = &tp->tpc_tp.tp_def_label;
 982         mntlabel = label2bslabel(zlabel);
 983 
 984         /*
 985          * Now compare labels to complete the MAC check.  If the labels
 986          * are equal or if the requestor is in the global zone and has
 987          * NET_MAC_AWARE, then allow read-write access.   (Except for
 988          * mounts into the global zone itself; restrict these to
 989          * read-only.)
 990          *
 991          * If the requestor is in some other zone, but his label
 992          * dominates the server, then allow read-down.
 993          *
 994          * Otherwise, access is denied.
 995          */
 996         if (blequal(mntlabel, server_sl) ||
 997             (crgetzoneid(cr) == GLOBAL_ZONEID &&
 998             getpflags(NET_MAC_AWARE, cr) != 0)) {
 999                 if ((mntzone == global_zone) ||
1000                     !blequal(mntlabel, server_sl))
1001                         retv = -1;              /* read-only */
1002                 else
1003                         retv = 0;               /* access OK */
1004         } else if (bldominates(mntlabel, server_sl)) {
1005                 retv = -1;                      /* read-only */
1006         } else {
1007                 retv = EACCES;
1008         }
1009 
1010         if (tsl != NULL)
1011                 label_rele(tsl);
1012 
1013 rel_tpc:
1014         /*LINTED*/
1015         TPC_RELE(tp);
1016 out:
1017         if (mntzone)
1018                 zone_rele(mntzone);
1019         label_rele(zlabel);
1020         return (retv);
1021 }