1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2020 Tintri by DDN, Inc. All rights reserved. 24 */ 25 /* 26 * SMB Node State Machine 27 * ---------------------- 28 * 29 * 30 * +----------- Creation/Allocation 31 * | 32 * | T0 33 * | 34 * v 35 * +----------------------------+ 36 * | SMB_NODE_STATE_AVAILABLE | 37 * +----------------------------+ 38 * | 39 * | T1 40 * | 41 * v 42 * +-----------------------------+ 43 * | SMB_NODE_STATE_DESTROYING | 44 * +-----------------------------+ 45 * | 46 * | 47 * | T2 48 * | 49 * +----------> Deletion/Free 50 * 51 * Transition T0 52 * 53 * This transition occurs in smb_node_lookup(). If the node looked for is 54 * not found in the has table a new node is created. The reference count is 55 * initialized to 1 and the state initialized to SMB_NODE_STATE_AVAILABLE. 56 * 57 * Transition T1 58 * 59 * This transition occurs in smb_node_release(). If the reference count 60 * drops to zero the state is moved to SMB_NODE_STATE_DESTROYING and no more 61 * reference count will be given out for that node. 62 * 63 * Transition T2 64 * 65 * This transition occurs in smb_node_release(). The structure is deleted. 66 * 67 * Comments 68 * -------- 69 * 70 * The reason the smb node has 2 states is the following synchronization 71 * rule: 72 * 73 * There's a mutex embedded in the node used to protect its fields and 74 * there's a lock embedded in the bucket of the hash table the node belongs 75 * to. To increment or to decrement the reference count the mutex must be 76 * entered. To insert the node into the bucket and to remove it from the 77 * bucket the lock must be entered in RW_WRITER mode. When both (mutex and 78 * lock) have to be entered, the lock has always to be entered first then 79 * the mutex. This prevents a deadlock between smb_node_lookup() and 80 * smb_node_release() from occurring. However, in smb_node_release() when the 81 * reference count drops to zero and triggers the deletion of the node, the 82 * mutex has to be released before entering the lock of the bucket (to 83 * remove the node). This creates a window during which the node that is 84 * about to be freed could be given out by smb_node_lookup(). To close that 85 * window the node is moved to the state SMB_NODE_STATE_DESTROYING before 86 * releasing the mutex. That way, even if smb_node_lookup() finds it, the 87 * state will indicate that the node should be treated as non existent (of 88 * course the state of the node should be tested/updated under the 89 * protection of the mutex). 90 */ 91 #include <smbsrv/smb2_kproto.h> 92 #include <smbsrv/smb_fsops.h> 93 #include <smbsrv/smb_kstat.h> 94 #include <sys/ddi.h> 95 #include <sys/extdirent.h> 96 #include <sys/pathname.h> 97 #include <sys/sdt.h> 98 #include <sys/nbmlock.h> 99 #include <fs/fs_reparse.h> 100 101 uint32_t smb_is_executable(char *); 102 static void smb_node_create_audit_buf(smb_node_t *, int); 103 static void smb_node_destroy_audit_buf(smb_node_t *); 104 static void smb_node_audit(smb_node_t *); 105 static smb_node_t *smb_node_alloc(char *, vnode_t *, smb_llist_t *, uint32_t); 106 static void smb_node_free(smb_node_t *); 107 static int smb_node_constructor(void *, void *, int); 108 static void smb_node_destructor(void *, void *); 109 static smb_llist_t *smb_node_get_hash(fsid_t *, smb_attr_t *, uint32_t *); 110 111 static void smb_node_init_reparse(smb_node_t *, smb_attr_t *); 112 static void smb_node_init_system(smb_node_t *); 113 114 #define VALIDATE_DIR_NODE(_dir_, _node_) \ 115 ASSERT((_dir_)->n_magic == SMB_NODE_MAGIC); \ 116 ASSERT(((_dir_)->vp->v_xattrdir) || ((_dir_)->vp->v_type == VDIR)); \ 117 ASSERT((_dir_)->n_dnode != (_node_)); 118 119 /* round sz to DEV_BSIZE block */ 120 #define SMB_ALLOCSZ(sz) (((sz) + DEV_BSIZE-1) & ~(DEV_BSIZE-1)) 121 122 static kmem_cache_t *smb_node_cache = NULL; 123 static smb_llist_t smb_node_hash_table[SMBND_HASH_MASK+1]; 124 static smb_node_t *smb_root_node; 125 126 /* 127 * smb_node_init 128 * 129 * Initialization of the SMB node layer. 130 * 131 * This function is not multi-thread safe. The caller must make sure only one 132 * thread makes the call. 133 */ 134 void 135 smb_node_init(void) 136 { 137 smb_attr_t attr; 138 smb_llist_t *node_hdr; 139 smb_node_t *node; 140 uint32_t hashkey; 141 int i; 142 143 if (smb_node_cache != NULL) 144 return; 145 146 smb_node_cache = kmem_cache_create(SMBSRV_KSTAT_NODE_CACHE, 147 sizeof (smb_node_t), 8, smb_node_constructor, smb_node_destructor, 148 NULL, NULL, NULL, 0); 149 150 for (i = 0; i <= SMBND_HASH_MASK; i++) { 151 smb_llist_constructor(&smb_node_hash_table[i], 152 sizeof (smb_node_t), offsetof(smb_node_t, n_lnd)); 153 } 154 155 /* 156 * The node cache is shared by all zones, so the smb_root_node 157 * must represent the real (global zone) rootdir. 158 * Note intentional use of kcred here. 159 */ 160 attr.sa_mask = SMB_AT_ALL; 161 VERIFY0(smb_vop_getattr(rootdir, NULL, &attr, 0, kcred)); 162 node_hdr = smb_node_get_hash(&rootdir->v_vfsp->vfs_fsid, &attr, 163 &hashkey); 164 node = smb_node_alloc("/", rootdir, node_hdr, hashkey); 165 smb_llist_enter(node_hdr, RW_WRITER); 166 smb_llist_insert_head(node_hdr, node); 167 smb_llist_exit(node_hdr); 168 smb_root_node = node; /* smb_node_release in smb_node_fini */ 169 } 170 171 /* 172 * smb_node_fini 173 * 174 * This function is not multi-thread safe. The caller must make sure only one 175 * thread makes the call. 176 */ 177 void 178 smb_node_fini(void) 179 { 180 int i; 181 182 if (smb_root_node != NULL) { 183 smb_node_release(smb_root_node); 184 smb_root_node = NULL; 185 } 186 187 if (smb_node_cache == NULL) 188 return; 189 190 #ifdef DEBUG 191 for (i = 0; i <= SMBND_HASH_MASK; i++) { 192 smb_llist_t *bucket; 193 smb_node_t *node; 194 195 /* 196 * The following sequence is just intended for sanity check. 197 * This will have to be modified when the code goes into 198 * production. 199 * 200 * The SMB node hash table should be emtpy at this point. If the 201 * hash table is not empty a panic will be triggered. 202 * 203 * The reason why SMB nodes are still remaining in the hash 204 * table is problably due to a mismatch between calls to 205 * smb_node_lookup() and smb_node_release(). You must track that 206 * down. 207 */ 208 bucket = &smb_node_hash_table[i]; 209 node = smb_llist_head(bucket); 210 while (node != NULL) { 211 cmn_err(CE_NOTE, "leaked node: 0x%p %s", 212 (void *)node, node->od_name); 213 node = smb_llist_next(bucket, node); 214 } 215 } 216 #endif 217 218 for (i = 0; i <= SMBND_HASH_MASK; i++) { 219 smb_llist_destructor(&smb_node_hash_table[i]); 220 } 221 kmem_cache_destroy(smb_node_cache); 222 smb_node_cache = NULL; 223 } 224 225 /* 226 * smb_node_lookup() 227 * 228 * NOTE: This routine should only be called by the file system interface layer, 229 * and not by SMB. 230 * 231 * smb_node_lookup() is called upon successful lookup, mkdir, and create 232 * (for both non-streams and streams). In each of these cases, a held vnode is 233 * passed into this routine. If a new smb_node is created it will take its 234 * own hold on the vnode. The caller's hold therefore still belongs to, and 235 * should be released by, the caller. 236 * 237 * A reference is taken on the smb_node whether found in the hash table 238 * or newly created. 239 * 240 * If an smb_node needs to be created, a reference is also taken on the 241 * dnode (if passed in). 242 * 243 * See smb_node_release() for details on the release of these references. 244 */ 245 246 /*ARGSUSED*/ 247 smb_node_t * 248 smb_node_lookup( 249 struct smb_request *sr, 250 struct open_param *op, 251 cred_t *cred, 252 vnode_t *vp, 253 char *od_name, 254 smb_node_t *dnode, 255 smb_node_t *unode) 256 { 257 smb_llist_t *node_hdr; 258 smb_node_t *node; 259 smb_attr_t attr; 260 uint32_t hashkey = 0; 261 fsid_t fsid; 262 int error; 263 krw_t lock_mode; 264 vnode_t *unnamed_vp = NULL; 265 266 /* 267 * smb_vop_getattr() is called here instead of smb_fsop_getattr(), 268 * because the node may not yet exist. We also do not want to call 269 * it with the list lock held. 270 */ 271 272 if (unode) 273 unnamed_vp = unode->vp; 274 275 /* 276 * This getattr is performed on behalf of the server 277 * that's why kcred is used not the user's cred 278 */ 279 attr.sa_mask = SMB_AT_ALL; 280 error = smb_vop_getattr(vp, unnamed_vp, &attr, 0, zone_kcred()); 281 if (error) 282 return (NULL); 283 284 if (sr && sr->tid_tree) { 285 /* 286 * The fsid for a file is that of the tree, even 287 * if the file resides in a different mountpoint 288 * under the share. 289 */ 290 fsid = SMB_TREE_FSID(sr->tid_tree); 291 } else { 292 /* 293 * This should be getting executed only for the 294 * tree root smb_node. 295 */ 296 fsid = vp->v_vfsp->vfs_fsid; 297 } 298 299 node_hdr = smb_node_get_hash(&fsid, &attr, &hashkey); 300 lock_mode = RW_READER; 301 302 smb_llist_enter(node_hdr, lock_mode); 303 for (;;) { 304 node = list_head(&node_hdr->ll_list); 305 while (node) { 306 ASSERT(node->n_magic == SMB_NODE_MAGIC); 307 ASSERT(node->n_hash_bucket == node_hdr); 308 if ((node->n_hashkey == hashkey) && (node->vp == vp)) { 309 mutex_enter(&node->n_mutex); 310 DTRACE_PROBE1(smb_node_lookup_hit, 311 smb_node_t *, node); 312 switch (node->n_state) { 313 case SMB_NODE_STATE_AVAILABLE: 314 /* The node was found. */ 315 node->n_refcnt++; 316 if ((node->n_dnode == NULL) && 317 (dnode != NULL) && 318 (node != dnode) && 319 (strcmp(od_name, "..") != 0) && 320 (strcmp(od_name, ".") != 0)) { 321 VALIDATE_DIR_NODE(dnode, node); 322 node->n_dnode = dnode; 323 smb_node_ref(dnode); 324 } 325 326 smb_node_audit(node); 327 mutex_exit(&node->n_mutex); 328 smb_llist_exit(node_hdr); 329 return (node); 330 331 case SMB_NODE_STATE_DESTROYING: 332 /* 333 * Although the node exists it is about 334 * to be destroyed. We act as it hasn't 335 * been found. 336 */ 337 mutex_exit(&node->n_mutex); 338 break; 339 default: 340 /* 341 * Although the node exists it is in an 342 * unknown state. We act as it hasn't 343 * been found. 344 */ 345 ASSERT(0); 346 mutex_exit(&node->n_mutex); 347 break; 348 } 349 } 350 node = smb_llist_next(node_hdr, node); 351 } 352 if ((lock_mode == RW_READER) && smb_llist_upgrade(node_hdr)) { 353 lock_mode = RW_WRITER; 354 continue; 355 } 356 break; 357 } 358 node = smb_node_alloc(od_name, vp, node_hdr, hashkey); 359 smb_node_init_reparse(node, &attr); 360 361 if (op) 362 node->flags |= smb_is_executable(op->fqi.fq_last_comp); 363 364 if (dnode) { 365 smb_node_ref(dnode); 366 node->n_dnode = dnode; 367 ASSERT(dnode->n_dnode != node); 368 ASSERT((dnode->vp->v_xattrdir) || 369 (dnode->vp->v_type == VDIR)); 370 } 371 372 if (unode) { 373 smb_node_ref(unode); 374 node->n_unode = unode; 375 } 376 377 smb_node_init_system(node); 378 379 DTRACE_PROBE1(smb_node_lookup_miss, smb_node_t *, node); 380 smb_node_audit(node); 381 smb_llist_insert_head(node_hdr, node); 382 smb_llist_exit(node_hdr); 383 return (node); 384 } 385 386 /* 387 * smb_stream_node_lookup() 388 * 389 * Note: stream_name (the name that will be stored in the "od_name" field 390 * of a stream's smb_node) is the same as the on-disk name for the stream 391 * except that it does not have SMB_STREAM_PREFIX prepended. 392 */ 393 394 smb_node_t * 395 smb_stream_node_lookup(smb_request_t *sr, cred_t *cr, smb_node_t *fnode, 396 vnode_t *xattrdirvp, vnode_t *vp, char *stream_name) 397 { 398 smb_node_t *xattrdir_node; 399 smb_node_t *snode; 400 401 xattrdir_node = smb_node_lookup(sr, NULL, cr, xattrdirvp, XATTR_DIR, 402 fnode, NULL); 403 404 if (xattrdir_node == NULL) 405 return (NULL); 406 407 snode = smb_node_lookup(sr, NULL, cr, vp, stream_name, xattrdir_node, 408 fnode); 409 410 (void) smb_node_release(xattrdir_node); 411 return (snode); 412 } 413 414 415 /* 416 * This function should be called whenever a reference is needed on an 417 * smb_node pointer. The copy of an smb_node pointer from one non-local 418 * data structure to another requires a reference to be taken on the smb_node 419 * (unless the usage is localized). Each data structure deallocation routine 420 * will call smb_node_release() on its smb_node pointers. 421 * 422 * In general, an smb_node pointer residing in a structure should never be 423 * stale. A node pointer may be NULL, however, and care should be taken 424 * prior to calling smb_node_ref(), which ASSERTs that the pointer is valid. 425 * Care also needs to be taken with respect to racing deallocations of a 426 * structure. 427 */ 428 void 429 smb_node_ref(smb_node_t *node) 430 { 431 SMB_NODE_VALID(node); 432 433 mutex_enter(&node->n_mutex); 434 switch (node->n_state) { 435 case SMB_NODE_STATE_AVAILABLE: 436 node->n_refcnt++; 437 ASSERT(node->n_refcnt); 438 DTRACE_PROBE1(smb_node_ref_exit, smb_node_t *, node); 439 smb_node_audit(node); 440 break; 441 default: 442 SMB_PANIC(); 443 } 444 mutex_exit(&node->n_mutex); 445 } 446 447 /* 448 * smb_node_lookup() takes a hold on an smb_node, whether found in the 449 * hash table or newly created. This hold is expected to be released 450 * in the following manner. 451 * 452 * smb_node_lookup() takes an address of an smb_node pointer. This should 453 * be getting passed down via a lookup (whether path name or component), mkdir, 454 * create. If the original smb_node pointer resides in a data structure, then 455 * the deallocation routine for the data structure is responsible for calling 456 * smb_node_release() on the smb_node pointer. Alternatively, 457 * smb_node_release() can be called as soon as the smb_node pointer is no longer 458 * needed. In this case, callers are responsible for setting an embedded 459 * pointer to NULL if it is known that the last reference is being released. 460 * 461 * If the passed-in address of the smb_node pointer belongs to a local variable, 462 * then the caller with the local variable should call smb_node_release() 463 * directly. 464 * 465 * smb_node_release() itself will call smb_node_release() on a node's n_dnode, 466 * as smb_node_lookup() takes a hold on dnode. 467 */ 468 void 469 smb_node_release(smb_node_t *node) 470 { 471 SMB_NODE_VALID(node); 472 473 mutex_enter(&node->n_mutex); 474 ASSERT(node->n_refcnt); 475 DTRACE_PROBE1(smb_node_release, smb_node_t *, node); 476 if (--node->n_refcnt == 0) { 477 switch (node->n_state) { 478 479 case SMB_NODE_STATE_AVAILABLE: 480 node->n_state = SMB_NODE_STATE_DESTROYING; 481 482 /* 483 * While we still hold n_mutex, 484 * make sure FEM hooks are gone. 485 */ 486 if (node->n_fcn_count > 0) { 487 DTRACE_PROBE1(fem__fcn__dangles, 488 smb_node_t *, node); 489 node->n_fcn_count = 0; 490 (void) smb_fem_fcn_uninstall(node); 491 } 492 493 mutex_exit(&node->n_mutex); 494 495 smb_llist_enter(node->n_hash_bucket, RW_WRITER); 496 smb_llist_remove(node->n_hash_bucket, node); 497 smb_llist_exit(node->n_hash_bucket); 498 499 /* 500 * Check if the file was deleted 501 */ 502 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) { 503 smb_node_delete_on_close(node); 504 } 505 506 if (node->n_dnode) { 507 ASSERT(node->n_dnode->n_magic == 508 SMB_NODE_MAGIC); 509 smb_node_release(node->n_dnode); 510 } 511 512 if (node->n_unode) { 513 ASSERT(node->n_unode->n_magic == 514 SMB_NODE_MAGIC); 515 smb_node_release(node->n_unode); 516 } 517 518 smb_node_free(node); 519 return; 520 521 default: 522 SMB_PANIC(); 523 } 524 } 525 smb_node_audit(node); 526 mutex_exit(&node->n_mutex); 527 } 528 529 void 530 smb_node_delete_on_close(smb_node_t *node) 531 { 532 smb_node_t *d_snode; 533 int rc = 0; 534 uint32_t flags = 0; 535 536 d_snode = node->n_dnode; 537 538 ASSERT((node->flags & NODE_FLAGS_DELETE_ON_CLOSE) != 0); 539 540 node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE; 541 node->flags |= NODE_FLAGS_DELETE_COMMITTED; 542 flags = node->n_delete_on_close_flags; 543 ASSERT(node->od_name != NULL); 544 545 if (smb_node_is_dir(node)) 546 rc = smb_fsop_rmdir(0, node->delete_on_close_cred, 547 d_snode, node->od_name, flags); 548 else 549 rc = smb_fsop_remove(0, node->delete_on_close_cred, 550 d_snode, node->od_name, flags); 551 crfree(node->delete_on_close_cred); 552 node->delete_on_close_cred = NULL; 553 554 if (rc != 0) 555 cmn_err(CE_WARN, "File %s could not be removed, rc=%d\n", 556 node->od_name, rc); 557 DTRACE_PROBE2(smb_node_delete_on_close, int, rc, smb_node_t *, node); 558 } 559 560 /* 561 * smb_node_rename() 562 * 563 */ 564 void 565 smb_node_rename( 566 smb_node_t *from_dnode, 567 smb_node_t *ret_node, 568 smb_node_t *to_dnode, 569 char *to_name) 570 { 571 SMB_NODE_VALID(from_dnode); 572 SMB_NODE_VALID(to_dnode); 573 SMB_NODE_VALID(ret_node); 574 575 smb_node_ref(to_dnode); 576 mutex_enter(&ret_node->n_mutex); 577 switch (ret_node->n_state) { 578 case SMB_NODE_STATE_AVAILABLE: 579 ret_node->n_dnode = to_dnode; 580 mutex_exit(&ret_node->n_mutex); 581 ASSERT(to_dnode->n_dnode != ret_node); 582 ASSERT((to_dnode->vp->v_xattrdir) || 583 (to_dnode->vp->v_type == VDIR)); 584 smb_node_release(from_dnode); 585 (void) strcpy(ret_node->od_name, to_name); 586 /* 587 * XXX Need to update attributes? 588 */ 589 break; 590 default: 591 SMB_PANIC(); 592 } 593 } 594 595 /* 596 * Find/create an SMB node for the root of this zone and store it 597 * in *svrootp. Also create nodes leading to this directory. 598 */ 599 int 600 smb_node_root_init(smb_server_t *sv, smb_node_t **svrootp) 601 { 602 zone_t *zone = curzone; 603 int error; 604 605 ASSERT(zone->zone_id == sv->sv_zid); 606 if (smb_root_node == NULL) 607 return (ENOENT); 608 609 /* 610 * We're getting smb nodes below the zone root here, 611 * so need to use kcred, not zone_kcred(). 612 */ 613 error = smb_pathname(NULL, zone->zone_rootpath, 0, 614 smb_root_node, smb_root_node, NULL, svrootp, kcred, NULL); 615 616 return (error); 617 } 618 619 /* 620 * Helper function for smb_node_set_delete_on_close(). Assumes node is a dir. 621 * Return 0 if this is an empty dir. Otherwise return a NT_STATUS code. 622 * Unfortunately, to find out if a directory is empty, we have to read it 623 * and check for anything other than "." or ".." in the readdir buf. 624 */ 625 static uint32_t 626 smb_rmdir_possible(smb_node_t *n) 627 { 628 ASSERT(n->vp->v_type == VDIR); 629 char *buf; 630 char *bufptr; 631 struct dirent64 *dp; 632 uint32_t status = NT_STATUS_SUCCESS; 633 int bsize = SMB_ODIR_BUFSIZE; 634 int eof = 0; 635 636 buf = kmem_alloc(SMB_ODIR_BUFSIZE, KM_SLEEP); 637 638 /* Flags zero: no edirent, no ABE wanted here */ 639 if (smb_vop_readdir(n->vp, 0, buf, &bsize, &eof, 0, zone_kcred())) { 640 status = NT_STATUS_INTERNAL_ERROR; 641 goto out; 642 } 643 644 bufptr = buf; 645 while (bsize > 0) { 646 /* LINTED pointer alignment */ 647 dp = (struct dirent64 *)bufptr; 648 649 bufptr += dp->d_reclen; 650 bsize -= dp->d_reclen; 651 if (bsize < 0) { 652 /* partial record */ 653 status = NT_STATUS_DIRECTORY_NOT_EMPTY; 654 break; 655 } 656 657 if (strcmp(dp->d_name, ".") != 0 && 658 strcmp(dp->d_name, "..") != 0) { 659 status = NT_STATUS_DIRECTORY_NOT_EMPTY; 660 break; 661 } 662 } 663 664 out: 665 kmem_free(buf, SMB_ODIR_BUFSIZE); 666 return (status); 667 } 668 669 /* 670 * When DeleteOnClose is set on an smb_node, the common open code will 671 * reject subsequent open requests for the file. Observation of Windows 672 * 2000 indicates that subsequent opens should be allowed (assuming 673 * there would be no sharing violation) until the file is closed using 674 * the fid on which the DeleteOnClose was requested. 675 * 676 * If there are multiple opens with delete-on-close create options, 677 * whichever the first file handle is closed will trigger the node to be 678 * marked as delete-on-close. The credentials of that ofile will be used 679 * as the delete-on-close credentials of the node. 680 * 681 * Note that "read-only" tests have already happened before this call. 682 */ 683 uint32_t 684 smb_node_set_delete_on_close(smb_node_t *node, cred_t *cr, uint32_t flags) 685 { 686 uint32_t status; 687 688 /* 689 * If the directory is not empty we should fail setting del-on-close 690 * with STATUS_DIRECTORY_NOT_EMPTY. see MS's 691 * "File System Behavior Overview" doc section 4.3.2 692 */ 693 if (smb_node_is_dir(node)) { 694 status = smb_rmdir_possible(node); 695 if (status != 0) { 696 return (status); 697 } 698 } 699 700 /* Dataset roots can't be deleted, so don't set DOC */ 701 if ((node->flags & NODE_FLAGS_VFSROOT) != 0) { 702 return (NT_STATUS_CANNOT_DELETE); 703 } 704 705 mutex_enter(&node->n_mutex); 706 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) { 707 /* It was already marked. We're done. */ 708 mutex_exit(&node->n_mutex); 709 return (NT_STATUS_SUCCESS); 710 } 711 712 crhold(cr); 713 node->delete_on_close_cred = cr; 714 node->n_delete_on_close_flags = flags; 715 node->flags |= NODE_FLAGS_DELETE_ON_CLOSE; 716 mutex_exit(&node->n_mutex); 717 718 /* 719 * Tell any change notify calls to close their handles 720 * and get out of the way. FILE_ACTION_DELETE_PENDING 721 * is a special, internal-only action for this purpose. 722 */ 723 smb_node_notify_change(node, FILE_ACTION_DELETE_PENDING, NULL); 724 725 return (NT_STATUS_SUCCESS); 726 } 727 728 void 729 smb_node_reset_delete_on_close(smb_node_t *node) 730 { 731 mutex_enter(&node->n_mutex); 732 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) { 733 node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE; 734 crfree(node->delete_on_close_cred); 735 node->delete_on_close_cred = NULL; 736 node->n_delete_on_close_flags = 0; 737 } 738 mutex_exit(&node->n_mutex); 739 } 740 741 /* 742 * smb_node_open_check 743 * 744 * check file sharing rules for current open request 745 * against all existing opens for a file. 746 * 747 * Returns NT_STATUS_SHARING_VIOLATION if there is any 748 * sharing conflict, otherwise returns NT_STATUS_SUCCESS. 749 */ 750 uint32_t 751 smb_node_open_check(smb_node_t *node, uint32_t desired_access, 752 uint32_t share_access) 753 { 754 smb_ofile_t *of; 755 uint32_t status; 756 757 SMB_NODE_VALID(node); 758 759 smb_llist_enter(&node->n_ofile_list, RW_READER); 760 of = smb_llist_head(&node->n_ofile_list); 761 while (of) { 762 status = smb_ofile_open_check(of, desired_access, share_access); 763 764 switch (status) { 765 case NT_STATUS_INVALID_HANDLE: 766 case NT_STATUS_SUCCESS: 767 of = smb_llist_next(&node->n_ofile_list, of); 768 break; 769 default: 770 ASSERT(status == NT_STATUS_SHARING_VIOLATION); 771 DTRACE_PROBE3(conflict3, 772 smb_ofile_t, of, 773 uint32_t, desired_access, 774 uint32_t, share_access); 775 smb_llist_exit(&node->n_ofile_list); 776 return (status); 777 } 778 } 779 780 smb_llist_exit(&node->n_ofile_list); 781 return (NT_STATUS_SUCCESS); 782 } 783 784 uint32_t 785 smb_node_rename_check(smb_node_t *node) 786 { 787 smb_ofile_t *of; 788 uint32_t status; 789 790 SMB_NODE_VALID(node); 791 792 /* 793 * Intra-CIFS check 794 */ 795 smb_llist_enter(&node->n_ofile_list, RW_READER); 796 of = smb_llist_head(&node->n_ofile_list); 797 while (of) { 798 status = smb_ofile_rename_check(of); 799 800 switch (status) { 801 case NT_STATUS_INVALID_HANDLE: 802 case NT_STATUS_SUCCESS: 803 of = smb_llist_next(&node->n_ofile_list, of); 804 break; 805 default: 806 ASSERT(status == NT_STATUS_SHARING_VIOLATION); 807 DTRACE_PROBE1(conflict1, smb_ofile_t, of); 808 smb_llist_exit(&node->n_ofile_list); 809 return (status); 810 } 811 } 812 smb_llist_exit(&node->n_ofile_list); 813 return (NT_STATUS_SUCCESS); 814 } 815 816 uint32_t 817 smb_node_delete_check(smb_node_t *node) 818 { 819 smb_ofile_t *of; 820 uint32_t status; 821 822 SMB_NODE_VALID(node); 823 824 if (smb_node_is_dir(node)) 825 return (NT_STATUS_SUCCESS); 826 827 if (smb_node_is_reparse(node)) 828 return (NT_STATUS_ACCESS_DENIED); 829 830 /* 831 * intra-CIFS check 832 */ 833 smb_llist_enter(&node->n_ofile_list, RW_READER); 834 of = smb_llist_head(&node->n_ofile_list); 835 while (of) { 836 status = smb_ofile_delete_check(of); 837 838 switch (status) { 839 case NT_STATUS_INVALID_HANDLE: 840 case NT_STATUS_SUCCESS: 841 of = smb_llist_next(&node->n_ofile_list, of); 842 break; 843 default: 844 ASSERT(status == NT_STATUS_SHARING_VIOLATION); 845 DTRACE_PROBE1(conflict1, smb_ofile_t, of); 846 smb_llist_exit(&node->n_ofile_list); 847 return (status); 848 } 849 } 850 smb_llist_exit(&node->n_ofile_list); 851 return (NT_STATUS_SUCCESS); 852 } 853 854 /* 855 * smb_node_share_check 856 * 857 * Returns: TRUE - ofiles have non-zero share access 858 * B_FALSE - ofile with share access NONE. 859 */ 860 boolean_t 861 smb_node_share_check(smb_node_t *node) 862 { 863 smb_ofile_t *of; 864 boolean_t status = B_TRUE; 865 866 SMB_NODE_VALID(node); 867 868 smb_llist_enter(&node->n_ofile_list, RW_READER); 869 of = smb_llist_head(&node->n_ofile_list); 870 if (of) 871 status = smb_ofile_share_check(of); 872 smb_llist_exit(&node->n_ofile_list); 873 874 return (status); 875 } 876 877 /* 878 * SMB Change Notification 879 */ 880 881 void 882 smb_node_fcn_subscribe(smb_node_t *node) 883 { 884 885 mutex_enter(&node->n_mutex); 886 if (node->n_fcn_count == 0) 887 (void) smb_fem_fcn_install(node); 888 node->n_fcn_count++; 889 mutex_exit(&node->n_mutex); 890 } 891 892 void 893 smb_node_fcn_unsubscribe(smb_node_t *node) 894 { 895 896 mutex_enter(&node->n_mutex); 897 node->n_fcn_count--; 898 if (node->n_fcn_count == 0) { 899 VERIFY0(smb_fem_fcn_uninstall(node)); 900 } 901 mutex_exit(&node->n_mutex); 902 } 903 904 void 905 smb_node_notify_change(smb_node_t *node, uint_t action, const char *name) 906 { 907 smb_ofile_t *of; 908 909 SMB_NODE_VALID(node); 910 911 smb_llist_enter(&node->n_ofile_list, RW_READER); 912 of = smb_llist_head(&node->n_ofile_list); 913 while (of) { 914 /* 915 * We'd rather deliver events only to ofiles that have 916 * subscribed. There's no explicit synchronization with 917 * where this flag is set, but other actions cause this 918 * value to reach visibility soon enough for events to 919 * start arriving by the time we need them to start. 920 * Once nc_subscribed is set, it stays set for the 921 * life of the ofile. 922 */ 923 if (of->f_notify.nc_subscribed) 924 smb_notify_ofile(of, action, name); 925 of = smb_llist_next(&node->n_ofile_list, of); 926 } 927 smb_llist_exit(&node->n_ofile_list); 928 929 /* 930 * After changes that add or remove a name, 931 * we know the directory attributes changed, 932 * and we can tell the immediate parent. 933 */ 934 switch (action) { 935 case FILE_ACTION_ADDED: 936 case FILE_ACTION_REMOVED: 937 case FILE_ACTION_RENAMED_NEW_NAME: 938 /* 939 * Note: FILE_ACTION_RENAMED_OLD_NAME is intentionally 940 * omitted, because it's always followed by another 941 * event with FILE_ACTION_RENAMED_NEW_NAME posted to 942 * the same directory, and we only need/want one. 943 */ 944 if (node->n_dnode != NULL) { 945 smb_node_notify_change(node->n_dnode, 946 FILE_ACTION_MODIFIED, node->od_name); 947 } 948 break; 949 } 950 951 /* 952 * If we wanted to support recursive notify events 953 * (where a notify call on some directory receives 954 * events from all objects below that directory), 955 * we might deliver _SUBDIR_CHANGED to all our 956 * parents, grandparents etc, here. However, we 957 * don't currently subscribe to changes on all the 958 * child (and grandchild) objects that would be 959 * needed to make that work. It's prohibitively 960 * expensive to do that, and support for recursive 961 * notify is optional anyway, so don't bother. 962 */ 963 } 964 965 /* 966 * smb_node_start_crit() 967 * 968 * Enter critical region for share reservations. 969 * See comments above smb_fsop_shrlock(). 970 */ 971 void 972 smb_node_start_crit(smb_node_t *node, krw_t mode) 973 { 974 rw_enter(&node->n_lock, mode); 975 nbl_start_crit(node->vp, mode); 976 } 977 978 /* 979 * smb_node_end_crit() 980 * 981 * Exit critical region for share reservations. 982 */ 983 void 984 smb_node_end_crit(smb_node_t *node) 985 { 986 nbl_end_crit(node->vp); 987 rw_exit(&node->n_lock); 988 } 989 990 int 991 smb_node_in_crit(smb_node_t *node) 992 { 993 return (nbl_in_crit(node->vp) && RW_LOCK_HELD(&node->n_lock)); 994 } 995 996 void 997 smb_node_rdlock(smb_node_t *node) 998 { 999 rw_enter(&node->n_lock, RW_READER); 1000 } 1001 1002 void 1003 smb_node_wrlock(smb_node_t *node) 1004 { 1005 rw_enter(&node->n_lock, RW_WRITER); 1006 } 1007 1008 void 1009 smb_node_unlock(smb_node_t *node) 1010 { 1011 rw_exit(&node->n_lock); 1012 } 1013 1014 void 1015 smb_node_add_ofile(smb_node_t *node, smb_ofile_t *of) 1016 { 1017 SMB_NODE_VALID(node); 1018 1019 smb_llist_enter(&node->n_ofile_list, RW_WRITER); 1020 smb_llist_insert_tail(&node->n_ofile_list, of); 1021 smb_llist_exit(&node->n_ofile_list); 1022 } 1023 1024 void 1025 smb_node_rem_ofile(smb_node_t *node, smb_ofile_t *of) 1026 { 1027 SMB_NODE_VALID(node); 1028 1029 smb_llist_enter(&node->n_ofile_list, RW_WRITER); 1030 smb_llist_remove(&node->n_ofile_list, of); 1031 smb_llist_exit(&node->n_ofile_list); 1032 } 1033 1034 /* 1035 * smb_node_inc_open_ofiles 1036 */ 1037 void 1038 smb_node_inc_open_ofiles(smb_node_t *node) 1039 { 1040 SMB_NODE_VALID(node); 1041 atomic_inc_32(&node->n_open_count); 1042 } 1043 1044 /* 1045 * smb_node_dec_open_ofiles 1046 * returns new value 1047 */ 1048 uint32_t 1049 smb_node_dec_open_ofiles(smb_node_t *node) 1050 { 1051 SMB_NODE_VALID(node); 1052 return (atomic_dec_32_nv(&node->n_open_count)); 1053 } 1054 1055 /* 1056 * smb_node_inc_opening_count 1057 */ 1058 void 1059 smb_node_inc_opening_count(smb_node_t *node) 1060 { 1061 SMB_NODE_VALID(node); 1062 atomic_inc_32(&node->n_opening_count); 1063 } 1064 1065 /* 1066 * smb_node_dec_opening_count 1067 */ 1068 void 1069 smb_node_dec_opening_count(smb_node_t *node) 1070 { 1071 SMB_NODE_VALID(node); 1072 atomic_dec_32(&node->n_opening_count); 1073 } 1074 1075 /* 1076 * smb_node_getmntpath 1077 */ 1078 int 1079 smb_node_getmntpath(smb_node_t *node, char *buf, uint32_t buflen) 1080 { 1081 vnode_t *vp, *root_vp; 1082 vfs_t *vfsp; 1083 int err; 1084 1085 ASSERT(node); 1086 ASSERT(node->vp); 1087 ASSERT(node->vp->v_vfsp); 1088 1089 vp = node->vp; 1090 vfsp = vp->v_vfsp; 1091 1092 if (VFS_ROOT(vfsp, &root_vp)) 1093 return (ENOENT); 1094 1095 VN_HOLD(vp); 1096 1097 /* NULL is passed in as we want to start at "/" */ 1098 err = vnodetopath(NULL, root_vp, buf, buflen, zone_kcred()); 1099 1100 VN_RELE(vp); 1101 VN_RELE(root_vp); 1102 return (err); 1103 } 1104 1105 /* 1106 * smb_node_getshrpath 1107 * 1108 * Determine the absolute pathname of 'node' within the share (tree). 1109 * For example if the node represents file "test1.txt" in directory 1110 * "dir1" the pathname would be: \dir1\test1.txt 1111 */ 1112 int 1113 smb_node_getshrpath(smb_node_t *node, smb_tree_t *tree, 1114 char *buf, uint32_t buflen) 1115 { 1116 int rc; 1117 1118 ASSERT(node); 1119 ASSERT(tree); 1120 ASSERT(tree->t_snode); 1121 1122 rc = smb_node_getpath(node, tree->t_snode->vp, buf, buflen); 1123 (void) strsubst(buf, '/', '\\'); 1124 return (rc); 1125 } 1126 1127 /* 1128 * smb_node_getpath 1129 * 1130 * Determine the absolute pathname of 'node' from 'rootvp'. 1131 * 1132 * Using vnodetopath is only reliable for directory nodes (due to 1133 * its reliance on the DNLC for non-directory nodes). Thus, if node 1134 * represents a file, construct the pathname for the parent dnode 1135 * and append filename. 1136 * If node represents a named stream, construct the pathname for the 1137 * associated unnamed stream and append the stream name. 1138 * 1139 * The pathname returned in buf will be '/' separated. 1140 */ 1141 int 1142 smb_node_getpath(smb_node_t *node, vnode_t *rootvp, char *buf, uint32_t buflen) 1143 { 1144 int rc; 1145 vnode_t *vp; 1146 smb_node_t *unode, *dnode; 1147 cred_t *kcr = zone_kcred(); 1148 1149 unode = (SMB_IS_STREAM(node)) ? node->n_unode : node; 1150 dnode = (smb_node_is_dir(unode)) ? unode : unode->n_dnode; 1151 1152 /* find path to directory node */ 1153 vp = dnode->vp; 1154 VN_HOLD(vp); 1155 if (rootvp) { 1156 VN_HOLD(rootvp); 1157 rc = vnodetopath(rootvp, vp, buf, buflen, kcr); 1158 VN_RELE(rootvp); 1159 } else { 1160 rc = vnodetopath(NULL, vp, buf, buflen, kcr); 1161 } 1162 VN_RELE(vp); 1163 1164 if (rc != 0) 1165 return (rc); 1166 1167 /* append filename if necessary */ 1168 if (!smb_node_is_dir(unode)) { 1169 if (buf[strlen(buf) - 1] != '/') 1170 (void) strlcat(buf, "/", buflen); 1171 (void) strlcat(buf, unode->od_name, buflen); 1172 } 1173 1174 /* append named stream name if necessary */ 1175 if (SMB_IS_STREAM(node)) 1176 (void) strlcat(buf, node->od_name, buflen); 1177 1178 return (rc); 1179 } 1180 1181 /* 1182 * smb_node_alloc 1183 */ 1184 static smb_node_t * 1185 smb_node_alloc( 1186 char *od_name, 1187 vnode_t *vp, 1188 smb_llist_t *bucket, 1189 uint32_t hashkey) 1190 { 1191 smb_node_t *node; 1192 vnode_t *root_vp; 1193 1194 node = kmem_cache_alloc(smb_node_cache, KM_SLEEP); 1195 1196 if (node->n_audit_buf != NULL) 1197 node->n_audit_buf->anb_index = 0; 1198 1199 node->flags = 0; 1200 VN_HOLD(vp); 1201 node->vp = vp; 1202 node->n_refcnt = 1; 1203 node->n_hash_bucket = bucket; 1204 node->n_hashkey = hashkey; 1205 node->n_open_count = 0; 1206 node->n_allocsz = 0; 1207 node->n_dnode = NULL; 1208 node->n_unode = NULL; 1209 node->delete_on_close_cred = NULL; 1210 node->n_delete_on_close_flags = 0; 1211 node->n_oplock.ol_fem = B_FALSE; 1212 1213 (void) strlcpy(node->od_name, od_name, sizeof (node->od_name)); 1214 if (strcmp(od_name, XATTR_DIR) == 0) 1215 node->flags |= NODE_XATTR_DIR; 1216 1217 if (VFS_ROOT(vp->v_vfsp, &root_vp) == 0) { 1218 if (vp == root_vp) 1219 node->flags |= NODE_FLAGS_VFSROOT; 1220 VN_RELE(root_vp); 1221 } 1222 1223 node->n_state = SMB_NODE_STATE_AVAILABLE; 1224 node->n_magic = SMB_NODE_MAGIC; 1225 1226 return (node); 1227 } 1228 1229 /* 1230 * smb_node_free 1231 */ 1232 static void 1233 smb_node_free(smb_node_t *node) 1234 { 1235 SMB_NODE_VALID(node); 1236 1237 node->n_magic = 0; 1238 VERIFY(!list_link_active(&node->n_lnd)); 1239 VERIFY(node->n_lock_list.ll_count == 0); 1240 VERIFY(node->n_wlock_list.ll_count == 0); 1241 VERIFY(node->n_ofile_list.ll_count == 0); 1242 VERIFY(node->n_oplock.ol_fem == B_FALSE); 1243 VERIFY(MUTEX_NOT_HELD(&node->n_mutex)); 1244 VERIFY(!RW_LOCK_HELD(&node->n_lock)); 1245 VN_RELE(node->vp); 1246 kmem_cache_free(smb_node_cache, node); 1247 } 1248 1249 /* 1250 * smb_node_constructor 1251 */ 1252 static int 1253 smb_node_constructor(void *buf, void *un, int kmflags) 1254 { 1255 _NOTE(ARGUNUSED(kmflags, un)) 1256 1257 smb_node_t *node = (smb_node_t *)buf; 1258 1259 bzero(node, sizeof (smb_node_t)); 1260 1261 smb_llist_constructor(&node->n_ofile_list, sizeof (smb_ofile_t), 1262 offsetof(smb_ofile_t, f_node_lnd)); 1263 smb_llist_constructor(&node->n_lock_list, sizeof (smb_lock_t), 1264 offsetof(smb_lock_t, l_lnd)); 1265 smb_llist_constructor(&node->n_wlock_list, sizeof (smb_lock_t), 1266 offsetof(smb_lock_t, l_lnd)); 1267 mutex_init(&node->n_oplock.ol_mutex, NULL, MUTEX_DEFAULT, NULL); 1268 cv_init(&node->n_oplock.WaitingOpenCV, NULL, CV_DEFAULT, NULL); 1269 rw_init(&node->n_lock, NULL, RW_DEFAULT, NULL); 1270 mutex_init(&node->n_mutex, NULL, MUTEX_DEFAULT, NULL); 1271 smb_node_create_audit_buf(node, kmflags); 1272 return (0); 1273 } 1274 1275 /* 1276 * smb_node_destructor 1277 */ 1278 static void 1279 smb_node_destructor(void *buf, void *un) 1280 { 1281 _NOTE(ARGUNUSED(un)) 1282 1283 smb_node_t *node = (smb_node_t *)buf; 1284 1285 smb_node_destroy_audit_buf(node); 1286 mutex_destroy(&node->n_mutex); 1287 rw_destroy(&node->n_lock); 1288 cv_destroy(&node->n_oplock.WaitingOpenCV); 1289 mutex_destroy(&node->n_oplock.ol_mutex); 1290 smb_llist_destructor(&node->n_lock_list); 1291 smb_llist_destructor(&node->n_wlock_list); 1292 smb_llist_destructor(&node->n_ofile_list); 1293 } 1294 1295 /* 1296 * smb_node_create_audit_buf 1297 */ 1298 static void 1299 smb_node_create_audit_buf(smb_node_t *node, int kmflags) 1300 { 1301 smb_audit_buf_node_t *abn; 1302 1303 if (smb_audit_flags & SMB_AUDIT_NODE) { 1304 abn = kmem_zalloc(sizeof (smb_audit_buf_node_t), kmflags); 1305 abn->anb_max_index = SMB_AUDIT_BUF_MAX_REC - 1; 1306 node->n_audit_buf = abn; 1307 } 1308 } 1309 1310 /* 1311 * smb_node_destroy_audit_buf 1312 */ 1313 static void 1314 smb_node_destroy_audit_buf(smb_node_t *node) 1315 { 1316 if (node->n_audit_buf != NULL) { 1317 kmem_free(node->n_audit_buf, sizeof (smb_audit_buf_node_t)); 1318 node->n_audit_buf = NULL; 1319 } 1320 } 1321 1322 /* 1323 * smb_node_audit 1324 * 1325 * This function saves the calling stack in the audit buffer of the node passed 1326 * in. 1327 */ 1328 static void 1329 smb_node_audit(smb_node_t *node) 1330 { 1331 #ifdef _KERNEL 1332 smb_audit_buf_node_t *abn; 1333 smb_audit_record_node_t *anr; 1334 1335 if (node->n_audit_buf) { 1336 abn = node->n_audit_buf; 1337 anr = abn->anb_records; 1338 anr += abn->anb_index; 1339 abn->anb_index++; 1340 abn->anb_index &= abn->anb_max_index; 1341 anr->anr_refcnt = node->n_refcnt; 1342 anr->anr_depth = getpcstack(anr->anr_stack, 1343 SMB_AUDIT_STACK_DEPTH); 1344 } 1345 #else /* _KERNEL */ 1346 _NOTE(ARGUNUSED(node)) 1347 #endif /* _KERNEL */ 1348 } 1349 1350 static smb_llist_t * 1351 smb_node_get_hash(fsid_t *fsid, smb_attr_t *attr, uint32_t *phashkey) 1352 { 1353 uint32_t hashkey; 1354 1355 hashkey = fsid->val[0] + attr->sa_vattr.va_nodeid; 1356 hashkey += (hashkey >> 24) + (hashkey >> 16) + (hashkey >> 8); 1357 *phashkey = hashkey; 1358 return (&smb_node_hash_table[(hashkey & SMBND_HASH_MASK)]); 1359 } 1360 1361 boolean_t 1362 smb_node_is_file(smb_node_t *node) 1363 { 1364 SMB_NODE_VALID(node); 1365 return (node->vp->v_type == VREG); 1366 } 1367 1368 boolean_t 1369 smb_node_is_dir(smb_node_t *node) 1370 { 1371 SMB_NODE_VALID(node); 1372 return ((node->vp->v_type == VDIR) || 1373 (node->flags & NODE_FLAGS_DFSLINK)); 1374 } 1375 1376 boolean_t 1377 smb_node_is_symlink(smb_node_t *node) 1378 { 1379 SMB_NODE_VALID(node); 1380 return ((node->vp->v_type == VLNK) && 1381 ((node->flags & NODE_FLAGS_REPARSE) == 0)); 1382 } 1383 1384 boolean_t 1385 smb_node_is_dfslink(smb_node_t *node) 1386 { 1387 SMB_NODE_VALID(node); 1388 return ((node->vp->v_type == VLNK) && 1389 (node->flags & NODE_FLAGS_DFSLINK)); 1390 } 1391 1392 boolean_t 1393 smb_node_is_reparse(smb_node_t *node) 1394 { 1395 SMB_NODE_VALID(node); 1396 return ((node->vp->v_type == VLNK) && 1397 (node->flags & NODE_FLAGS_REPARSE)); 1398 } 1399 1400 boolean_t 1401 smb_node_is_vfsroot(smb_node_t *node) 1402 { 1403 SMB_NODE_VALID(node); 1404 return ((node->flags & NODE_FLAGS_VFSROOT) == NODE_FLAGS_VFSROOT); 1405 } 1406 1407 boolean_t 1408 smb_node_is_system(smb_node_t *node) 1409 { 1410 SMB_NODE_VALID(node); 1411 return ((node->flags & NODE_FLAGS_SYSTEM) == NODE_FLAGS_SYSTEM); 1412 } 1413 1414 /* 1415 * smb_node_file_is_readonly 1416 * 1417 * Checks if the file (which node represents) is marked readonly 1418 * in the filesystem. Note that there may be handles open with 1419 * modify rights, and those continue to allow access even after 1420 * the DOS read-only flag has been set in the file system. 1421 */ 1422 boolean_t 1423 smb_node_file_is_readonly(smb_node_t *node) 1424 { 1425 smb_attr_t attr; 1426 1427 if (node == NULL) 1428 return (B_FALSE); /* pipes */ 1429 1430 bzero(&attr, sizeof (smb_attr_t)); 1431 attr.sa_mask = SMB_AT_DOSATTR; 1432 (void) smb_fsop_getattr(NULL, zone_kcred(), node, &attr); 1433 return ((attr.sa_dosattr & FILE_ATTRIBUTE_READONLY) != 0); 1434 } 1435 1436 /* 1437 * smb_node_setattr 1438 * 1439 * The sr may be NULL, for example when closing an ofile. 1440 * The ofile may be NULL, for example when a client request 1441 * specifies the file by pathname. 1442 * 1443 * Returns: errno 1444 * 1445 * Timestamps 1446 * 1447 * Windows and Unix have different models for timestamp updates. 1448 * [MS-FSA 2.1.5.14 Server Requests Setting of File Information] 1449 * 1450 * An open "handle" in Windows can control whether and when 1451 * any timestamp updates happen for that handle. For example, 1452 * timestamps set via some handle are no longer updated by I/O 1453 * operations on that handle. In Unix we don't really have any 1454 * way to avoid the timestamp updates that the file system does. 1455 * Therefore, we need to make some compromises, and simulate the 1456 * more important parts of the Windows file system semantics. 1457 * 1458 * For example, when an SMB client sets file times, set those 1459 * times in the file system (so the change will be visible to 1460 * other clients, at least until they change again) but we also 1461 * make those times "sticky" in our open handle, and reapply 1462 * those times when the handle is closed. That reapply on close 1463 * simulates the Windows behavior where the timestamp updates 1464 * would be discontinued after they were set. These "sticky" 1465 * attributes are returned in any query on the handle where 1466 * they are stored. 1467 * 1468 * Other than the above, the file system layer takes care of the 1469 * normal time stamp updates, such as updating the mtime after a 1470 * write, and ctime after an attribute change. 1471 * 1472 * Dos Attributes are stored persistently, but with a twist: 1473 * In Windows, when you set the "read-only" bit on some file, 1474 * existing writable handles to that file continue to have 1475 * write access. (because access check happens at open) 1476 * If we were to set the read-only bit directly, we would 1477 * cause errors in subsequent writes on any of our open 1478 * (and writable) file handles. So here too, we have to 1479 * simulate the Windows behavior. We keep the read-only 1480 * bit "pending" in the smb_node (so it will be visible in 1481 * any new opens of the file) and apply it on close. 1482 * 1483 * File allocation size is also simulated, and not persistent. 1484 * When the file allocation size is set it is first rounded up 1485 * to block size. If the file size is smaller than the allocation 1486 * size the file is truncated by setting the filesize to allocsz. 1487 */ 1488 int 1489 smb_node_setattr(smb_request_t *sr, smb_node_t *node, 1490 cred_t *cr, smb_ofile_t *of, smb_attr_t *attr) 1491 { 1492 int rc; 1493 uint_t times_mask; 1494 smb_attr_t tmp_attr; 1495 smb_node_t *unnamed_node; 1496 1497 SMB_NODE_VALID(node); 1498 1499 /* set attributes specified in attr */ 1500 if (attr->sa_mask == 0) 1501 return (0); /* nothing to do (caller bug?) */ 1502 1503 /* 1504 * Allocation size and EOF position interact. 1505 * We don't persistently store the allocation size 1506 * but make it look like we do while there are opens. 1507 * Note: We update the caller's attr in the cases 1508 * where they're setting only one of allocsz|size. 1509 */ 1510 switch (attr->sa_mask & (SMB_AT_ALLOCSZ | SMB_AT_SIZE)) { 1511 1512 case SMB_AT_ALLOCSZ: 1513 /* 1514 * Setting the allocation size but not EOF position. 1515 * Get the current EOF in tmp_attr and (if necessary) 1516 * truncate to the (rounded up) allocation size. 1517 * Using kcred here because if we don't have access, 1518 * we want to fail at setattr below and not here. 1519 */ 1520 bzero(&tmp_attr, sizeof (smb_attr_t)); 1521 tmp_attr.sa_mask = SMB_AT_SIZE; 1522 rc = smb_fsop_getattr(NULL, zone_kcred(), node, &tmp_attr); 1523 if (rc != 0) 1524 return (rc); 1525 attr->sa_allocsz = SMB_ALLOCSZ(attr->sa_allocsz); 1526 if (tmp_attr.sa_vattr.va_size > attr->sa_allocsz) { 1527 /* truncate the file to allocsz */ 1528 attr->sa_vattr.va_size = attr->sa_allocsz; 1529 attr->sa_mask |= SMB_AT_SIZE; 1530 } 1531 break; 1532 1533 case SMB_AT_SIZE: 1534 /* 1535 * Setting the EOF position but not allocation size. 1536 * If the new EOF position would be greater than 1537 * the allocation size, increase the latter. 1538 */ 1539 if (node->n_allocsz < attr->sa_vattr.va_size) { 1540 attr->sa_mask |= SMB_AT_ALLOCSZ; 1541 attr->sa_allocsz = 1542 SMB_ALLOCSZ(attr->sa_vattr.va_size); 1543 } 1544 break; 1545 1546 case SMB_AT_ALLOCSZ | SMB_AT_SIZE: 1547 /* 1548 * Setting both. Increase alloc size if needed. 1549 */ 1550 if (attr->sa_allocsz < attr->sa_vattr.va_size) 1551 attr->sa_allocsz = 1552 SMB_ALLOCSZ(attr->sa_vattr.va_size); 1553 break; 1554 1555 default: 1556 break; 1557 } 1558 1559 /* 1560 * When operating on an open file, some settable attributes 1561 * become "sticky" in the open file object until close. 1562 * (see above re. timestamps) 1563 */ 1564 times_mask = attr->sa_mask & SMB_AT_TIMES; 1565 if (of != NULL && times_mask != 0) { 1566 smb_attr_t *pa; 1567 1568 SMB_OFILE_VALID(of); 1569 mutex_enter(&of->f_mutex); 1570 pa = &of->f_pending_attr; 1571 1572 pa->sa_mask |= times_mask; 1573 1574 if (times_mask & SMB_AT_ATIME) 1575 pa->sa_vattr.va_atime = 1576 attr->sa_vattr.va_atime; 1577 if (times_mask & SMB_AT_MTIME) 1578 pa->sa_vattr.va_mtime = 1579 attr->sa_vattr.va_mtime; 1580 if (times_mask & SMB_AT_CTIME) 1581 pa->sa_vattr.va_ctime = 1582 attr->sa_vattr.va_ctime; 1583 if (times_mask & SMB_AT_CRTIME) 1584 pa->sa_crtime = 1585 attr->sa_crtime; 1586 1587 mutex_exit(&of->f_mutex); 1588 1589 /* 1590 * The f_pending_attr times are reapplied in 1591 * smb_ofile_close(). 1592 */ 1593 1594 /* 1595 * If this change is coming directly from a client 1596 * (sr != NULL) and it's a persistent handle, save 1597 * the "sticky times" in the handle. 1598 */ 1599 if (sr != NULL && of->dh_persist) { 1600 smb2_dh_update_times(sr, of, attr); 1601 } 1602 } 1603 1604 if ((attr->sa_mask & SMB_AT_ALLOCSZ) != 0) { 1605 mutex_enter(&node->n_mutex); 1606 /* 1607 * Simulate n_allocsz persistence only while 1608 * there are opens. See smb_node_getattr 1609 */ 1610 if (node->n_open_count != 0) 1611 node->n_allocsz = attr->sa_allocsz; 1612 mutex_exit(&node->n_mutex); 1613 } 1614 1615 rc = smb_fsop_setattr(sr, cr, node, attr); 1616 if (rc != 0) 1617 return (rc); 1618 1619 if (node->n_dnode != NULL) { 1620 smb_node_notify_change(node->n_dnode, 1621 FILE_ACTION_MODIFIED, node->od_name); 1622 } 1623 1624 if ((unnamed_node = SMB_IS_STREAM(node)) != NULL) { 1625 ASSERT(unnamed_node->n_magic == SMB_NODE_MAGIC); 1626 ASSERT(unnamed_node->n_state != SMB_NODE_STATE_DESTROYING); 1627 smb_node_notify_change(node->n_dnode, 1628 FILE_ACTION_MODIFIED_STREAM, node->od_name); 1629 } 1630 1631 return (0); 1632 } 1633 1634 /* 1635 * smb_node_getattr 1636 * 1637 * Get attributes from the file system and apply any smb-specific 1638 * overrides for size, dos attributes and timestamps 1639 * 1640 * When node->n_pending_readonly is set on a node, pretend that 1641 * we've already set this node readonly at the filesystem level. 1642 * We can't actually do that until all writable handles are closed 1643 * or those writable handles would suddenly loose their access. 1644 * 1645 * Returns: errno 1646 */ 1647 int 1648 smb_node_getattr(smb_request_t *sr, smb_node_t *node, cred_t *cr, 1649 smb_ofile_t *of, smb_attr_t *attr) 1650 { 1651 int rc; 1652 uint_t want_mask, pend_mask; 1653 boolean_t isdir; 1654 1655 SMB_NODE_VALID(node); 1656 1657 /* Deal with some interdependencies */ 1658 if (attr->sa_mask & SMB_AT_ALLOCSZ) 1659 attr->sa_mask |= SMB_AT_SIZE; 1660 if (attr->sa_mask & SMB_AT_DOSATTR) 1661 attr->sa_mask |= SMB_AT_TYPE; 1662 1663 rc = smb_fsop_getattr(sr, cr, node, attr); 1664 if (rc != 0) 1665 return (rc); 1666 1667 isdir = smb_node_is_dir(node); 1668 1669 mutex_enter(&node->n_mutex); 1670 1671 if (attr->sa_mask & SMB_AT_DOSATTR) { 1672 if (attr->sa_dosattr == 0) { 1673 attr->sa_dosattr = (isdir) ? 1674 FILE_ATTRIBUTE_DIRECTORY: 1675 FILE_ATTRIBUTE_NORMAL; 1676 } 1677 } 1678 1679 /* 1680 * Also fix-up sa_allocsz, which is not persistent. 1681 * When there are no open files, allocsz is faked. 1682 * While there are open files, we pretend we have a 1683 * persistent allocation size in n_allocsz, and 1684 * keep that up-to-date here, increasing it when 1685 * we see the file size grow past it. 1686 */ 1687 if (attr->sa_mask & SMB_AT_ALLOCSZ) { 1688 if (isdir) { 1689 attr->sa_allocsz = 0; 1690 } else if (node->n_open_count == 0) { 1691 attr->sa_allocsz = 1692 SMB_ALLOCSZ(attr->sa_vattr.va_size); 1693 } else { 1694 if (node->n_allocsz < attr->sa_vattr.va_size) 1695 node->n_allocsz = 1696 SMB_ALLOCSZ(attr->sa_vattr.va_size); 1697 attr->sa_allocsz = node->n_allocsz; 1698 } 1699 } 1700 1701 mutex_exit(&node->n_mutex); 1702 1703 if (isdir) { 1704 attr->sa_vattr.va_size = 0; 1705 attr->sa_vattr.va_nlink = 1; 1706 } 1707 1708 /* 1709 * getattr with an ofile gets any "pending" times that 1710 * might have been previously set via this ofile. 1711 * This is what makes these times "sticky". 1712 */ 1713 want_mask = attr->sa_mask & SMB_AT_TIMES; 1714 if (of != NULL && want_mask != 0) { 1715 smb_attr_t *pa; 1716 1717 SMB_OFILE_VALID(of); 1718 mutex_enter(&of->f_mutex); 1719 pa = &of->f_pending_attr; 1720 1721 pend_mask = pa->sa_mask; 1722 1723 if (want_mask & pend_mask & SMB_AT_ATIME) 1724 attr->sa_vattr.va_atime = 1725 pa->sa_vattr.va_atime; 1726 if (want_mask & pend_mask & SMB_AT_MTIME) 1727 attr->sa_vattr.va_mtime = 1728 pa->sa_vattr.va_mtime; 1729 if (want_mask & pend_mask & SMB_AT_CTIME) 1730 attr->sa_vattr.va_ctime = 1731 pa->sa_vattr.va_ctime; 1732 if (want_mask & pend_mask & SMB_AT_CRTIME) 1733 attr->sa_crtime = 1734 pa->sa_crtime; 1735 1736 mutex_exit(&of->f_mutex); 1737 } 1738 1739 1740 return (0); 1741 } 1742 1743 1744 #ifndef _KERNEL 1745 extern int reparse_vnode_parse(vnode_t *vp, nvlist_t *nvl); 1746 #endif /* _KERNEL */ 1747 1748 /* 1749 * Check to see if the node represents a reparse point. 1750 * If yes, whether the reparse point contains a DFS link. 1751 */ 1752 static void 1753 smb_node_init_reparse(smb_node_t *node, smb_attr_t *attr) 1754 { 1755 nvlist_t *nvl; 1756 nvpair_t *rec; 1757 char *rec_type; 1758 1759 if ((attr->sa_dosattr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) 1760 return; 1761 1762 if ((nvl = reparse_init()) == NULL) 1763 return; 1764 1765 if (reparse_vnode_parse(node->vp, nvl) != 0) { 1766 reparse_free(nvl); 1767 return; 1768 } 1769 1770 node->flags |= NODE_FLAGS_REPARSE; 1771 1772 rec = nvlist_next_nvpair(nvl, NULL); 1773 while (rec != NULL) { 1774 rec_type = nvpair_name(rec); 1775 if ((rec_type != NULL) && 1776 (strcasecmp(rec_type, DFS_REPARSE_SVCTYPE) == 0)) { 1777 node->flags |= NODE_FLAGS_DFSLINK; 1778 break; 1779 } 1780 rec = nvlist_next_nvpair(nvl, rec); 1781 } 1782 1783 reparse_free(nvl); 1784 } 1785 1786 /* 1787 * smb_node_init_system 1788 * 1789 * If the node represents a special system file set NODE_FLAG_SYSTEM. 1790 * System files: 1791 * - any node whose parent dnode has NODE_FLAG_SYSTEM set 1792 * - any node whose associated unnamed stream node (unode) has 1793 * NODE_FLAG_SYSTEM set 1794 * - .$EXTEND at root of share (quota management) 1795 */ 1796 static void 1797 smb_node_init_system(smb_node_t *node) 1798 { 1799 smb_node_t *dnode = node->n_dnode; 1800 smb_node_t *unode = node->n_unode; 1801 1802 if ((dnode) && (dnode->flags & NODE_FLAGS_SYSTEM)) { 1803 node->flags |= NODE_FLAGS_SYSTEM; 1804 return; 1805 } 1806 1807 if ((unode) && (unode->flags & NODE_FLAGS_SYSTEM)) { 1808 node->flags |= NODE_FLAGS_SYSTEM; 1809 return; 1810 } 1811 1812 if ((dnode) && (smb_node_is_vfsroot(node->n_dnode) && 1813 (strcasecmp(node->od_name, ".$EXTEND") == 0))) { 1814 node->flags |= NODE_FLAGS_SYSTEM; 1815 } 1816 } 1817