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