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