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