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