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