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