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_vnops.c,v 1.128.36.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/vnode.h> 42 #include <sys/vfs.h> 43 #include <sys/filio.h> 44 #include <sys/uio.h> 45 #include <sys/dirent.h> 46 #include <sys/errno.h> 47 #include <sys/sunddi.h> 48 #include <sys/sysmacros.h> 49 #include <sys/kmem.h> 50 #include <sys/cmn_err.h> 51 #include <sys/vfs_opreg.h> 52 #include <sys/policy.h> 53 54 #include <netsmb/smb_osdep.h> 55 #include <netsmb/smb.h> 56 #include <netsmb/smb_conn.h> 57 #include <netsmb/smb_subr.h> 58 59 #include <smbfs/smbfs.h> 60 #include <smbfs/smbfs_node.h> 61 #include <smbfs/smbfs_subr.h> 62 63 #include <sys/fs/smbfs_ioctl.h> 64 #include <fs/fs_subr.h> 65 66 /* 67 * We assign directory offsets like the NFS client, where the 68 * offset increments by _one_ after each directory entry. 69 * Further, the entries "." and ".." are always at offsets 70 * zero and one (respectively) and the "real" entries from 71 * the server appear at offsets starting with two. This 72 * macro is used to initialize the n_dirofs field after 73 * setting n_dirseq with a _findopen call. 74 */ 75 #define FIRST_DIROFS 2 76 77 /* 78 * These characters are illegal in NTFS file names. 79 * ref: http://support.microsoft.com/kb/147438 80 * 81 * Careful! The check in the XATTR case skips the 82 * first character to allow colon in XATTR names. 83 */ 84 static const char illegal_chars[] = { 85 ':', /* colon - keep this first! */ 86 '\\', /* back slash */ 87 '/', /* slash */ 88 '*', /* asterisk */ 89 '?', /* question mark */ 90 '"', /* double quote */ 91 '<', /* less than sign */ 92 '>', /* greater than sign */ 93 '|', /* vertical bar */ 94 0 95 }; 96 97 /* 98 * Turning this on causes nodes to be created in the cache 99 * during directory listings, normally avoiding a second 100 * OtW attribute fetch just after a readdir. 101 */ 102 int smbfs_fastlookup = 1; 103 104 /* local static function defines */ 105 106 static int smbfslookup_cache(vnode_t *, char *, int, vnode_t **, 107 cred_t *); 108 static int smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr, 109 int cache_ok, caller_context_t *); 110 static int smbfsremove(vnode_t *dvp, vnode_t *vp, struct smb_cred *scred, 111 int flags); 112 static int smbfsrename(vnode_t *odvp, vnode_t *ovp, vnode_t *ndvp, 113 char *nnm, struct smb_cred *scred, int flags); 114 static int smbfssetattr(vnode_t *, struct vattr *, int, cred_t *); 115 static int smbfs_accessx(void *, int, cred_t *); 116 static int smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp, 117 caller_context_t *); 118 static void smbfs_rele_fid(smbnode_t *, struct smb_cred *); 119 static uint32_t xvattr_to_dosattr(smbnode_t *, struct vattr *); 120 121 /* 122 * These are the vnode ops routines which implement the vnode interface to 123 * the networked file system. These routines just take their parameters, 124 * make them look networkish by putting the right info into interface structs, 125 * and then calling the appropriate remote routine(s) to do the work. 126 * 127 * Note on directory name lookup cacheing: If we detect a stale fhandle, 128 * we purge the directory cache relative to that vnode. This way, the 129 * user won't get burned by the cache repeatedly. See <smbfs/smbnode.h> for 130 * more details on smbnode locking. 131 */ 132 133 static int smbfs_open(vnode_t **, int, cred_t *, caller_context_t *); 134 static int smbfs_close(vnode_t *, int, int, offset_t, cred_t *, 135 caller_context_t *); 136 static int smbfs_read(vnode_t *, struct uio *, int, cred_t *, 137 caller_context_t *); 138 static int smbfs_write(vnode_t *, struct uio *, int, cred_t *, 139 caller_context_t *); 140 static int smbfs_ioctl(vnode_t *, int, intptr_t, int, cred_t *, int *, 141 caller_context_t *); 142 static int smbfs_getattr(vnode_t *, struct vattr *, int, cred_t *, 143 caller_context_t *); 144 static int smbfs_setattr(vnode_t *, struct vattr *, int, cred_t *, 145 caller_context_t *); 146 static int smbfs_access(vnode_t *, int, int, cred_t *, caller_context_t *); 147 static int smbfs_fsync(vnode_t *, int, cred_t *, caller_context_t *); 148 static void smbfs_inactive(vnode_t *, cred_t *, caller_context_t *); 149 static int smbfs_lookup(vnode_t *, char *, vnode_t **, struct pathname *, 150 int, vnode_t *, cred_t *, caller_context_t *, 151 int *, pathname_t *); 152 static int smbfs_create(vnode_t *, char *, struct vattr *, enum vcexcl, 153 int, vnode_t **, cred_t *, int, caller_context_t *, 154 vsecattr_t *); 155 static int smbfs_remove(vnode_t *, char *, cred_t *, caller_context_t *, 156 int); 157 static int smbfs_rename(vnode_t *, char *, vnode_t *, char *, cred_t *, 158 caller_context_t *, int); 159 static int smbfs_mkdir(vnode_t *, char *, struct vattr *, vnode_t **, 160 cred_t *, caller_context_t *, int, vsecattr_t *); 161 static int smbfs_rmdir(vnode_t *, char *, vnode_t *, cred_t *, 162 caller_context_t *, int); 163 static int smbfs_readdir(vnode_t *, struct uio *, cred_t *, int *, 164 caller_context_t *, int); 165 static int smbfs_rwlock(vnode_t *, int, caller_context_t *); 166 static void smbfs_rwunlock(vnode_t *, int, caller_context_t *); 167 static int smbfs_seek(vnode_t *, offset_t, offset_t *, caller_context_t *); 168 static int smbfs_frlock(vnode_t *, int, struct flock64 *, int, offset_t, 169 struct flk_callback *, cred_t *, caller_context_t *); 170 static int smbfs_space(vnode_t *, int, struct flock64 *, int, offset_t, 171 cred_t *, caller_context_t *); 172 static int smbfs_pathconf(vnode_t *, int, ulong_t *, cred_t *, 173 caller_context_t *); 174 static int smbfs_setsecattr(vnode_t *, vsecattr_t *, int, cred_t *, 175 caller_context_t *); 176 static int smbfs_getsecattr(vnode_t *, vsecattr_t *, int, cred_t *, 177 caller_context_t *); 178 static int smbfs_shrlock(vnode_t *, int, struct shrlock *, int, cred_t *, 179 caller_context_t *); 180 181 /* Dummy function to use until correct function is ported in */ 182 int noop_vnodeop() { 183 return (0); 184 } 185 186 struct vnodeops *smbfs_vnodeops = NULL; 187 188 /* 189 * Most unimplemented ops will return ENOSYS because of fs_nosys(). 190 * The only ops where that won't work are ACCESS (due to open(2) 191 * failures) and ... (anything else left?) 192 */ 193 const fs_operation_def_t smbfs_vnodeops_template[] = { 194 { VOPNAME_OPEN, { .vop_open = smbfs_open } }, 195 { VOPNAME_CLOSE, { .vop_close = smbfs_close } }, 196 { VOPNAME_READ, { .vop_read = smbfs_read } }, 197 { VOPNAME_WRITE, { .vop_write = smbfs_write } }, 198 { VOPNAME_IOCTL, { .vop_ioctl = smbfs_ioctl } }, 199 { VOPNAME_GETATTR, { .vop_getattr = smbfs_getattr } }, 200 { VOPNAME_SETATTR, { .vop_setattr = smbfs_setattr } }, 201 { VOPNAME_ACCESS, { .vop_access = smbfs_access } }, 202 { VOPNAME_LOOKUP, { .vop_lookup = smbfs_lookup } }, 203 { VOPNAME_CREATE, { .vop_create = smbfs_create } }, 204 { VOPNAME_REMOVE, { .vop_remove = smbfs_remove } }, 205 { VOPNAME_LINK, { .error = fs_nosys } }, /* smbfs_link, */ 206 { VOPNAME_RENAME, { .vop_rename = smbfs_rename } }, 207 { VOPNAME_MKDIR, { .vop_mkdir = smbfs_mkdir } }, 208 { VOPNAME_RMDIR, { .vop_rmdir = smbfs_rmdir } }, 209 { VOPNAME_READDIR, { .vop_readdir = smbfs_readdir } }, 210 { VOPNAME_SYMLINK, { .error = fs_nosys } }, /* smbfs_symlink, */ 211 { VOPNAME_READLINK, { .error = fs_nosys } }, /* smbfs_readlink, */ 212 { VOPNAME_FSYNC, { .vop_fsync = smbfs_fsync } }, 213 { VOPNAME_INACTIVE, { .vop_inactive = smbfs_inactive } }, 214 { VOPNAME_FID, { .error = fs_nosys } }, /* smbfs_fid, */ 215 { VOPNAME_RWLOCK, { .vop_rwlock = smbfs_rwlock } }, 216 { VOPNAME_RWUNLOCK, { .vop_rwunlock = smbfs_rwunlock } }, 217 { VOPNAME_SEEK, { .vop_seek = smbfs_seek } }, 218 { VOPNAME_FRLOCK, { .vop_frlock = smbfs_frlock } }, 219 { VOPNAME_SPACE, { .vop_space = smbfs_space } }, 220 { VOPNAME_REALVP, { .error = fs_nosys } }, /* smbfs_realvp, */ 221 { VOPNAME_GETPAGE, { .error = fs_nosys } }, /* smbfs_getpage, */ 222 { VOPNAME_PUTPAGE, { .error = fs_nosys } }, /* smbfs_putpage, */ 223 { VOPNAME_MAP, { .error = fs_nosys } }, /* smbfs_map, */ 224 { VOPNAME_ADDMAP, { .error = fs_nosys } }, /* smbfs_addmap, */ 225 { VOPNAME_DELMAP, { .error = fs_nosys } }, /* smbfs_delmap, */ 226 { VOPNAME_DUMP, { .error = fs_nosys } }, /* smbfs_dump, */ 227 { VOPNAME_PATHCONF, { .vop_pathconf = smbfs_pathconf } }, 228 { VOPNAME_PAGEIO, { .error = fs_nosys } }, /* smbfs_pageio, */ 229 { VOPNAME_SETSECATTR, { .vop_setsecattr = smbfs_setsecattr } }, 230 { VOPNAME_GETSECATTR, { .vop_getsecattr = smbfs_getsecattr } }, 231 { VOPNAME_SHRLOCK, { .vop_shrlock = smbfs_shrlock } }, 232 { NULL, NULL } 233 }; 234 235 /* 236 * XXX 237 * When new and relevant functionality is enabled, we should be 238 * calling vfs_set_feature() to inform callers that pieces of 239 * functionality are available, per PSARC 2007/227. 240 */ 241 /* ARGSUSED */ 242 static int 243 smbfs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct) 244 { 245 smbnode_t *np; 246 vnode_t *vp; 247 smbfattr_t fa; 248 u_int32_t rights, rightsrcvd; 249 u_int16_t fid, oldfid; 250 int oldgenid; 251 struct smb_cred scred; 252 smbmntinfo_t *smi; 253 smb_share_t *ssp; 254 cred_t *oldcr; 255 int tmperror; 256 int error = 0; 257 258 vp = *vpp; 259 np = VTOSMB(vp); 260 smi = VTOSMI(vp); 261 ssp = smi->smi_share; 262 263 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 264 return (EIO); 265 266 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 267 return (EIO); 268 269 if (vp->v_type != VREG && vp->v_type != VDIR) { /* XXX VLNK? */ 270 SMBVDEBUG("open eacces vtype=%d\n", vp->v_type); 271 return (EACCES); 272 } 273 274 /* 275 * Get exclusive access to n_fid and related stuff. 276 * No returns after this until out. 277 */ 278 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp))) 279 return (EINTR); 280 smb_credinit(&scred, cr); 281 282 /* 283 * Keep track of the vnode type at first open. 284 * It may change later, and we need close to do 285 * cleanup for the type we opened. Also deny 286 * open of new types until old type is closed. 287 * XXX: Per-open instance nodes whould help. 288 */ 289 if (np->n_ovtype == VNON) { 290 ASSERT(np->n_dirrefs == 0); 291 ASSERT(np->n_fidrefs == 0); 292 } else if (np->n_ovtype != vp->v_type) { 293 SMBVDEBUG("open n_ovtype=%d v_type=%d\n", 294 np->n_ovtype, vp->v_type); 295 error = EACCES; 296 goto out; 297 } 298 299 /* 300 * Directory open. See smbfs_readvdir() 301 */ 302 if (vp->v_type == VDIR) { 303 if (np->n_dirseq == NULL) { 304 /* first open */ 305 error = smbfs_smb_findopen(np, "*", 1, 306 SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, 307 &scred, &np->n_dirseq); 308 if (error != 0) 309 goto out; 310 } 311 np->n_dirofs = FIRST_DIROFS; 312 np->n_dirrefs++; 313 goto have_fid; 314 } 315 316 /* 317 * If caller specified O_TRUNC/FTRUNC, then be sure to set 318 * FWRITE (to drive successful setattr(size=0) after open) 319 */ 320 if (flag & FTRUNC) 321 flag |= FWRITE; 322 323 /* 324 * If we already have it open, and the FID is still valid, 325 * check whether the rights are sufficient for FID reuse. 326 */ 327 if (np->n_fidrefs > 0 && 328 np->n_vcgenid == ssp->ss_vcgenid) { 329 int upgrade = 0; 330 331 if ((flag & FWRITE) && 332 !(np->n_rights & SA_RIGHT_FILE_WRITE_DATA)) 333 upgrade = 1; 334 if ((flag & FREAD) && 335 !(np->n_rights & SA_RIGHT_FILE_READ_DATA)) 336 upgrade = 1; 337 if (!upgrade) { 338 /* 339 * the existing open is good enough 340 */ 341 np->n_fidrefs++; 342 goto have_fid; 343 } 344 } 345 rights = np->n_fidrefs ? np->n_rights : 0; 346 347 /* 348 * we always ask for READ_CONTROL so we can always get the 349 * owner/group IDs to satisfy a stat. Ditto attributes. 350 */ 351 rights |= (STD_RIGHT_READ_CONTROL_ACCESS | 352 SA_RIGHT_FILE_READ_ATTRIBUTES); 353 if ((flag & FREAD)) 354 rights |= SA_RIGHT_FILE_READ_DATA; 355 if ((flag & FWRITE)) 356 rights |= SA_RIGHT_FILE_WRITE_DATA | 357 SA_RIGHT_FILE_APPEND_DATA | 358 SA_RIGHT_FILE_WRITE_ATTRIBUTES; 359 360 bzero(&fa, sizeof (fa)); 361 error = smbfs_smb_open(np, 362 NULL, 0, 0, /* name nmlen xattr */ 363 rights, &scred, 364 &fid, &rightsrcvd, &fa); 365 if (error) 366 goto out; 367 smbfs_attrcache_fa(vp, &fa); 368 369 /* 370 * We have a new FID and access rights. 371 */ 372 oldfid = np->n_fid; 373 oldgenid = np->n_vcgenid; 374 np->n_fid = fid; 375 np->n_vcgenid = ssp->ss_vcgenid; 376 np->n_rights = rightsrcvd; 377 np->n_fidrefs++; 378 if (np->n_fidrefs > 1 && 379 oldgenid == ssp->ss_vcgenid) { 380 /* 381 * We already had it open (presumably because 382 * it was open with insufficient rights.) 383 * Close old wire-open. 384 */ 385 tmperror = smbfs_smb_close(ssp, 386 oldfid, NULL, &scred); 387 if (tmperror) 388 SMBVDEBUG("error %d closing %s\n", 389 tmperror, np->n_rpath); 390 } 391 392 /* 393 * This thread did the open. 394 * Save our credentials too. 395 */ 396 mutex_enter(&np->r_statelock); 397 oldcr = np->r_cred; 398 np->r_cred = cr; 399 crhold(cr); 400 if (oldcr) 401 crfree(oldcr); 402 mutex_exit(&np->r_statelock); 403 404 have_fid: 405 /* 406 * Keep track of the vnode type at first open. 407 * (see comments above) 408 */ 409 if (np->n_ovtype == VNON) 410 np->n_ovtype = vp->v_type; 411 412 out: 413 smb_credrele(&scred); 414 smbfs_rw_exit(&np->r_lkserlock); 415 return (error); 416 } 417 418 /*ARGSUSED*/ 419 static int 420 smbfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr, 421 caller_context_t *ct) 422 { 423 smbnode_t *np; 424 smbmntinfo_t *smi; 425 struct smb_cred scred; 426 427 np = VTOSMB(vp); 428 smi = VTOSMI(vp); 429 430 /* 431 * Don't "bail out" for VFS_UNMOUNTED here, 432 * as we want to do cleanup, etc. 433 */ 434 435 /* 436 * zone_enter(2) prevents processes from changing zones with SMBFS files 437 * open; if we happen to get here from the wrong zone we can't do 438 * anything over the wire. 439 */ 440 if (smi->smi_zone_ref.zref_zone != curproc->p_zone) { 441 /* 442 * We could attempt to clean up locks, except we're sure 443 * that the current process didn't acquire any locks on 444 * the file: any attempt to lock a file belong to another zone 445 * will fail, and one can't lock an SMBFS file and then change 446 * zones, as that fails too. 447 * 448 * Returning an error here is the sane thing to do. A 449 * subsequent call to VN_RELE() which translates to a 450 * smbfs_inactive() will clean up state: if the zone of the 451 * vnode's origin is still alive and kicking, an async worker 452 * thread will handle the request (from the correct zone), and 453 * everything (minus the final smbfs_getattr_otw() call) should 454 * be OK. If the zone is going away smbfs_async_inactive() will 455 * throw away cached pages inline. 456 */ 457 return (EIO); 458 } 459 460 /* 461 * If we are using local locking for this filesystem, then 462 * release all of the SYSV style record locks. Otherwise, 463 * we are doing network locking and we need to release all 464 * of the network locks. All of the locks held by this 465 * process on this file are released no matter what the 466 * incoming reference count is. 467 */ 468 if (smi->smi_flags & SMI_LLOCK) { 469 pid_t pid = ddi_get_pid(); 470 cleanlocks(vp, pid, 0); 471 cleanshares(vp, pid); 472 } 473 474 /* 475 * This (passed in) count is the ref. count from the 476 * user's file_t before the closef call (fio.c). 477 * We only care when the reference goes away. 478 */ 479 if (count > 1) 480 return (0); 481 482 /* 483 * Decrement the reference count for the FID 484 * and possibly do the OtW close. 485 * 486 * Exclusive lock for modifying n_fid stuff. 487 * Don't want this one ever interruptible. 488 */ 489 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0); 490 smb_credinit(&scred, cr); 491 492 smbfs_rele_fid(np, &scred); 493 494 smb_credrele(&scred); 495 smbfs_rw_exit(&np->r_lkserlock); 496 497 return (0); 498 } 499 500 /* 501 * Helper for smbfs_close. Decrement the reference count 502 * for an SMB-level file or directory ID, and when the last 503 * reference for the fid goes away, do the OtW close. 504 * Also called in smbfs_inactive (defensive cleanup). 505 */ 506 static void 507 smbfs_rele_fid(smbnode_t *np, struct smb_cred *scred) 508 { 509 smb_share_t *ssp; 510 cred_t *oldcr; 511 struct smbfs_fctx *fctx; 512 int error; 513 uint16_t ofid; 514 515 ssp = np->n_mount->smi_share; 516 error = 0; 517 518 /* Make sure we serialize for n_dirseq use. */ 519 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_WRITER)); 520 521 /* 522 * Note that vp->v_type may change if a remote node 523 * is deleted and recreated as a different type, and 524 * our getattr may change v_type accordingly. 525 * Now use n_ovtype to keep track of the v_type 526 * we had during open (see comments above). 527 */ 528 switch (np->n_ovtype) { 529 case VDIR: 530 ASSERT(np->n_dirrefs > 0); 531 if (--np->n_dirrefs) 532 return; 533 if ((fctx = np->n_dirseq) != NULL) { 534 np->n_dirseq = NULL; 535 np->n_dirofs = 0; 536 error = smbfs_smb_findclose(fctx, scred); 537 } 538 break; 539 540 case VREG: 541 ASSERT(np->n_fidrefs > 0); 542 if (--np->n_fidrefs) 543 return; 544 if ((ofid = np->n_fid) != SMB_FID_UNUSED) { 545 np->n_fid = SMB_FID_UNUSED; 546 /* After reconnect, n_fid is invalid */ 547 if (np->n_vcgenid == ssp->ss_vcgenid) { 548 error = smbfs_smb_close( 549 ssp, ofid, NULL, scred); 550 } 551 } 552 break; 553 554 default: 555 SMBVDEBUG("bad n_ovtype %d\n", np->n_ovtype); 556 break; 557 } 558 if (error) { 559 SMBVDEBUG("error %d closing %s\n", 560 error, np->n_rpath); 561 } 562 563 /* Allow next open to use any v_type. */ 564 np->n_ovtype = VNON; 565 566 /* 567 * Other "last close" stuff. 568 */ 569 mutex_enter(&np->r_statelock); 570 if (np->n_flag & NATTRCHANGED) 571 smbfs_attrcache_rm_locked(np); 572 oldcr = np->r_cred; 573 np->r_cred = NULL; 574 mutex_exit(&np->r_statelock); 575 if (oldcr != NULL) 576 crfree(oldcr); 577 } 578 579 /* ARGSUSED */ 580 static int 581 smbfs_read(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr, 582 caller_context_t *ct) 583 { 584 struct smb_cred scred; 585 struct vattr va; 586 smbnode_t *np; 587 smbmntinfo_t *smi; 588 smb_share_t *ssp; 589 offset_t endoff; 590 ssize_t past_eof; 591 int error; 592 593 np = VTOSMB(vp); 594 smi = VTOSMI(vp); 595 ssp = smi->smi_share; 596 597 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 598 return (EIO); 599 600 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 601 return (EIO); 602 603 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER)); 604 605 if (vp->v_type != VREG) 606 return (EISDIR); 607 608 if (uiop->uio_resid == 0) 609 return (0); 610 611 /* 612 * Like NFS3, just check for 63-bit overflow. 613 * Our SMB layer takes care to return EFBIG 614 * when it has to fallback to a 32-bit call. 615 */ 616 endoff = uiop->uio_loffset + uiop->uio_resid; 617 if (uiop->uio_loffset < 0 || endoff < 0) 618 return (EINVAL); 619 620 /* get vnode attributes from server */ 621 va.va_mask = AT_SIZE | AT_MTIME; 622 if (error = smbfsgetattr(vp, &va, cr)) 623 return (error); 624 625 /* Update mtime with mtime from server here? */ 626 627 /* if offset is beyond EOF, read nothing */ 628 if (uiop->uio_loffset >= va.va_size) 629 return (0); 630 631 /* 632 * Limit the read to the remaining file size. 633 * Do this by temporarily reducing uio_resid 634 * by the amount the lies beyoned the EOF. 635 */ 636 if (endoff > va.va_size) { 637 past_eof = (ssize_t)(endoff - va.va_size); 638 uiop->uio_resid -= past_eof; 639 } else 640 past_eof = 0; 641 642 /* Shared lock for n_fid use in smb_rwuio */ 643 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 644 return (EINTR); 645 smb_credinit(&scred, cr); 646 647 /* After reconnect, n_fid is invalid */ 648 if (np->n_vcgenid != ssp->ss_vcgenid) 649 error = ESTALE; 650 else 651 error = smb_rwuio(ssp, np->n_fid, UIO_READ, 652 uiop, &scred, smb_timo_read); 653 654 smb_credrele(&scred); 655 smbfs_rw_exit(&np->r_lkserlock); 656 657 /* undo adjustment of resid */ 658 uiop->uio_resid += past_eof; 659 660 return (error); 661 } 662 663 664 /* ARGSUSED */ 665 static int 666 smbfs_write(vnode_t *vp, struct uio *uiop, int ioflag, cred_t *cr, 667 caller_context_t *ct) 668 { 669 struct smb_cred scred; 670 struct vattr va; 671 smbnode_t *np; 672 smbmntinfo_t *smi; 673 smb_share_t *ssp; 674 offset_t endoff, limit; 675 ssize_t past_limit; 676 int error, timo; 677 678 np = VTOSMB(vp); 679 smi = VTOSMI(vp); 680 ssp = smi->smi_share; 681 682 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 683 return (EIO); 684 685 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 686 return (EIO); 687 688 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_WRITER)); 689 690 if (vp->v_type != VREG) 691 return (EISDIR); 692 693 if (uiop->uio_resid == 0) 694 return (0); 695 696 /* 697 * Handle ioflag bits: (FAPPEND|FSYNC|FDSYNC) 698 */ 699 if (ioflag & (FAPPEND | FSYNC)) { 700 if (np->n_flag & NMODIFIED) { 701 smbfs_attrcache_remove(np); 702 /* XXX: smbfs_vinvalbuf? */ 703 } 704 } 705 if (ioflag & FAPPEND) { 706 /* 707 * File size can be changed by another client 708 */ 709 va.va_mask = AT_SIZE; 710 if (error = smbfsgetattr(vp, &va, cr)) 711 return (error); 712 uiop->uio_loffset = va.va_size; 713 } 714 715 /* 716 * Like NFS3, just check for 63-bit overflow. 717 */ 718 endoff = uiop->uio_loffset + uiop->uio_resid; 719 if (uiop->uio_loffset < 0 || endoff < 0) 720 return (EINVAL); 721 722 /* 723 * Check to make sure that the process will not exceed 724 * its limit on file size. It is okay to write up to 725 * the limit, but not beyond. Thus, the write which 726 * reaches the limit will be short and the next write 727 * will return an error. 728 * 729 * So if we're starting at or beyond the limit, EFBIG. 730 * Otherwise, temporarily reduce resid to the amount 731 * the falls after the limit. 732 */ 733 limit = uiop->uio_llimit; 734 if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T) 735 limit = MAXOFFSET_T; 736 if (uiop->uio_loffset >= limit) 737 return (EFBIG); 738 if (endoff > limit) { 739 past_limit = (ssize_t)(endoff - limit); 740 uiop->uio_resid -= past_limit; 741 } else 742 past_limit = 0; 743 744 /* Timeout: longer for append. */ 745 timo = smb_timo_write; 746 if (endoff > np->r_size) 747 timo = smb_timo_append; 748 749 /* Shared lock for n_fid use in smb_rwuio */ 750 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 751 return (EINTR); 752 smb_credinit(&scred, cr); 753 754 /* After reconnect, n_fid is invalid */ 755 if (np->n_vcgenid != ssp->ss_vcgenid) 756 error = ESTALE; 757 else 758 error = smb_rwuio(ssp, np->n_fid, UIO_WRITE, 759 uiop, &scred, timo); 760 761 if (error == 0) { 762 mutex_enter(&np->r_statelock); 763 np->n_flag |= (NFLUSHWIRE | NATTRCHANGED); 764 if (uiop->uio_loffset > (offset_t)np->r_size) 765 np->r_size = (len_t)uiop->uio_loffset; 766 mutex_exit(&np->r_statelock); 767 if (ioflag & (FSYNC|FDSYNC)) { 768 /* Don't error the I/O if this fails. */ 769 (void) smbfs_smb_flush(np, &scred); 770 } 771 } 772 773 smb_credrele(&scred); 774 smbfs_rw_exit(&np->r_lkserlock); 775 776 /* undo adjustment of resid */ 777 uiop->uio_resid += past_limit; 778 779 return (error); 780 } 781 782 783 /* ARGSUSED */ 784 static int 785 smbfs_ioctl(vnode_t *vp, int cmd, intptr_t arg, int flag, 786 cred_t *cr, int *rvalp, caller_context_t *ct) 787 { 788 int error; 789 smbmntinfo_t *smi; 790 791 smi = VTOSMI(vp); 792 793 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 794 return (EIO); 795 796 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 797 return (EIO); 798 799 switch (cmd) { 800 /* First three from ZFS. XXX - need these? */ 801 802 case _FIOFFS: 803 error = smbfs_fsync(vp, 0, cr, ct); 804 break; 805 806 /* 807 * The following two ioctls are used by bfu. 808 * Silently ignore to avoid bfu errors. 809 */ 810 case _FIOGDIO: 811 case _FIOSDIO: 812 error = 0; 813 break; 814 815 #ifdef NOT_YET /* XXX - from the NFS code. */ 816 case _FIODIRECTIO: 817 error = smbfs_directio(vp, (int)arg, cr); 818 #endif 819 820 /* 821 * Allow get/set with "raw" security descriptor (SD) data. 822 * Useful for testing, diagnosing idmap problems, etc. 823 */ 824 case SMBFSIO_GETSD: 825 error = smbfs_acl_iocget(vp, arg, flag, cr); 826 break; 827 828 case SMBFSIO_SETSD: 829 error = smbfs_acl_iocset(vp, arg, flag, cr); 830 break; 831 832 default: 833 error = ENOTTY; 834 break; 835 } 836 837 return (error); 838 } 839 840 841 /* 842 * Return either cached or remote attributes. If get remote attr 843 * use them to check and invalidate caches, then cache the new attributes. 844 */ 845 /* ARGSUSED */ 846 static int 847 smbfs_getattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr, 848 caller_context_t *ct) 849 { 850 smbnode_t *np; 851 smbmntinfo_t *smi; 852 853 smi = VTOSMI(vp); 854 855 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 856 return (EIO); 857 858 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 859 return (EIO); 860 861 /* 862 * If it has been specified that the return value will 863 * just be used as a hint, and we are only being asked 864 * for size, fsid or rdevid, then return the client's 865 * notion of these values without checking to make sure 866 * that the attribute cache is up to date. 867 * The whole point is to avoid an over the wire GETATTR 868 * call. 869 */ 870 np = VTOSMB(vp); 871 if (flags & ATTR_HINT) { 872 if (vap->va_mask == 873 (vap->va_mask & (AT_SIZE | AT_FSID | AT_RDEV))) { 874 mutex_enter(&np->r_statelock); 875 if (vap->va_mask | AT_SIZE) 876 vap->va_size = np->r_size; 877 if (vap->va_mask | AT_FSID) 878 vap->va_fsid = vp->v_vfsp->vfs_dev; 879 if (vap->va_mask | AT_RDEV) 880 vap->va_rdev = vp->v_rdev; 881 mutex_exit(&np->r_statelock); 882 return (0); 883 } 884 } 885 886 return (smbfsgetattr(vp, vap, cr)); 887 } 888 889 /* smbfsgetattr() in smbfs_client.c */ 890 891 /*ARGSUSED4*/ 892 static int 893 smbfs_setattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr, 894 caller_context_t *ct) 895 { 896 vfs_t *vfsp; 897 smbmntinfo_t *smi; 898 int error; 899 uint_t mask; 900 struct vattr oldva; 901 902 vfsp = vp->v_vfsp; 903 smi = VFTOSMI(vfsp); 904 905 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 906 return (EIO); 907 908 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 909 return (EIO); 910 911 mask = vap->va_mask; 912 if (mask & AT_NOSET) 913 return (EINVAL); 914 915 if (vfsp->vfs_flag & VFS_RDONLY) 916 return (EROFS); 917 918 /* 919 * This is a _local_ access check so that only the owner of 920 * this mount can set attributes. With ACLs enabled, the 921 * file owner can be different from the mount owner, and we 922 * need to check the _mount_ owner here. See _access_rwx 923 */ 924 bzero(&oldva, sizeof (oldva)); 925 oldva.va_mask = AT_TYPE | AT_MODE; 926 error = smbfsgetattr(vp, &oldva, cr); 927 if (error) 928 return (error); 929 oldva.va_mask |= AT_UID | AT_GID; 930 oldva.va_uid = smi->smi_uid; 931 oldva.va_gid = smi->smi_gid; 932 933 error = secpolicy_vnode_setattr(cr, vp, vap, &oldva, flags, 934 smbfs_accessx, vp); 935 if (error) 936 return (error); 937 938 if (mask & (AT_UID | AT_GID)) { 939 if (smi->smi_flags & SMI_ACL) 940 error = smbfs_acl_setids(vp, vap, cr); 941 else 942 error = ENOSYS; 943 if (error != 0) { 944 SMBVDEBUG("error %d seting UID/GID on %s", 945 error, VTOSMB(vp)->n_rpath); 946 /* 947 * It might be more correct to return the 948 * error here, but that causes complaints 949 * when root extracts a cpio archive, etc. 950 * So ignore this error, and go ahead with 951 * the rest of the setattr work. 952 */ 953 } 954 } 955 956 return (smbfssetattr(vp, vap, flags, cr)); 957 } 958 959 /* 960 * Mostly from Darwin smbfs_setattr() 961 * but then modified a lot. 962 */ 963 /* ARGSUSED */ 964 static int 965 smbfssetattr(vnode_t *vp, struct vattr *vap, int flags, cred_t *cr) 966 { 967 int error = 0; 968 smbnode_t *np = VTOSMB(vp); 969 uint_t mask = vap->va_mask; 970 struct timespec *mtime, *atime; 971 struct smb_cred scred; 972 int cerror, modified = 0; 973 unsigned short fid; 974 int have_fid = 0; 975 uint32_t rights = 0; 976 uint32_t dosattr = 0; 977 978 ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone_ref.zref_zone); 979 980 /* 981 * There are no settable attributes on the XATTR dir, 982 * so just silently ignore these. On XATTR files, 983 * you can set the size but nothing else. 984 */ 985 if (vp->v_flag & V_XATTRDIR) 986 return (0); 987 if (np->n_flag & N_XATTR) { 988 if (mask & AT_TIMES) 989 SMBVDEBUG("ignore set time on xattr\n"); 990 mask &= AT_SIZE; 991 } 992 993 /* 994 * If our caller is trying to set multiple attributes, they 995 * can make no assumption about what order they are done in. 996 * Here we try to do them in order of decreasing likelihood 997 * of failure, just to minimize the chance we'll wind up 998 * with a partially complete request. 999 */ 1000 1001 /* Shared lock for (possible) n_fid use. */ 1002 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 1003 return (EINTR); 1004 smb_credinit(&scred, cr); 1005 1006 /* 1007 * If the caller has provided extensible attributes, 1008 * map those into DOS attributes supported by SMB. 1009 * Note: zero means "no change". 1010 */ 1011 if (mask & AT_XVATTR) 1012 dosattr = xvattr_to_dosattr(np, vap); 1013 1014 /* 1015 * Will we need an open handle for this setattr? 1016 * If so, what rights will we need? 1017 */ 1018 if (dosattr || (mask & (AT_ATIME | AT_MTIME))) { 1019 rights |= 1020 SA_RIGHT_FILE_WRITE_ATTRIBUTES; 1021 } 1022 if (mask & AT_SIZE) { 1023 rights |= 1024 SA_RIGHT_FILE_WRITE_DATA | 1025 SA_RIGHT_FILE_APPEND_DATA; 1026 } 1027 1028 /* 1029 * Only SIZE really requires a handle, but it's 1030 * simpler and more reliable to set via a handle. 1031 * Some servers like NT4 won't set times by path. 1032 * Also, we're usually setting everything anyway. 1033 */ 1034 if (rights != 0) { 1035 error = smbfs_smb_tmpopen(np, rights, &scred, &fid); 1036 if (error) { 1037 SMBVDEBUG("error %d opening %s\n", 1038 error, np->n_rpath); 1039 goto out; 1040 } 1041 have_fid = 1; 1042 } 1043 1044 /* 1045 * If the server supports the UNIX extensions, right here is where 1046 * we'd support changes to uid, gid, mode, and possibly va_flags. 1047 * For now we claim to have made any such changes. 1048 */ 1049 1050 if (mask & AT_SIZE) { 1051 /* 1052 * If the new file size is less than what the client sees as 1053 * the file size, then just change the size and invalidate 1054 * the pages. 1055 * I am commenting this code at present because the function 1056 * smbfs_putapage() is not yet implemented. 1057 */ 1058 1059 /* 1060 * Set the file size to vap->va_size. 1061 */ 1062 ASSERT(have_fid); 1063 error = smbfs_smb_setfsize(np, fid, vap->va_size, &scred); 1064 if (error) { 1065 SMBVDEBUG("setsize error %d file %s\n", 1066 error, np->n_rpath); 1067 } else { 1068 /* 1069 * Darwin had code here to zero-extend. 1070 * Tests indicate the server will zero-fill, 1071 * so looks like we don't need to do this. 1072 * Good thing, as this could take forever. 1073 * 1074 * XXX: Reportedly, writing one byte of zero 1075 * at the end offset avoids problems here. 1076 */ 1077 mutex_enter(&np->r_statelock); 1078 np->r_size = vap->va_size; 1079 mutex_exit(&np->r_statelock); 1080 modified = 1; 1081 } 1082 } 1083 1084 /* 1085 * XXX: When Solaris has create_time, set that too. 1086 * Note: create_time is different from ctime. 1087 */ 1088 mtime = ((mask & AT_MTIME) ? &vap->va_mtime : 0); 1089 atime = ((mask & AT_ATIME) ? &vap->va_atime : 0); 1090 1091 if (dosattr || mtime || atime) { 1092 /* 1093 * Always use the handle-based set attr call now. 1094 */ 1095 ASSERT(have_fid); 1096 error = smbfs_smb_setfattr(np, fid, 1097 dosattr, mtime, atime, &scred); 1098 if (error) { 1099 SMBVDEBUG("set times error %d file %s\n", 1100 error, np->n_rpath); 1101 } else { 1102 modified = 1; 1103 } 1104 } 1105 1106 out: 1107 if (modified) { 1108 /* 1109 * Invalidate attribute cache in case the server 1110 * doesn't set exactly the attributes we asked. 1111 */ 1112 smbfs_attrcache_remove(np); 1113 } 1114 1115 if (have_fid) { 1116 cerror = smbfs_smb_tmpclose(np, fid, &scred); 1117 if (cerror) 1118 SMBVDEBUG("error %d closing %s\n", 1119 cerror, np->n_rpath); 1120 } 1121 1122 smb_credrele(&scred); 1123 smbfs_rw_exit(&np->r_lkserlock); 1124 1125 return (error); 1126 } 1127 1128 /* 1129 * Helper function for extensible system attributes (PSARC 2007/315) 1130 * Compute the DOS attribute word to pass to _setfattr (see above). 1131 * This returns zero IFF no change is being made to attributes. 1132 * Otherwise return the new attributes or SMB_EFA_NORMAL. 1133 */ 1134 static uint32_t 1135 xvattr_to_dosattr(smbnode_t *np, struct vattr *vap) 1136 { 1137 xvattr_t *xvap = (xvattr_t *)vap; 1138 xoptattr_t *xoap = NULL; 1139 uint32_t attr = np->r_attr.fa_attr; 1140 boolean_t anyset = B_FALSE; 1141 1142 if ((xoap = xva_getxoptattr(xvap)) == NULL) 1143 return (0); 1144 1145 if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) { 1146 if (xoap->xoa_archive) 1147 attr |= SMB_FA_ARCHIVE; 1148 else 1149 attr &= ~SMB_FA_ARCHIVE; 1150 XVA_SET_RTN(xvap, XAT_ARCHIVE); 1151 anyset = B_TRUE; 1152 } 1153 if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) { 1154 if (xoap->xoa_system) 1155 attr |= SMB_FA_SYSTEM; 1156 else 1157 attr &= ~SMB_FA_SYSTEM; 1158 XVA_SET_RTN(xvap, XAT_SYSTEM); 1159 anyset = B_TRUE; 1160 } 1161 if (XVA_ISSET_REQ(xvap, XAT_READONLY)) { 1162 if (xoap->xoa_readonly) 1163 attr |= SMB_FA_RDONLY; 1164 else 1165 attr &= ~SMB_FA_RDONLY; 1166 XVA_SET_RTN(xvap, XAT_READONLY); 1167 anyset = B_TRUE; 1168 } 1169 if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) { 1170 if (xoap->xoa_hidden) 1171 attr |= SMB_FA_HIDDEN; 1172 else 1173 attr &= ~SMB_FA_HIDDEN; 1174 XVA_SET_RTN(xvap, XAT_HIDDEN); 1175 anyset = B_TRUE; 1176 } 1177 1178 if (anyset == B_FALSE) 1179 return (0); /* no change */ 1180 if (attr == 0) 1181 attr = SMB_EFA_NORMAL; 1182 1183 return (attr); 1184 } 1185 1186 /* 1187 * smbfs_access_rwx() 1188 * Common function for smbfs_access, etc. 1189 * 1190 * The security model implemented by the FS is unusual 1191 * due to the current "single user mounts" restriction: 1192 * All access under a given mount point uses the CIFS 1193 * credentials established by the owner of the mount. 1194 * 1195 * Most access checking is handled by the CIFS server, 1196 * but we need sufficient Unix access checks here to 1197 * prevent other local Unix users from having access 1198 * to objects under this mount that the uid/gid/mode 1199 * settings in the mount would not allow. 1200 * 1201 * With this model, there is a case where we need the 1202 * ability to do an access check before we have the 1203 * vnode for an object. This function takes advantage 1204 * of the fact that the uid/gid/mode is per mount, and 1205 * avoids the need for a vnode. 1206 * 1207 * We still (sort of) need a vnode when we call 1208 * secpolicy_vnode_access, but that only uses 1209 * the vtype field, so we can use a pair of fake 1210 * vnodes that have only v_type filled in. 1211 * 1212 * XXX: Later, add a new secpolicy_vtype_access() 1213 * that takes the vtype instead of a vnode, and 1214 * get rid of the tmpl_vxxx fake vnodes below. 1215 */ 1216 static int 1217 smbfs_access_rwx(vfs_t *vfsp, int vtype, int mode, cred_t *cr) 1218 { 1219 /* See the secpolicy call below. */ 1220 static const vnode_t tmpl_vdir = { .v_type = VDIR }; 1221 static const vnode_t tmpl_vreg = { .v_type = VREG }; 1222 vattr_t va; 1223 vnode_t *tvp; 1224 struct smbmntinfo *smi = VFTOSMI(vfsp); 1225 int shift = 0; 1226 1227 /* 1228 * Build our (fabricated) vnode attributes. 1229 * XXX: Could make these templates in the 1230 * per-mount struct and use them here. 1231 */ 1232 bzero(&va, sizeof (va)); 1233 va.va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID; 1234 va.va_type = vtype; 1235 va.va_mode = (vtype == VDIR) ? 1236 smi->smi_dmode : smi->smi_fmode; 1237 va.va_uid = smi->smi_uid; 1238 va.va_gid = smi->smi_gid; 1239 1240 /* 1241 * Disallow write attempts on read-only file systems, 1242 * unless the file is a device or fifo node. Note: 1243 * Inline vn_is_readonly and IS_DEVVP here because 1244 * we may not have a vnode ptr. Original expr. was: 1245 * (mode & VWRITE) && vn_is_readonly(vp) && !IS_DEVVP(vp)) 1246 */ 1247 if ((mode & VWRITE) && 1248 (vfsp->vfs_flag & VFS_RDONLY) && 1249 !(vtype == VCHR || vtype == VBLK || vtype == VFIFO)) 1250 return (EROFS); 1251 1252 /* 1253 * Disallow attempts to access mandatory lock files. 1254 * Similarly, expand MANDLOCK here. 1255 * XXX: not sure we need this. 1256 */ 1257 if ((mode & (VWRITE | VREAD | VEXEC)) && 1258 va.va_type == VREG && MANDMODE(va.va_mode)) 1259 return (EACCES); 1260 1261 /* 1262 * Access check is based on only 1263 * one of owner, group, public. 1264 * If not owner, then check group. 1265 * If not a member of the group, 1266 * then check public access. 1267 */ 1268 if (crgetuid(cr) != va.va_uid) { 1269 shift += 3; 1270 if (!groupmember(va.va_gid, cr)) 1271 shift += 3; 1272 } 1273 1274 /* 1275 * We need a vnode for secpolicy_vnode_access, 1276 * but the only thing it looks at is v_type, 1277 * so pass one of the templates above. 1278 */ 1279 tvp = (va.va_type == VDIR) ? 1280 (vnode_t *)&tmpl_vdir : 1281 (vnode_t *)&tmpl_vreg; 1282 1283 return (secpolicy_vnode_access2(cr, tvp, va.va_uid, 1284 va.va_mode << shift, mode)); 1285 } 1286 1287 /* 1288 * See smbfs_setattr 1289 */ 1290 static int 1291 smbfs_accessx(void *arg, int mode, cred_t *cr) 1292 { 1293 vnode_t *vp = arg; 1294 /* 1295 * Note: The caller has checked the current zone, 1296 * the SMI_DEAD and VFS_UNMOUNTED flags, etc. 1297 */ 1298 return (smbfs_access_rwx(vp->v_vfsp, vp->v_type, mode, cr)); 1299 } 1300 1301 /* 1302 * XXX 1303 * This op should support PSARC 2007/403, Modified Access Checks for CIFS 1304 */ 1305 /* ARGSUSED */ 1306 static int 1307 smbfs_access(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct) 1308 { 1309 vfs_t *vfsp; 1310 smbmntinfo_t *smi; 1311 1312 vfsp = vp->v_vfsp; 1313 smi = VFTOSMI(vfsp); 1314 1315 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 1316 return (EIO); 1317 1318 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 1319 return (EIO); 1320 1321 return (smbfs_access_rwx(vfsp, vp->v_type, mode, cr)); 1322 } 1323 1324 1325 /* 1326 * Flush local dirty pages to stable storage on the server. 1327 * 1328 * If FNODSYNC is specified, then there is nothing to do because 1329 * metadata changes are not cached on the client before being 1330 * sent to the server. 1331 */ 1332 /* ARGSUSED */ 1333 static int 1334 smbfs_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct) 1335 { 1336 int error = 0; 1337 smbmntinfo_t *smi; 1338 smbnode_t *np; 1339 struct smb_cred scred; 1340 1341 np = VTOSMB(vp); 1342 smi = VTOSMI(vp); 1343 1344 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 1345 return (EIO); 1346 1347 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 1348 return (EIO); 1349 1350 if ((syncflag & FNODSYNC) || IS_SWAPVP(vp)) 1351 return (0); 1352 1353 if ((syncflag & (FSYNC|FDSYNC)) == 0) 1354 return (0); 1355 1356 /* Shared lock for n_fid use in _flush */ 1357 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 1358 return (EINTR); 1359 smb_credinit(&scred, cr); 1360 1361 error = smbfs_smb_flush(np, &scred); 1362 1363 smb_credrele(&scred); 1364 smbfs_rw_exit(&np->r_lkserlock); 1365 1366 return (error); 1367 } 1368 1369 /* 1370 * Last reference to vnode went away. 1371 */ 1372 /* ARGSUSED */ 1373 static void 1374 smbfs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct) 1375 { 1376 smbnode_t *np; 1377 struct smb_cred scred; 1378 1379 /* 1380 * Don't "bail out" for VFS_UNMOUNTED here, 1381 * as we want to do cleanup, etc. 1382 * See also pcfs_inactive 1383 */ 1384 1385 np = VTOSMB(vp); 1386 1387 /* 1388 * If this is coming from the wrong zone, we let someone in the right 1389 * zone take care of it asynchronously. We can get here due to 1390 * VN_RELE() being called from pageout() or fsflush(). This call may 1391 * potentially turn into an expensive no-op if, for instance, v_count 1392 * gets incremented in the meantime, but it's still correct. 1393 */ 1394 1395 /* 1396 * Defend against the possibility that higher-level callers 1397 * might not correctly balance open and close calls. If we 1398 * get here with open references remaining, it means there 1399 * was a missing VOP_CLOSE somewhere. If that happens, do 1400 * the close here so we don't "leak" FIDs on the server. 1401 * 1402 * Exclusive lock for modifying n_fid stuff. 1403 * Don't want this one ever interruptible. 1404 */ 1405 (void) smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, 0); 1406 smb_credinit(&scred, cr); 1407 1408 switch (np->n_ovtype) { 1409 case VNON: 1410 /* not open (OK) */ 1411 break; 1412 1413 case VDIR: 1414 if (np->n_dirrefs == 0) 1415 break; 1416 SMBVDEBUG("open dir: refs %d path %s\n", 1417 np->n_dirrefs, np->n_rpath); 1418 /* Force last close. */ 1419 np->n_dirrefs = 1; 1420 smbfs_rele_fid(np, &scred); 1421 break; 1422 1423 case VREG: 1424 if (np->n_fidrefs == 0) 1425 break; 1426 SMBVDEBUG("open file: refs %d id 0x%x path %s\n", 1427 np->n_fidrefs, np->n_fid, np->n_rpath); 1428 /* Force last close. */ 1429 np->n_fidrefs = 1; 1430 smbfs_rele_fid(np, &scred); 1431 break; 1432 1433 default: 1434 SMBVDEBUG("bad n_ovtype %d\n", np->n_ovtype); 1435 np->n_ovtype = VNON; 1436 break; 1437 } 1438 1439 smb_credrele(&scred); 1440 smbfs_rw_exit(&np->r_lkserlock); 1441 1442 /* 1443 * XATTR directories (and the files under them) have 1444 * little value for reclaim, so just remove them from 1445 * the "hash" (AVL) as soon as they go inactive. 1446 * Note that the node may already have been removed 1447 * from the hash by smbfsremove. 1448 */ 1449 if ((np->n_flag & N_XATTR) != 0 && 1450 (np->r_flags & RHASHED) != 0) 1451 smbfs_rmhash(np); 1452 1453 smbfs_addfree(np); 1454 } 1455 1456 /* 1457 * Remote file system operations having to do with directory manipulation. 1458 */ 1459 /* ARGSUSED */ 1460 static int 1461 smbfs_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, struct pathname *pnp, 1462 int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct, 1463 int *direntflags, pathname_t *realpnp) 1464 { 1465 vfs_t *vfs; 1466 smbmntinfo_t *smi; 1467 smbnode_t *dnp; 1468 int error; 1469 1470 vfs = dvp->v_vfsp; 1471 smi = VFTOSMI(vfs); 1472 1473 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 1474 return (EPERM); 1475 1476 if (smi->smi_flags & SMI_DEAD || vfs->vfs_flag & VFS_UNMOUNTED) 1477 return (EIO); 1478 1479 dnp = VTOSMB(dvp); 1480 1481 /* 1482 * Are we looking up extended attributes? If so, "dvp" is 1483 * the file or directory for which we want attributes, and 1484 * we need a lookup of the (faked up) attribute directory 1485 * before we lookup the rest of the path. 1486 */ 1487 if (flags & LOOKUP_XATTR) { 1488 /* 1489 * Require the xattr mount option. 1490 */ 1491 if ((vfs->vfs_flag & VFS_XATTR) == 0) 1492 return (EINVAL); 1493 1494 error = smbfs_get_xattrdir(dvp, vpp, cr, flags); 1495 return (error); 1496 } 1497 1498 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_READER, SMBINTR(dvp))) 1499 return (EINTR); 1500 1501 error = smbfslookup(dvp, nm, vpp, cr, 1, ct); 1502 1503 smbfs_rw_exit(&dnp->r_rwlock); 1504 1505 return (error); 1506 } 1507 1508 /* ARGSUSED */ 1509 static int 1510 smbfslookup(vnode_t *dvp, char *nm, vnode_t **vpp, cred_t *cr, 1511 int cache_ok, caller_context_t *ct) 1512 { 1513 int error; 1514 int supplen; /* supported length */ 1515 vnode_t *vp; 1516 smbnode_t *np; 1517 smbnode_t *dnp; 1518 smbmntinfo_t *smi; 1519 /* struct smb_vc *vcp; */ 1520 const char *ill; 1521 const char *name = (const char *)nm; 1522 int nmlen = strlen(nm); 1523 int rplen; 1524 struct smb_cred scred; 1525 struct smbfattr fa; 1526 1527 smi = VTOSMI(dvp); 1528 dnp = VTOSMB(dvp); 1529 1530 ASSERT(curproc->p_zone == smi->smi_zone_ref.zref_zone); 1531 1532 #ifdef NOT_YET 1533 vcp = SSTOVC(smi->smi_share); 1534 1535 /* XXX: Should compute this once and store it in smbmntinfo_t */ 1536 supplen = (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN2_0) ? 255 : 12; 1537 #else 1538 supplen = 255; 1539 #endif 1540 1541 /* 1542 * RWlock must be held, either reader or writer. 1543 * XXX: Can we check without looking directly 1544 * inside the struct smbfs_rwlock_t? 1545 */ 1546 ASSERT(dnp->r_rwlock.count != 0); 1547 1548 /* 1549 * If lookup is for "", just return dvp. 1550 * No need to perform any access checks. 1551 */ 1552 if (nmlen == 0) { 1553 VN_HOLD(dvp); 1554 *vpp = dvp; 1555 return (0); 1556 } 1557 1558 /* 1559 * Can't do lookups in non-directories. 1560 */ 1561 if (dvp->v_type != VDIR) 1562 return (ENOTDIR); 1563 1564 /* 1565 * Need search permission in the directory. 1566 */ 1567 error = smbfs_access(dvp, VEXEC, 0, cr, ct); 1568 if (error) 1569 return (error); 1570 1571 /* 1572 * If lookup is for ".", just return dvp. 1573 * Access check was done above. 1574 */ 1575 if (nmlen == 1 && name[0] == '.') { 1576 VN_HOLD(dvp); 1577 *vpp = dvp; 1578 return (0); 1579 } 1580 1581 /* 1582 * Now some sanity checks on the name. 1583 * First check the length. 1584 */ 1585 if (nmlen > supplen) 1586 return (ENAMETOOLONG); 1587 1588 /* 1589 * Avoid surprises with characters that are 1590 * illegal in Windows file names. 1591 * Todo: CATIA mappings XXX 1592 */ 1593 ill = illegal_chars; 1594 if (dnp->n_flag & N_XATTR) 1595 ill++; /* allow colon */ 1596 if (strpbrk(nm, ill)) 1597 return (EINVAL); 1598 1599 /* 1600 * Special handling for lookup of ".." 1601 * 1602 * We keep full pathnames (as seen on the server) 1603 * so we can just trim off the last component to 1604 * get the full pathname of the parent. Note: 1605 * We don't actually copy and modify, but just 1606 * compute the trimmed length and pass that with 1607 * the current dir path (not null terminated). 1608 * 1609 * We don't go over-the-wire to get attributes 1610 * for ".." because we know it's a directory, 1611 * and we can just leave the rest "stale" 1612 * until someone does a getattr. 1613 */ 1614 if (nmlen == 2 && name[0] == '.' && name[1] == '.') { 1615 if (dvp->v_flag & VROOT) { 1616 /* 1617 * Already at the root. This can happen 1618 * with directory listings at the root, 1619 * which lookup "." and ".." to get the 1620 * inode numbers. Let ".." be the same 1621 * as "." in the FS root. 1622 */ 1623 VN_HOLD(dvp); 1624 *vpp = dvp; 1625 return (0); 1626 } 1627 1628 /* 1629 * Special case for XATTR directory 1630 */ 1631 if (dvp->v_flag & V_XATTRDIR) { 1632 error = smbfs_xa_parent(dvp, vpp); 1633 return (error); 1634 } 1635 1636 /* 1637 * Find the parent path length. 1638 */ 1639 rplen = dnp->n_rplen; 1640 ASSERT(rplen > 0); 1641 while (--rplen >= 0) { 1642 if (dnp->n_rpath[rplen] == '\\') 1643 break; 1644 } 1645 if (rplen <= 0) { 1646 /* Found our way to the root. */ 1647 vp = SMBTOV(smi->smi_root); 1648 VN_HOLD(vp); 1649 *vpp = vp; 1650 return (0); 1651 } 1652 np = smbfs_node_findcreate(smi, 1653 dnp->n_rpath, rplen, NULL, 0, 0, 1654 &smbfs_fattr0); /* force create */ 1655 ASSERT(np != NULL); 1656 vp = SMBTOV(np); 1657 vp->v_type = VDIR; 1658 1659 /* Success! */ 1660 *vpp = vp; 1661 return (0); 1662 } 1663 1664 /* 1665 * Normal lookup of a name under this directory. 1666 * Note we handled "", ".", ".." above. 1667 */ 1668 if (cache_ok) { 1669 /* 1670 * The caller indicated that it's OK to use a 1671 * cached result for this lookup, so try to 1672 * reclaim a node from the smbfs node cache. 1673 */ 1674 error = smbfslookup_cache(dvp, nm, nmlen, &vp, cr); 1675 if (error) 1676 return (error); 1677 if (vp != NULL) { 1678 /* hold taken in lookup_cache */ 1679 *vpp = vp; 1680 return (0); 1681 } 1682 } 1683 1684 /* 1685 * OK, go over-the-wire to get the attributes, 1686 * then create the node. 1687 */ 1688 smb_credinit(&scred, cr); 1689 /* Note: this can allocate a new "name" */ 1690 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fa, &scred); 1691 smb_credrele(&scred); 1692 if (error == ENOTDIR) { 1693 /* 1694 * Lookup failed because this directory was 1695 * removed or renamed by another client. 1696 * Remove any cached attributes under it. 1697 */ 1698 smbfs_attrcache_remove(dnp); 1699 smbfs_attrcache_prune(dnp); 1700 } 1701 if (error) 1702 goto out; 1703 1704 error = smbfs_nget(dvp, name, nmlen, &fa, &vp); 1705 if (error) 1706 goto out; 1707 1708 /* Success! */ 1709 *vpp = vp; 1710 1711 out: 1712 /* smbfs_smb_lookup may have allocated name. */ 1713 if (name != nm) 1714 smbfs_name_free(name, nmlen); 1715 1716 return (error); 1717 } 1718 1719 /* 1720 * smbfslookup_cache 1721 * 1722 * Try to reclaim a node from the smbfs node cache. 1723 * Some statistics for DEBUG. 1724 * 1725 * This mechanism lets us avoid many of the five (or more) 1726 * OtW lookup calls per file seen with "ls -l" if we search 1727 * the smbfs node cache for recently inactive(ated) nodes. 1728 */ 1729 #ifdef DEBUG 1730 int smbfs_lookup_cache_calls = 0; 1731 int smbfs_lookup_cache_error = 0; 1732 int smbfs_lookup_cache_miss = 0; 1733 int smbfs_lookup_cache_stale = 0; 1734 int smbfs_lookup_cache_hits = 0; 1735 #endif /* DEBUG */ 1736 1737 /* ARGSUSED */ 1738 static int 1739 smbfslookup_cache(vnode_t *dvp, char *nm, int nmlen, 1740 vnode_t **vpp, cred_t *cr) 1741 { 1742 struct vattr va; 1743 smbnode_t *dnp; 1744 smbnode_t *np; 1745 vnode_t *vp; 1746 int error; 1747 char sep; 1748 1749 dnp = VTOSMB(dvp); 1750 *vpp = NULL; 1751 1752 #ifdef DEBUG 1753 smbfs_lookup_cache_calls++; 1754 #endif 1755 1756 /* 1757 * First make sure we can get attributes for the 1758 * directory. Cached attributes are OK here. 1759 * If we removed or renamed the directory, this 1760 * will return ENOENT. If someone else removed 1761 * this directory or file, we'll find out when we 1762 * try to open or get attributes. 1763 */ 1764 va.va_mask = AT_TYPE | AT_MODE; 1765 error = smbfsgetattr(dvp, &va, cr); 1766 if (error) { 1767 #ifdef DEBUG 1768 smbfs_lookup_cache_error++; 1769 #endif 1770 return (error); 1771 } 1772 1773 /* 1774 * Passing NULL smbfattr here so we will 1775 * just look, not create. 1776 */ 1777 sep = SMBFS_DNP_SEP(dnp); 1778 np = smbfs_node_findcreate(dnp->n_mount, 1779 dnp->n_rpath, dnp->n_rplen, 1780 nm, nmlen, sep, NULL); 1781 if (np == NULL) { 1782 #ifdef DEBUG 1783 smbfs_lookup_cache_miss++; 1784 #endif 1785 return (0); 1786 } 1787 1788 /* 1789 * Found it. Attributes still valid? 1790 */ 1791 vp = SMBTOV(np); 1792 if (np->r_attrtime <= gethrtime()) { 1793 /* stale */ 1794 #ifdef DEBUG 1795 smbfs_lookup_cache_stale++; 1796 #endif 1797 VN_RELE(vp); 1798 return (0); 1799 } 1800 1801 /* 1802 * Success! 1803 * Caller gets hold from smbfs_node_findcreate 1804 */ 1805 #ifdef DEBUG 1806 smbfs_lookup_cache_hits++; 1807 #endif 1808 *vpp = vp; 1809 return (0); 1810 } 1811 1812 /* 1813 * XXX 1814 * vsecattr_t is new to build 77, and we need to eventually support 1815 * it in order to create an ACL when an object is created. 1816 * 1817 * This op should support the new FIGNORECASE flag for case-insensitive 1818 * lookups, per PSARC 2007/244. 1819 */ 1820 /* ARGSUSED */ 1821 static int 1822 smbfs_create(vnode_t *dvp, char *nm, struct vattr *va, enum vcexcl exclusive, 1823 int mode, vnode_t **vpp, cred_t *cr, int lfaware, caller_context_t *ct, 1824 vsecattr_t *vsecp) 1825 { 1826 int error; 1827 int cerror; 1828 vfs_t *vfsp; 1829 vnode_t *vp; 1830 #ifdef NOT_YET 1831 smbnode_t *np; 1832 #endif 1833 smbnode_t *dnp; 1834 smbmntinfo_t *smi; 1835 struct vattr vattr; 1836 struct smbfattr fattr; 1837 struct smb_cred scred; 1838 const char *name = (const char *)nm; 1839 int nmlen = strlen(nm); 1840 uint32_t disp; 1841 uint16_t fid; 1842 int xattr; 1843 1844 vfsp = dvp->v_vfsp; 1845 smi = VFTOSMI(vfsp); 1846 dnp = VTOSMB(dvp); 1847 vp = NULL; 1848 1849 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 1850 return (EPERM); 1851 1852 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 1853 return (EIO); 1854 1855 /* 1856 * Note: this may break mknod(2) calls to create a directory, 1857 * but that's obscure use. Some other filesystems do this. 1858 * XXX: Later, redirect VDIR type here to _mkdir. 1859 */ 1860 if (va->va_type != VREG) 1861 return (EINVAL); 1862 1863 /* 1864 * If the pathname is "", just use dvp, no checks. 1865 * Do this outside of the rwlock (like zfs). 1866 */ 1867 if (nmlen == 0) { 1868 VN_HOLD(dvp); 1869 *vpp = dvp; 1870 return (0); 1871 } 1872 1873 /* Don't allow "." or ".." through here. */ 1874 if ((nmlen == 1 && name[0] == '.') || 1875 (nmlen == 2 && name[0] == '.' && name[1] == '.')) 1876 return (EISDIR); 1877 1878 /* 1879 * We make a copy of the attributes because the caller does not 1880 * expect us to change what va points to. 1881 */ 1882 vattr = *va; 1883 1884 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp))) 1885 return (EINTR); 1886 smb_credinit(&scred, cr); 1887 1888 /* 1889 * NFS needs to go over the wire, just to be sure whether the 1890 * file exists or not. Using a cached result is dangerous in 1891 * this case when making a decision regarding existence. 1892 * 1893 * The SMB protocol does NOT really need to go OTW here 1894 * thanks to the expressive NTCREATE disposition values. 1895 * Unfortunately, to do Unix access checks correctly, 1896 * we need to know if the object already exists. 1897 * When the object does not exist, we need VWRITE on 1898 * the directory. Note: smbfslookup() checks VEXEC. 1899 */ 1900 error = smbfslookup(dvp, nm, &vp, cr, 0, ct); 1901 if (error == 0) { 1902 /* 1903 * The file already exists. Error? 1904 * NB: have a hold from smbfslookup 1905 */ 1906 if (exclusive == EXCL) { 1907 error = EEXIST; 1908 VN_RELE(vp); 1909 goto out; 1910 } 1911 /* 1912 * Verify requested access. 1913 */ 1914 error = smbfs_access(vp, mode, 0, cr, ct); 1915 if (error) { 1916 VN_RELE(vp); 1917 goto out; 1918 } 1919 1920 /* 1921 * Truncate (if requested). 1922 */ 1923 if ((vattr.va_mask & AT_SIZE) && vattr.va_size == 0) { 1924 vattr.va_mask = AT_SIZE; 1925 error = smbfssetattr(vp, &vattr, 0, cr); 1926 if (error) { 1927 VN_RELE(vp); 1928 goto out; 1929 } 1930 } 1931 /* Success! */ 1932 #ifdef NOT_YET 1933 vnevent_create(vp, ct); 1934 #endif 1935 *vpp = vp; 1936 goto out; 1937 } 1938 1939 /* 1940 * The file did not exist. Need VWRITE in the directory. 1941 */ 1942 error = smbfs_access(dvp, VWRITE, 0, cr, ct); 1943 if (error) 1944 goto out; 1945 1946 /* 1947 * Now things get tricky. We also need to check the 1948 * requested open mode against the file we may create. 1949 * See comments at smbfs_access_rwx 1950 */ 1951 error = smbfs_access_rwx(vfsp, VREG, mode, cr); 1952 if (error) 1953 goto out; 1954 1955 /* 1956 * Now the code derived from Darwin, 1957 * but with greater use of NT_CREATE 1958 * disposition options. Much changed. 1959 * 1960 * Create (or open) a new child node. 1961 * Note we handled "." and ".." above. 1962 */ 1963 1964 if (exclusive == EXCL) 1965 disp = NTCREATEX_DISP_CREATE; 1966 else { 1967 /* Truncate regular files if requested. */ 1968 if ((va->va_type == VREG) && 1969 (va->va_mask & AT_SIZE) && 1970 (va->va_size == 0)) 1971 disp = NTCREATEX_DISP_OVERWRITE_IF; 1972 else 1973 disp = NTCREATEX_DISP_OPEN_IF; 1974 } 1975 xattr = (dnp->n_flag & N_XATTR) ? 1 : 0; 1976 error = smbfs_smb_create(dnp, 1977 name, nmlen, xattr, 1978 disp, &scred, &fid); 1979 if (error) 1980 goto out; 1981 1982 /* 1983 * XXX: Missing some code here to deal with 1984 * the case where we opened an existing file, 1985 * it's size is larger than 32-bits, and we're 1986 * setting the size from a process that's not 1987 * aware of large file offsets. i.e. 1988 * from the NFS3 code: 1989 */ 1990 #if NOT_YET /* XXX */ 1991 if ((vattr.va_mask & AT_SIZE) && 1992 vp->v_type == VREG) { 1993 np = VTOSMB(vp); 1994 /* 1995 * Check here for large file handled 1996 * by LF-unaware process (as 1997 * ufs_create() does) 1998 */ 1999 if (!(lfaware & FOFFMAX)) { 2000 mutex_enter(&np->r_statelock); 2001 if (np->r_size > MAXOFF32_T) 2002 error = EOVERFLOW; 2003 mutex_exit(&np->r_statelock); 2004 } 2005 if (!error) { 2006 vattr.va_mask = AT_SIZE; 2007 error = smbfssetattr(vp, 2008 &vattr, 0, cr); 2009 } 2010 } 2011 #endif /* XXX */ 2012 /* 2013 * Should use the fid to get/set the size 2014 * while we have it opened here. See above. 2015 */ 2016 2017 cerror = smbfs_smb_close(smi->smi_share, fid, NULL, &scred); 2018 if (cerror) 2019 SMBVDEBUG("error %d closing %s\\%s\n", 2020 cerror, dnp->n_rpath, name); 2021 2022 /* 2023 * In the open case, the name may differ a little 2024 * from what we passed to create (case, etc.) 2025 * so call lookup to get the (opened) name. 2026 * 2027 * XXX: Could avoid this extra lookup if the 2028 * "createact" result from NT_CREATE says we 2029 * created the object. 2030 */ 2031 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred); 2032 if (error) 2033 goto out; 2034 2035 /* update attr and directory cache */ 2036 smbfs_attr_touchdir(dnp); 2037 2038 error = smbfs_nget(dvp, name, nmlen, &fattr, &vp); 2039 if (error) 2040 goto out; 2041 2042 /* XXX invalidate pages if we truncated? */ 2043 2044 /* Success! */ 2045 *vpp = vp; 2046 error = 0; 2047 2048 out: 2049 smb_credrele(&scred); 2050 smbfs_rw_exit(&dnp->r_rwlock); 2051 if (name != nm) 2052 smbfs_name_free(name, nmlen); 2053 return (error); 2054 } 2055 2056 /* 2057 * XXX 2058 * This op should support the new FIGNORECASE flag for case-insensitive 2059 * lookups, per PSARC 2007/244. 2060 */ 2061 /* ARGSUSED */ 2062 static int 2063 smbfs_remove(vnode_t *dvp, char *nm, cred_t *cr, caller_context_t *ct, 2064 int flags) 2065 { 2066 struct smb_cred scred; 2067 vnode_t *vp = NULL; 2068 smbnode_t *dnp = VTOSMB(dvp); 2069 smbmntinfo_t *smi = VTOSMI(dvp); 2070 int error; 2071 2072 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 2073 return (EPERM); 2074 2075 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2076 return (EIO); 2077 2078 /* 2079 * Verify access to the dirctory. 2080 */ 2081 error = smbfs_access(dvp, VWRITE|VEXEC, 0, cr, ct); 2082 if (error) 2083 return (error); 2084 2085 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp))) 2086 return (EINTR); 2087 smb_credinit(&scred, cr); 2088 2089 /* Lookup the file to remove. */ 2090 error = smbfslookup(dvp, nm, &vp, cr, 0, ct); 2091 if (error == 0) { 2092 /* 2093 * Do the real remove work 2094 */ 2095 error = smbfsremove(dvp, vp, &scred, flags); 2096 VN_RELE(vp); 2097 } 2098 2099 smb_credrele(&scred); 2100 smbfs_rw_exit(&dnp->r_rwlock); 2101 2102 return (error); 2103 } 2104 2105 /* 2106 * smbfsremove does the real work of removing in SMBFS 2107 * Caller has done dir access checks etc. 2108 * 2109 * The normal way to delete a file over SMB is open it (with DELETE access), 2110 * set the "delete-on-close" flag, and close the file. The problem for Unix 2111 * applications is that they expect the file name to be gone once the unlink 2112 * completes, and the SMB server does not actually delete the file until ALL 2113 * opens of that file are closed. We can't assume our open handles are the 2114 * only open handles on a file we're deleting, so to be safe we'll try to 2115 * rename the file to a temporary name and then set delete-on-close. If we 2116 * fail to set delete-on-close (i.e. because other opens prevent it) then 2117 * undo the changes we made and give up with EBUSY. Note that we might have 2118 * permission to delete a file but lack permission to rename, so we want to 2119 * continue in cases where rename fails. As an optimization, only do the 2120 * rename when we have the file open. 2121 * 2122 * This is similar to what NFS does when deleting a file that has local opens, 2123 * but thanks to SMB delete-on-close, we don't need to keep track of when the 2124 * last local open goes away and send a delete. The server does that for us. 2125 */ 2126 /* ARGSUSED */ 2127 static int 2128 smbfsremove(vnode_t *dvp, vnode_t *vp, struct smb_cred *scred, 2129 int flags) 2130 { 2131 smbnode_t *dnp = VTOSMB(dvp); 2132 smbnode_t *np = VTOSMB(vp); 2133 char *tmpname = NULL; 2134 int tnlen; 2135 int error; 2136 unsigned short fid; 2137 boolean_t have_fid = B_FALSE; 2138 boolean_t renamed = B_FALSE; 2139 2140 /* 2141 * The dvp RWlock must be held as writer. 2142 */ 2143 ASSERT(dnp->r_rwlock.owner == curthread); 2144 2145 /* Never allow link/unlink directories on SMB. */ 2146 if (vp->v_type == VDIR) 2147 return (EPERM); 2148 2149 /* Shared lock for n_fid use in smbfs_smb_setdisp etc. */ 2150 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_READER, SMBINTR(vp))) 2151 return (EINTR); 2152 2153 /* Force lookup to go OtW */ 2154 smbfs_attrcache_remove(np); 2155 2156 /* 2157 * Get a file handle with delete access. 2158 * Close this FID before return. 2159 */ 2160 error = smbfs_smb_tmpopen(np, STD_RIGHT_DELETE_ACCESS, 2161 scred, &fid); 2162 if (error) { 2163 SMBVDEBUG("error %d opening %s\n", 2164 error, np->n_rpath); 2165 goto out; 2166 } 2167 have_fid = B_TRUE; 2168 2169 /* 2170 * If we have the file open, try to rename it to a temporary name. 2171 * If we can't rename, continue on and try setting DoC anyway. 2172 */ 2173 if ((vp->v_count > 1) && (np->n_fidrefs > 0)) { 2174 tmpname = kmem_alloc(MAXNAMELEN, KM_SLEEP); 2175 tnlen = smbfs_newname(tmpname, MAXNAMELEN); 2176 error = smbfs_smb_t2rename(np, tmpname, tnlen, scred, fid, 0); 2177 if (error != 0) { 2178 SMBVDEBUG("error %d renaming %s -> %s\n", 2179 error, np->n_rpath, tmpname); 2180 /* Keep going without the rename. */ 2181 } else { 2182 renamed = B_TRUE; 2183 } 2184 } 2185 2186 /* 2187 * Mark the file as delete-on-close. If we can't, 2188 * undo what we did and err out. 2189 */ 2190 error = smbfs_smb_setdisp(np, fid, 1, scred); 2191 if (error != 0) { 2192 SMBVDEBUG("error %d setting DoC on %s\n", 2193 error, np->n_rpath); 2194 /* 2195 * Failed to set DoC. If we renamed, undo that. 2196 * Need np->n_rpath relative to parent (dnp). 2197 * Use parent path name length plus one for 2198 * the separator ('/' or ':') 2199 */ 2200 if (renamed) { 2201 char *oldname; 2202 int oldnlen; 2203 int err2; 2204 2205 oldname = np->n_rpath + (dnp->n_rplen + 1); 2206 oldnlen = np->n_rplen - (dnp->n_rplen + 1); 2207 err2 = smbfs_smb_t2rename(np, oldname, oldnlen, 2208 scred, fid, 0); 2209 SMBVDEBUG("error %d un-renaming %s -> %s\n", 2210 err2, tmpname, np->n_rpath); 2211 } 2212 error = EBUSY; 2213 goto out; 2214 } 2215 /* Done! */ 2216 smbfs_attrcache_prune(np); 2217 2218 out: 2219 if (tmpname != NULL) 2220 kmem_free(tmpname, MAXNAMELEN); 2221 2222 if (have_fid) 2223 (void) smbfs_smb_tmpclose(np, fid, scred); 2224 smbfs_rw_exit(&np->r_lkserlock); 2225 2226 if (error == 0) { 2227 /* Keep lookup from finding this node anymore. */ 2228 smbfs_rmhash(np); 2229 } 2230 2231 return (error); 2232 } 2233 2234 2235 /* 2236 * XXX 2237 * This op should support the new FIGNORECASE flag for case-insensitive 2238 * lookups, per PSARC 2007/244. 2239 */ 2240 /* ARGSUSED */ 2241 static int 2242 smbfs_rename(vnode_t *odvp, char *onm, vnode_t *ndvp, char *nnm, cred_t *cr, 2243 caller_context_t *ct, int flags) 2244 { 2245 struct smb_cred scred; 2246 smbnode_t *odnp = VTOSMB(odvp); 2247 smbnode_t *ndnp = VTOSMB(ndvp); 2248 vnode_t *ovp; 2249 int error; 2250 2251 if (curproc->p_zone != VTOSMI(odvp)->smi_zone_ref.zref_zone || 2252 curproc->p_zone != VTOSMI(ndvp)->smi_zone_ref.zref_zone) 2253 return (EPERM); 2254 2255 if (VTOSMI(odvp)->smi_flags & SMI_DEAD || 2256 VTOSMI(ndvp)->smi_flags & SMI_DEAD || 2257 odvp->v_vfsp->vfs_flag & VFS_UNMOUNTED || 2258 ndvp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2259 return (EIO); 2260 2261 if (strcmp(onm, ".") == 0 || strcmp(onm, "..") == 0 || 2262 strcmp(nnm, ".") == 0 || strcmp(nnm, "..") == 0) 2263 return (EINVAL); 2264 2265 /* 2266 * Check that everything is on the same filesystem. 2267 * vn_rename checks the fsid's, but in case we don't 2268 * fill those in correctly, check here too. 2269 */ 2270 if (odvp->v_vfsp != ndvp->v_vfsp) 2271 return (EXDEV); 2272 2273 /* 2274 * Need write access on source and target. 2275 * Server takes care of most checks. 2276 */ 2277 error = smbfs_access(odvp, VWRITE|VEXEC, 0, cr, ct); 2278 if (error) 2279 return (error); 2280 if (odvp != ndvp) { 2281 error = smbfs_access(ndvp, VWRITE, 0, cr, ct); 2282 if (error) 2283 return (error); 2284 } 2285 2286 /* 2287 * Need to lock both old/new dirs as writer. 2288 * 2289 * Avoid deadlock here on old vs new directory nodes 2290 * by always taking the locks in order of address. 2291 * The order is arbitrary, but must be consistent. 2292 */ 2293 if (odnp < ndnp) { 2294 if (smbfs_rw_enter_sig(&odnp->r_rwlock, RW_WRITER, 2295 SMBINTR(odvp))) 2296 return (EINTR); 2297 if (smbfs_rw_enter_sig(&ndnp->r_rwlock, RW_WRITER, 2298 SMBINTR(ndvp))) { 2299 smbfs_rw_exit(&odnp->r_rwlock); 2300 return (EINTR); 2301 } 2302 } else { 2303 if (smbfs_rw_enter_sig(&ndnp->r_rwlock, RW_WRITER, 2304 SMBINTR(ndvp))) 2305 return (EINTR); 2306 if (smbfs_rw_enter_sig(&odnp->r_rwlock, RW_WRITER, 2307 SMBINTR(odvp))) { 2308 smbfs_rw_exit(&ndnp->r_rwlock); 2309 return (EINTR); 2310 } 2311 } 2312 smb_credinit(&scred, cr); 2313 2314 /* Lookup the "old" name */ 2315 error = smbfslookup(odvp, onm, &ovp, cr, 0, ct); 2316 if (error == 0) { 2317 /* 2318 * Do the real rename work 2319 */ 2320 error = smbfsrename(odvp, ovp, ndvp, nnm, &scred, flags); 2321 VN_RELE(ovp); 2322 } 2323 2324 smb_credrele(&scred); 2325 smbfs_rw_exit(&odnp->r_rwlock); 2326 smbfs_rw_exit(&ndnp->r_rwlock); 2327 2328 return (error); 2329 } 2330 2331 /* 2332 * smbfsrename does the real work of renaming in SMBFS 2333 * Caller has done dir access checks etc. 2334 */ 2335 /* ARGSUSED */ 2336 static int 2337 smbfsrename(vnode_t *odvp, vnode_t *ovp, vnode_t *ndvp, char *nnm, 2338 struct smb_cred *scred, int flags) 2339 { 2340 smbnode_t *odnp = VTOSMB(odvp); 2341 smbnode_t *onp = VTOSMB(ovp); 2342 smbnode_t *ndnp = VTOSMB(ndvp); 2343 vnode_t *nvp = NULL; 2344 int error; 2345 int nvp_locked = 0; 2346 2347 /* Things our caller should have checked. */ 2348 ASSERT(curproc->p_zone == VTOSMI(odvp)->smi_zone_ref.zref_zone); 2349 ASSERT(odvp->v_vfsp == ndvp->v_vfsp); 2350 ASSERT(odnp->r_rwlock.owner == curthread); 2351 ASSERT(ndnp->r_rwlock.owner == curthread); 2352 2353 /* 2354 * Lookup the target file. If it exists, it needs to be 2355 * checked to see whether it is a mount point and whether 2356 * it is active (open). 2357 */ 2358 error = smbfslookup(ndvp, nnm, &nvp, scred->scr_cred, 0, NULL); 2359 if (!error) { 2360 /* 2361 * Target (nvp) already exists. Check that it 2362 * has the same type as the source. The server 2363 * will check this also, (and more reliably) but 2364 * this lets us return the correct error codes. 2365 */ 2366 if (ovp->v_type == VDIR) { 2367 if (nvp->v_type != VDIR) { 2368 error = ENOTDIR; 2369 goto out; 2370 } 2371 } else { 2372 if (nvp->v_type == VDIR) { 2373 error = EISDIR; 2374 goto out; 2375 } 2376 } 2377 2378 /* 2379 * POSIX dictates that when the source and target 2380 * entries refer to the same file object, rename 2381 * must do nothing and exit without error. 2382 */ 2383 if (ovp == nvp) { 2384 error = 0; 2385 goto out; 2386 } 2387 2388 /* 2389 * Also must ensure the target is not a mount point, 2390 * and keep mount/umount away until we're done. 2391 */ 2392 if (vn_vfsrlock(nvp)) { 2393 error = EBUSY; 2394 goto out; 2395 } 2396 nvp_locked = 1; 2397 if (vn_mountedvfs(nvp) != NULL) { 2398 error = EBUSY; 2399 goto out; 2400 } 2401 2402 /* 2403 * CIFS may give a SHARING_VIOLATION error when 2404 * trying to rename onto an exising object, 2405 * so try to remove the target first. 2406 * (Only for files, not directories.) 2407 */ 2408 if (nvp->v_type == VDIR) { 2409 error = EEXIST; 2410 goto out; 2411 } 2412 error = smbfsremove(ndvp, nvp, scred, flags); 2413 if (error != 0) 2414 goto out; 2415 2416 /* 2417 * OK, removed the target file. Continue as if 2418 * lookup target had failed (nvp == NULL). 2419 */ 2420 vn_vfsunlock(nvp); 2421 nvp_locked = 0; 2422 VN_RELE(nvp); 2423 nvp = NULL; 2424 } /* nvp */ 2425 2426 smbfs_attrcache_remove(onp); 2427 2428 error = smbfs_smb_rename(onp, ndnp, nnm, strlen(nnm), scred); 2429 2430 /* 2431 * If the old name should no longer exist, 2432 * discard any cached attributes under it. 2433 */ 2434 if (error == 0) 2435 smbfs_attrcache_prune(onp); 2436 2437 out: 2438 if (nvp) { 2439 if (nvp_locked) 2440 vn_vfsunlock(nvp); 2441 VN_RELE(nvp); 2442 } 2443 2444 return (error); 2445 } 2446 2447 /* 2448 * XXX 2449 * vsecattr_t is new to build 77, and we need to eventually support 2450 * it in order to create an ACL when an object is created. 2451 * 2452 * This op should support the new FIGNORECASE flag for case-insensitive 2453 * lookups, per PSARC 2007/244. 2454 */ 2455 /* ARGSUSED */ 2456 static int 2457 smbfs_mkdir(vnode_t *dvp, char *nm, struct vattr *va, vnode_t **vpp, 2458 cred_t *cr, caller_context_t *ct, int flags, vsecattr_t *vsecp) 2459 { 2460 vnode_t *vp; 2461 struct smbnode *dnp = VTOSMB(dvp); 2462 struct smbmntinfo *smi = VTOSMI(dvp); 2463 struct smb_cred scred; 2464 struct smbfattr fattr; 2465 const char *name = (const char *) nm; 2466 int nmlen = strlen(name); 2467 int error, hiderr; 2468 2469 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 2470 return (EPERM); 2471 2472 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2473 return (EIO); 2474 2475 if ((nmlen == 1 && name[0] == '.') || 2476 (nmlen == 2 && name[0] == '.' && name[1] == '.')) 2477 return (EEXIST); 2478 2479 /* Only plain files are allowed in V_XATTRDIR. */ 2480 if (dvp->v_flag & V_XATTRDIR) 2481 return (EINVAL); 2482 2483 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp))) 2484 return (EINTR); 2485 smb_credinit(&scred, cr); 2486 2487 /* 2488 * XXX: Do we need r_lkserlock too? 2489 * No use of any shared fid or fctx... 2490 */ 2491 2492 /* 2493 * Require write access in the containing directory. 2494 */ 2495 error = smbfs_access(dvp, VWRITE, 0, cr, ct); 2496 if (error) 2497 goto out; 2498 2499 error = smbfs_smb_mkdir(dnp, name, nmlen, &scred); 2500 if (error) 2501 goto out; 2502 2503 error = smbfs_smb_lookup(dnp, &name, &nmlen, &fattr, &scred); 2504 if (error) 2505 goto out; 2506 2507 smbfs_attr_touchdir(dnp); 2508 2509 error = smbfs_nget(dvp, name, nmlen, &fattr, &vp); 2510 if (error) 2511 goto out; 2512 2513 if (name[0] == '.') 2514 if ((hiderr = smbfs_smb_hideit(VTOSMB(vp), NULL, 0, &scred))) 2515 SMBVDEBUG("hide failure %d\n", hiderr); 2516 2517 /* Success! */ 2518 *vpp = vp; 2519 error = 0; 2520 out: 2521 smb_credrele(&scred); 2522 smbfs_rw_exit(&dnp->r_rwlock); 2523 2524 if (name != nm) 2525 smbfs_name_free(name, nmlen); 2526 2527 return (error); 2528 } 2529 2530 /* 2531 * XXX 2532 * This op should support the new FIGNORECASE flag for case-insensitive 2533 * lookups, per PSARC 2007/244. 2534 */ 2535 /* ARGSUSED */ 2536 static int 2537 smbfs_rmdir(vnode_t *dvp, char *nm, vnode_t *cdir, cred_t *cr, 2538 caller_context_t *ct, int flags) 2539 { 2540 vnode_t *vp = NULL; 2541 int vp_locked = 0; 2542 struct smbmntinfo *smi = VTOSMI(dvp); 2543 struct smbnode *dnp = VTOSMB(dvp); 2544 struct smbnode *np; 2545 struct smb_cred scred; 2546 int error; 2547 2548 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 2549 return (EPERM); 2550 2551 if (smi->smi_flags & SMI_DEAD || dvp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2552 return (EIO); 2553 2554 if (smbfs_rw_enter_sig(&dnp->r_rwlock, RW_WRITER, SMBINTR(dvp))) 2555 return (EINTR); 2556 smb_credinit(&scred, cr); 2557 2558 /* 2559 * Require w/x access in the containing directory. 2560 * Server handles all other access checks. 2561 */ 2562 error = smbfs_access(dvp, VEXEC|VWRITE, 0, cr, ct); 2563 if (error) 2564 goto out; 2565 2566 /* 2567 * First lookup the entry to be removed. 2568 */ 2569 error = smbfslookup(dvp, nm, &vp, cr, 0, ct); 2570 if (error) 2571 goto out; 2572 np = VTOSMB(vp); 2573 2574 /* 2575 * Disallow rmdir of "." or current dir, or the FS root. 2576 * Also make sure it's a directory, not a mount point, 2577 * and lock to keep mount/umount away until we're done. 2578 */ 2579 if ((vp == dvp) || (vp == cdir) || (vp->v_flag & VROOT)) { 2580 error = EINVAL; 2581 goto out; 2582 } 2583 if (vp->v_type != VDIR) { 2584 error = ENOTDIR; 2585 goto out; 2586 } 2587 if (vn_vfsrlock(vp)) { 2588 error = EBUSY; 2589 goto out; 2590 } 2591 vp_locked = 1; 2592 if (vn_mountedvfs(vp) != NULL) { 2593 error = EBUSY; 2594 goto out; 2595 } 2596 2597 smbfs_attrcache_remove(np); 2598 error = smbfs_smb_rmdir(np, &scred); 2599 2600 /* 2601 * Similar to smbfs_remove 2602 */ 2603 switch (error) { 2604 case 0: 2605 case ENOENT: 2606 case ENOTDIR: 2607 smbfs_attrcache_prune(np); 2608 break; 2609 } 2610 2611 if (error) 2612 goto out; 2613 2614 mutex_enter(&np->r_statelock); 2615 dnp->n_flag |= NMODIFIED; 2616 mutex_exit(&np->r_statelock); 2617 smbfs_attr_touchdir(dnp); 2618 smbfs_rmhash(np); 2619 2620 out: 2621 if (vp) { 2622 if (vp_locked) 2623 vn_vfsunlock(vp); 2624 VN_RELE(vp); 2625 } 2626 smb_credrele(&scred); 2627 smbfs_rw_exit(&dnp->r_rwlock); 2628 2629 return (error); 2630 } 2631 2632 2633 /* ARGSUSED */ 2634 static int 2635 smbfs_readdir(vnode_t *vp, struct uio *uiop, cred_t *cr, int *eofp, 2636 caller_context_t *ct, int flags) 2637 { 2638 struct smbnode *np = VTOSMB(vp); 2639 int error = 0; 2640 smbmntinfo_t *smi; 2641 2642 smi = VTOSMI(vp); 2643 2644 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 2645 return (EIO); 2646 2647 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2648 return (EIO); 2649 2650 /* 2651 * Require read access in the directory. 2652 */ 2653 error = smbfs_access(vp, VREAD, 0, cr, ct); 2654 if (error) 2655 return (error); 2656 2657 ASSERT(smbfs_rw_lock_held(&np->r_rwlock, RW_READER)); 2658 2659 /* 2660 * XXX: Todo readdir cache here 2661 * Note: NFS code is just below this. 2662 * 2663 * I am serializing the entire readdir opreation 2664 * now since we have not yet implemented readdir 2665 * cache. This fix needs to be revisited once 2666 * we implement readdir cache. 2667 */ 2668 if (smbfs_rw_enter_sig(&np->r_lkserlock, RW_WRITER, SMBINTR(vp))) 2669 return (EINTR); 2670 2671 error = smbfs_readvdir(vp, uiop, cr, eofp, ct); 2672 2673 smbfs_rw_exit(&np->r_lkserlock); 2674 2675 return (error); 2676 } 2677 2678 /* ARGSUSED */ 2679 static int 2680 smbfs_readvdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *eofp, 2681 caller_context_t *ct) 2682 { 2683 /* 2684 * Note: "limit" tells the SMB-level FindFirst/FindNext 2685 * functions how many directory entries to request in 2686 * each OtW call. It needs to be large enough so that 2687 * we don't make lots of tiny OtW requests, but there's 2688 * no point making it larger than the maximum number of 2689 * OtW entries that would fit in a maximum sized trans2 2690 * response (64k / 48). Beyond that, it's just tuning. 2691 * WinNT used 512, Win2k used 1366. We use 1000. 2692 */ 2693 static const int limit = 1000; 2694 /* Largest possible dirent size. */ 2695 static const size_t dbufsiz = DIRENT64_RECLEN(SMB_MAXFNAMELEN); 2696 struct smb_cred scred; 2697 vnode_t *newvp; 2698 struct smbnode *np = VTOSMB(vp); 2699 struct smbfs_fctx *ctx; 2700 struct dirent64 *dp; 2701 ssize_t save_resid; 2702 offset_t save_offset; /* 64 bits */ 2703 int offset; /* yes, 32 bits */ 2704 int nmlen, error; 2705 ushort_t reclen; 2706 2707 ASSERT(curproc->p_zone == VTOSMI(vp)->smi_zone_ref.zref_zone); 2708 2709 /* Make sure we serialize for n_dirseq use. */ 2710 ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_WRITER)); 2711 2712 /* 2713 * Make sure smbfs_open filled in n_dirseq 2714 */ 2715 if (np->n_dirseq == NULL) 2716 return (EBADF); 2717 2718 /* Check for overflow of (32-bit) directory offset. */ 2719 if (uio->uio_loffset < 0 || uio->uio_loffset > INT32_MAX || 2720 (uio->uio_loffset + uio->uio_resid) > INT32_MAX) 2721 return (EINVAL); 2722 2723 /* Require space for at least one dirent. */ 2724 if (uio->uio_resid < dbufsiz) 2725 return (EINVAL); 2726 2727 SMBVDEBUG("dirname='%s'\n", np->n_rpath); 2728 smb_credinit(&scred, cr); 2729 dp = kmem_alloc(dbufsiz, KM_SLEEP); 2730 2731 save_resid = uio->uio_resid; 2732 save_offset = uio->uio_loffset; 2733 offset = uio->uio_offset; 2734 SMBVDEBUG("in: offset=%d, resid=%d\n", 2735 (int)uio->uio_offset, (int)uio->uio_resid); 2736 error = 0; 2737 2738 /* 2739 * Generate the "." and ".." entries here so we can 2740 * (1) make sure they appear (but only once), and 2741 * (2) deal with getting their I numbers which the 2742 * findnext below does only for normal names. 2743 */ 2744 while (offset < FIRST_DIROFS) { 2745 /* 2746 * Tricky bit filling in the first two: 2747 * offset 0 is ".", offset 1 is ".." 2748 * so strlen of these is offset+1. 2749 */ 2750 reclen = DIRENT64_RECLEN(offset + 1); 2751 if (uio->uio_resid < reclen) 2752 goto out; 2753 bzero(dp, reclen); 2754 dp->d_reclen = reclen; 2755 dp->d_name[0] = '.'; 2756 dp->d_name[1] = '.'; 2757 dp->d_name[offset + 1] = '\0'; 2758 /* 2759 * Want the real I-numbers for the "." and ".." 2760 * entries. For these two names, we know that 2761 * smbfslookup can get the nodes efficiently. 2762 */ 2763 error = smbfslookup(vp, dp->d_name, &newvp, cr, 1, ct); 2764 if (error) { 2765 dp->d_ino = np->n_ino + offset; /* fiction */ 2766 } else { 2767 dp->d_ino = VTOSMB(newvp)->n_ino; 2768 VN_RELE(newvp); 2769 } 2770 /* 2771 * Note: d_off is the offset that a user-level program 2772 * should seek to for reading the NEXT directory entry. 2773 * See libc: readdir, telldir, seekdir 2774 */ 2775 dp->d_off = offset + 1; 2776 error = uiomove(dp, reclen, UIO_READ, uio); 2777 if (error) 2778 goto out; 2779 /* 2780 * Note: uiomove updates uio->uio_offset, 2781 * but we want it to be our "cookie" value, 2782 * which just counts dirents ignoring size. 2783 */ 2784 uio->uio_offset = ++offset; 2785 } 2786 2787 /* 2788 * If there was a backward seek, we have to reopen. 2789 */ 2790 if (offset < np->n_dirofs) { 2791 SMBVDEBUG("Reopening search %d:%d\n", 2792 offset, np->n_dirofs); 2793 error = smbfs_smb_findopen(np, "*", 1, 2794 SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, 2795 &scred, &ctx); 2796 if (error) { 2797 SMBVDEBUG("can not open search, error = %d", error); 2798 goto out; 2799 } 2800 /* free the old one */ 2801 (void) smbfs_smb_findclose(np->n_dirseq, &scred); 2802 /* save the new one */ 2803 np->n_dirseq = ctx; 2804 np->n_dirofs = FIRST_DIROFS; 2805 } else { 2806 ctx = np->n_dirseq; 2807 } 2808 2809 /* 2810 * Skip entries before the requested offset. 2811 */ 2812 while (np->n_dirofs < offset) { 2813 error = smbfs_smb_findnext(ctx, limit, &scred); 2814 if (error != 0) 2815 goto out; 2816 np->n_dirofs++; 2817 } 2818 2819 /* 2820 * While there's room in the caller's buffer: 2821 * get a directory entry from SMB, 2822 * convert to a dirent, copyout. 2823 * We stop when there is no longer room for a 2824 * maximum sized dirent because we must decide 2825 * before we know anything about the next entry. 2826 */ 2827 while (uio->uio_resid >= dbufsiz) { 2828 error = smbfs_smb_findnext(ctx, limit, &scred); 2829 if (error != 0) 2830 goto out; 2831 np->n_dirofs++; 2832 2833 /* Sanity check the name length. */ 2834 nmlen = ctx->f_nmlen; 2835 if (nmlen > SMB_MAXFNAMELEN) { 2836 nmlen = SMB_MAXFNAMELEN; 2837 SMBVDEBUG("Truncating name: %s\n", ctx->f_name); 2838 } 2839 if (smbfs_fastlookup) { 2840 /* See comment at smbfs_fastlookup above. */ 2841 if (smbfs_nget(vp, ctx->f_name, nmlen, 2842 &ctx->f_attr, &newvp) == 0) 2843 VN_RELE(newvp); 2844 } 2845 2846 reclen = DIRENT64_RECLEN(nmlen); 2847 bzero(dp, reclen); 2848 dp->d_reclen = reclen; 2849 bcopy(ctx->f_name, dp->d_name, nmlen); 2850 dp->d_name[nmlen] = '\0'; 2851 dp->d_ino = ctx->f_inum; 2852 dp->d_off = offset + 1; /* See d_off comment above */ 2853 error = uiomove(dp, reclen, UIO_READ, uio); 2854 if (error) 2855 goto out; 2856 /* See comment re. uio_offset above. */ 2857 uio->uio_offset = ++offset; 2858 } 2859 2860 out: 2861 /* 2862 * When we come to the end of a directory, the 2863 * SMB-level functions return ENOENT, but the 2864 * caller is not expecting an error return. 2865 * 2866 * Also note that we must delay the call to 2867 * smbfs_smb_findclose(np->n_dirseq, ...) 2868 * until smbfs_close so that all reads at the 2869 * end of the directory will return no data. 2870 */ 2871 if (error == ENOENT) { 2872 error = 0; 2873 if (eofp) 2874 *eofp = 1; 2875 } 2876 /* 2877 * If we encountered an error (i.e. "access denied") 2878 * from the FindFirst call, we will have copied out 2879 * the "." and ".." entries leaving offset == 2. 2880 * In that case, restore the original offset/resid 2881 * so the caller gets no data with the error. 2882 */ 2883 if (error != 0 && offset == FIRST_DIROFS) { 2884 uio->uio_loffset = save_offset; 2885 uio->uio_resid = save_resid; 2886 } 2887 SMBVDEBUG("out: offset=%d, resid=%d\n", 2888 (int)uio->uio_offset, (int)uio->uio_resid); 2889 2890 kmem_free(dp, dbufsiz); 2891 smb_credrele(&scred); 2892 return (error); 2893 } 2894 2895 2896 /* 2897 * The pair of functions VOP_RWLOCK, VOP_RWUNLOCK 2898 * are optional functions that are called by: 2899 * getdents, before/after VOP_READDIR 2900 * pread, before/after ... VOP_READ 2901 * pwrite, before/after ... VOP_WRITE 2902 * (other places) 2903 * 2904 * Careful here: None of the above check for any 2905 * error returns from VOP_RWLOCK / VOP_RWUNLOCK! 2906 * In fact, the return value from _rwlock is NOT 2907 * an error code, but V_WRITELOCK_TRUE / _FALSE. 2908 * 2909 * Therefore, it's up to _this_ code to make sure 2910 * the lock state remains balanced, which means 2911 * we can't "bail out" on interrupts, etc. 2912 */ 2913 2914 /* ARGSUSED2 */ 2915 static int 2916 smbfs_rwlock(vnode_t *vp, int write_lock, caller_context_t *ctp) 2917 { 2918 smbnode_t *np = VTOSMB(vp); 2919 2920 if (!write_lock) { 2921 (void) smbfs_rw_enter_sig(&np->r_rwlock, RW_READER, FALSE); 2922 return (V_WRITELOCK_FALSE); 2923 } 2924 2925 2926 (void) smbfs_rw_enter_sig(&np->r_rwlock, RW_WRITER, FALSE); 2927 return (V_WRITELOCK_TRUE); 2928 } 2929 2930 /* ARGSUSED */ 2931 static void 2932 smbfs_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ctp) 2933 { 2934 smbnode_t *np = VTOSMB(vp); 2935 2936 smbfs_rw_exit(&np->r_rwlock); 2937 } 2938 2939 2940 /* ARGSUSED */ 2941 static int 2942 smbfs_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct) 2943 { 2944 smbmntinfo_t *smi; 2945 2946 smi = VTOSMI(vp); 2947 2948 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 2949 return (EPERM); 2950 2951 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 2952 return (EIO); 2953 2954 /* 2955 * Because we stuff the readdir cookie into the offset field 2956 * someone may attempt to do an lseek with the cookie which 2957 * we want to succeed. 2958 */ 2959 if (vp->v_type == VDIR) 2960 return (0); 2961 2962 /* Like NFS3, just check for 63-bit overflow. */ 2963 if (*noffp < 0) 2964 return (EINVAL); 2965 2966 return (0); 2967 } 2968 2969 2970 /* 2971 * XXX 2972 * This op may need to support PSARC 2007/440, nbmand changes for CIFS Service. 2973 */ 2974 static int 2975 smbfs_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag, 2976 offset_t offset, struct flk_callback *flk_cbp, cred_t *cr, 2977 caller_context_t *ct) 2978 { 2979 if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone) 2980 return (EIO); 2981 2982 if (VTOSMI(vp)->smi_flags & SMI_LLOCK) 2983 return (fs_frlock(vp, cmd, bfp, flag, offset, flk_cbp, cr, ct)); 2984 else 2985 return (ENOSYS); 2986 } 2987 2988 /* 2989 * Free storage space associated with the specified vnode. The portion 2990 * to be freed is specified by bfp->l_start and bfp->l_len (already 2991 * normalized to a "whence" of 0). 2992 * 2993 * Called by fcntl(fd, F_FREESP, lkp) for libc:ftruncate, etc. 2994 */ 2995 /* ARGSUSED */ 2996 static int 2997 smbfs_space(vnode_t *vp, int cmd, struct flock64 *bfp, int flag, 2998 offset_t offset, cred_t *cr, caller_context_t *ct) 2999 { 3000 int error; 3001 smbmntinfo_t *smi; 3002 3003 smi = VTOSMI(vp); 3004 3005 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 3006 return (EIO); 3007 3008 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 3009 return (EIO); 3010 3011 /* Caller (fcntl) has checked v_type */ 3012 ASSERT(vp->v_type == VREG); 3013 if (cmd != F_FREESP) 3014 return (EINVAL); 3015 3016 /* 3017 * Like NFS3, no 32-bit offset checks here. 3018 * Our SMB layer takes care to return EFBIG 3019 * when it has to fallback to a 32-bit call. 3020 */ 3021 3022 error = convoff(vp, bfp, 0, offset); 3023 if (!error) { 3024 ASSERT(bfp->l_start >= 0); 3025 if (bfp->l_len == 0) { 3026 struct vattr va; 3027 3028 /* 3029 * ftruncate should not change the ctime and 3030 * mtime if we truncate the file to its 3031 * previous size. 3032 */ 3033 va.va_mask = AT_SIZE; 3034 error = smbfsgetattr(vp, &va, cr); 3035 if (error || va.va_size == bfp->l_start) 3036 return (error); 3037 va.va_mask = AT_SIZE; 3038 va.va_size = bfp->l_start; 3039 error = smbfssetattr(vp, &va, 0, cr); 3040 } else 3041 error = EINVAL; 3042 } 3043 3044 return (error); 3045 } 3046 3047 /* ARGSUSED */ 3048 static int 3049 smbfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr, 3050 caller_context_t *ct) 3051 { 3052 vfs_t *vfs; 3053 smbmntinfo_t *smi; 3054 struct smb_share *ssp; 3055 3056 vfs = vp->v_vfsp; 3057 smi = VFTOSMI(vfs); 3058 3059 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 3060 return (EIO); 3061 3062 if (smi->smi_flags & SMI_DEAD || vp->v_vfsp->vfs_flag & VFS_UNMOUNTED) 3063 return (EIO); 3064 3065 switch (cmd) { 3066 case _PC_FILESIZEBITS: 3067 ssp = smi->smi_share; 3068 if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES) 3069 *valp = 64; 3070 else 3071 *valp = 32; 3072 break; 3073 3074 case _PC_LINK_MAX: 3075 /* We only ever report one link to an object */ 3076 *valp = 1; 3077 break; 3078 3079 case _PC_ACL_ENABLED: 3080 /* 3081 * Always indicate that ACLs are enabled and 3082 * that we support ACE_T format, otherwise 3083 * libsec will ask for ACLENT_T format data 3084 * which we don't support. 3085 */ 3086 *valp = _ACL_ACE_ENABLED; 3087 break; 3088 3089 case _PC_SYMLINK_MAX: /* No symlinks until we do Unix extensions */ 3090 *valp = 0; 3091 break; 3092 3093 case _PC_XATTR_EXISTS: 3094 if (vfs->vfs_flag & VFS_XATTR) { 3095 *valp = smbfs_xa_exists(vp, cr); 3096 break; 3097 } 3098 return (EINVAL); 3099 3100 case _PC_SATTR_ENABLED: 3101 case _PC_SATTR_EXISTS: 3102 *valp = 1; 3103 break; 3104 3105 case _PC_TIMESTAMP_RESOLUTION: 3106 /* 3107 * Windows times are tenths of microseconds 3108 * (multiples of 100 nanoseconds). 3109 */ 3110 *valp = 100L; 3111 break; 3112 3113 default: 3114 return (fs_pathconf(vp, cmd, valp, cr, ct)); 3115 } 3116 return (0); 3117 } 3118 3119 /* ARGSUSED */ 3120 static int 3121 smbfs_getsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr, 3122 caller_context_t *ct) 3123 { 3124 vfs_t *vfsp; 3125 smbmntinfo_t *smi; 3126 int error; 3127 uint_t mask; 3128 3129 vfsp = vp->v_vfsp; 3130 smi = VFTOSMI(vfsp); 3131 3132 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 3133 return (EIO); 3134 3135 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 3136 return (EIO); 3137 3138 /* 3139 * Our _pathconf indicates _ACL_ACE_ENABLED, 3140 * so we should only see VSA_ACE, etc here. 3141 * Note: vn_create asks for VSA_DFACLCNT, 3142 * and it expects ENOSYS and empty data. 3143 */ 3144 mask = vsa->vsa_mask & (VSA_ACE | VSA_ACECNT | 3145 VSA_ACE_ACLFLAGS | VSA_ACE_ALLTYPES); 3146 if (mask == 0) 3147 return (ENOSYS); 3148 3149 if (smi->smi_flags & SMI_ACL) 3150 error = smbfs_acl_getvsa(vp, vsa, flag, cr); 3151 else 3152 error = ENOSYS; 3153 3154 if (error == ENOSYS) 3155 error = fs_fab_acl(vp, vsa, flag, cr, ct); 3156 3157 return (error); 3158 } 3159 3160 /* ARGSUSED */ 3161 static int 3162 smbfs_setsecattr(vnode_t *vp, vsecattr_t *vsa, int flag, cred_t *cr, 3163 caller_context_t *ct) 3164 { 3165 vfs_t *vfsp; 3166 smbmntinfo_t *smi; 3167 int error; 3168 uint_t mask; 3169 3170 vfsp = vp->v_vfsp; 3171 smi = VFTOSMI(vfsp); 3172 3173 if (curproc->p_zone != smi->smi_zone_ref.zref_zone) 3174 return (EIO); 3175 3176 if (smi->smi_flags & SMI_DEAD || vfsp->vfs_flag & VFS_UNMOUNTED) 3177 return (EIO); 3178 3179 /* 3180 * Our _pathconf indicates _ACL_ACE_ENABLED, 3181 * so we should only see VSA_ACE, etc here. 3182 */ 3183 mask = vsa->vsa_mask & (VSA_ACE | VSA_ACECNT); 3184 if (mask == 0) 3185 return (ENOSYS); 3186 3187 if (vfsp->vfs_flag & VFS_RDONLY) 3188 return (EROFS); 3189 3190 /* 3191 * Allow only the mount owner to do this. 3192 * See comments at smbfs_access_rwx. 3193 */ 3194 error = secpolicy_vnode_setdac(cr, smi->smi_uid); 3195 if (error != 0) 3196 return (error); 3197 3198 if (smi->smi_flags & SMI_ACL) 3199 error = smbfs_acl_setvsa(vp, vsa, flag, cr); 3200 else 3201 error = ENOSYS; 3202 3203 return (error); 3204 } 3205 3206 3207 /* 3208 * XXX 3209 * This op should eventually support PSARC 2007/268. 3210 */ 3211 static int 3212 smbfs_shrlock(vnode_t *vp, int cmd, struct shrlock *shr, int flag, cred_t *cr, 3213 caller_context_t *ct) 3214 { 3215 if (curproc->p_zone != VTOSMI(vp)->smi_zone_ref.zref_zone) 3216 return (EIO); 3217 3218 if (VTOSMI(vp)->smi_flags & SMI_LLOCK) 3219 return (fs_shrlock(vp, cmd, shr, flag, cr, ct)); 3220 else 3221 return (ENOSYS); 3222 }