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 mutex_exit(&node->n_mutex); 482 483 smb_llist_enter(node->n_hash_bucket, RW_WRITER); 484 smb_llist_remove(node->n_hash_bucket, node); 485 smb_llist_exit(node->n_hash_bucket); 486 487 /* 488 * Check if the file was deleted 489 */ 490 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) { 491 smb_node_delete_on_close(node); 492 } 493 494 if (node->n_dnode) { 495 ASSERT(node->n_dnode->n_magic == 496 SMB_NODE_MAGIC); 497 smb_node_release(node->n_dnode); 498 } 499 500 if (node->n_unode) { 501 ASSERT(node->n_unode->n_magic == 502 SMB_NODE_MAGIC); 503 smb_node_release(node->n_unode); 504 } 505 506 smb_node_free(node); 507 return; 508 509 default: 510 SMB_PANIC(); 511 } 512 } 513 smb_node_audit(node); 514 mutex_exit(&node->n_mutex); 515 } 516 517 void 518 smb_node_delete_on_close(smb_node_t *node) 519 { 520 smb_node_t *d_snode; 521 int rc = 0; 522 uint32_t flags = 0; 523 524 d_snode = node->n_dnode; 525 526 ASSERT((node->flags & NODE_FLAGS_DELETE_ON_CLOSE) != 0); 527 528 node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE; 529 node->flags |= NODE_FLAGS_DELETE_COMMITTED; 530 flags = node->n_delete_on_close_flags; 531 ASSERT(node->od_name != NULL); 532 533 if (smb_node_is_dir(node)) 534 rc = smb_fsop_rmdir(0, node->delete_on_close_cred, 535 d_snode, node->od_name, flags); 536 else 537 rc = smb_fsop_remove(0, node->delete_on_close_cred, 538 d_snode, node->od_name, flags); 539 crfree(node->delete_on_close_cred); 540 node->delete_on_close_cred = NULL; 541 542 if (rc != 0) 543 cmn_err(CE_WARN, "File %s could not be removed, rc=%d\n", 544 node->od_name, rc); 545 DTRACE_PROBE2(smb_node_delete_on_close, int, rc, smb_node_t *, node); 546 } 547 548 /* 549 * smb_node_rename() 550 * 551 */ 552 void 553 smb_node_rename( 554 smb_node_t *from_dnode, 555 smb_node_t *ret_node, 556 smb_node_t *to_dnode, 557 char *to_name) 558 { 559 SMB_NODE_VALID(from_dnode); 560 SMB_NODE_VALID(to_dnode); 561 SMB_NODE_VALID(ret_node); 562 563 smb_node_ref(to_dnode); 564 mutex_enter(&ret_node->n_mutex); 565 switch (ret_node->n_state) { 566 case SMB_NODE_STATE_AVAILABLE: 567 ret_node->n_dnode = to_dnode; 568 mutex_exit(&ret_node->n_mutex); 569 ASSERT(to_dnode->n_dnode != ret_node); 570 ASSERT((to_dnode->vp->v_xattrdir) || 571 (to_dnode->vp->v_type == VDIR)); 572 smb_node_release(from_dnode); 573 (void) strcpy(ret_node->od_name, to_name); 574 /* 575 * XXX Need to update attributes? 576 */ 577 break; 578 default: 579 SMB_PANIC(); 580 } 581 } 582 583 /* 584 * Find/create an SMB node for the root of this zone and store it 585 * in *svrootp. Also create nodes leading to this directory. 586 */ 587 int 588 smb_node_root_init(smb_server_t *sv, smb_node_t **svrootp) 589 { 590 zone_t *zone = curzone; 591 int error; 592 593 ASSERT(zone->zone_id == sv->sv_zid); 594 if (smb_root_node == NULL) 595 return (ENOENT); 596 597 /* 598 * We're getting smb nodes below the zone root here, 599 * so need to use kcred, not zone_kcred(). 600 */ 601 error = smb_pathname(NULL, zone->zone_rootpath, 0, 602 smb_root_node, smb_root_node, NULL, svrootp, kcred, NULL); 603 604 return (error); 605 } 606 607 /* 608 * Helper function for smb_node_set_delete_on_close(). Assumes node is a dir. 609 * Return 0 if this is an empty dir. Otherwise return a NT_STATUS code. 610 * Unfortunately, to find out if a directory is empty, we have to read it 611 * and check for anything other than "." or ".." in the readdir buf. 612 */ 613 static uint32_t 614 smb_rmdir_possible(smb_node_t *n) 615 { 616 ASSERT(n->vp->v_type == VDIR); 617 char *buf; 618 char *bufptr; 619 struct dirent64 *dp; 620 uint32_t status = NT_STATUS_SUCCESS; 621 int bsize = SMB_ODIR_BUFSIZE; 622 int eof = 0; 623 624 buf = kmem_alloc(SMB_ODIR_BUFSIZE, KM_SLEEP); 625 626 /* Flags zero: no edirent, no ABE wanted here */ 627 if (smb_vop_readdir(n->vp, 0, buf, &bsize, &eof, 0, zone_kcred())) { 628 status = NT_STATUS_INTERNAL_ERROR; 629 goto out; 630 } 631 632 bufptr = buf; 633 while (bsize > 0) { 634 /* LINTED pointer alignment */ 635 dp = (struct dirent64 *)bufptr; 636 637 bufptr += dp->d_reclen; 638 bsize -= dp->d_reclen; 639 if (bsize < 0) { 640 /* partial record */ 641 status = NT_STATUS_DIRECTORY_NOT_EMPTY; 642 break; 643 } 644 645 if (strcmp(dp->d_name, ".") != 0 && 646 strcmp(dp->d_name, "..") != 0) { 647 status = NT_STATUS_DIRECTORY_NOT_EMPTY; 648 break; 649 } 650 } 651 652 out: 653 kmem_free(buf, SMB_ODIR_BUFSIZE); 654 return (status); 655 } 656 657 /* 658 * When DeleteOnClose is set on an smb_node, the common open code will 659 * reject subsequent open requests for the file. Observation of Windows 660 * 2000 indicates that subsequent opens should be allowed (assuming 661 * there would be no sharing violation) until the file is closed using 662 * the fid on which the DeleteOnClose was requested. 663 * 664 * If there are multiple opens with delete-on-close create options, 665 * whichever the first file handle is closed will trigger the node to be 666 * marked as delete-on-close. The credentials of that ofile will be used 667 * as the delete-on-close credentials of the node. 668 * 669 * Note that "read-only" tests have already happened before this call. 670 */ 671 uint32_t 672 smb_node_set_delete_on_close(smb_node_t *node, cred_t *cr, uint32_t flags) 673 { 674 uint32_t status; 675 676 /* 677 * If the directory is not empty we should fail setting del-on-close 678 * with STATUS_DIRECTORY_NOT_EMPTY. see MS's 679 * "File System Behavior Overview" doc section 4.3.2 680 */ 681 if (smb_node_is_dir(node)) { 682 status = smb_rmdir_possible(node); 683 if (status != 0) { 684 return (status); 685 } 686 } 687 688 /* Dataset roots can't be deleted, so don't set DOC */ 689 if ((node->flags & NODE_FLAGS_VFSROOT) != 0) { 690 return (NT_STATUS_CANNOT_DELETE); 691 } 692 693 mutex_enter(&node->n_mutex); 694 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) { 695 /* It was already marked. We're done. */ 696 mutex_exit(&node->n_mutex); 697 return (NT_STATUS_SUCCESS); 698 } 699 700 crhold(cr); 701 node->delete_on_close_cred = cr; 702 node->n_delete_on_close_flags = flags; 703 node->flags |= NODE_FLAGS_DELETE_ON_CLOSE; 704 mutex_exit(&node->n_mutex); 705 706 /* 707 * Tell any change notify calls to close their handles 708 * and get out of the way. FILE_ACTION_DELETE_PENDING 709 * is a special, internal-only action for this purpose. 710 */ 711 smb_node_notify_change(node, FILE_ACTION_DELETE_PENDING, NULL); 712 713 return (NT_STATUS_SUCCESS); 714 } 715 716 void 717 smb_node_reset_delete_on_close(smb_node_t *node) 718 { 719 mutex_enter(&node->n_mutex); 720 if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) { 721 node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE; 722 crfree(node->delete_on_close_cred); 723 node->delete_on_close_cred = NULL; 724 node->n_delete_on_close_flags = 0; 725 } 726 mutex_exit(&node->n_mutex); 727 } 728 729 /* 730 * smb_node_open_check 731 * 732 * check file sharing rules for current open request 733 * against all existing opens for a file. 734 * 735 * Returns NT_STATUS_SHARING_VIOLATION if there is any 736 * sharing conflict, otherwise returns NT_STATUS_SUCCESS. 737 */ 738 uint32_t 739 smb_node_open_check(smb_node_t *node, uint32_t desired_access, 740 uint32_t share_access) 741 { 742 smb_ofile_t *of; 743 uint32_t status; 744 745 SMB_NODE_VALID(node); 746 747 smb_llist_enter(&node->n_ofile_list, RW_READER); 748 of = smb_llist_head(&node->n_ofile_list); 749 while (of) { 750 status = smb_ofile_open_check(of, desired_access, share_access); 751 752 switch (status) { 753 case NT_STATUS_INVALID_HANDLE: 754 case NT_STATUS_SUCCESS: 755 of = smb_llist_next(&node->n_ofile_list, of); 756 break; 757 default: 758 ASSERT(status == NT_STATUS_SHARING_VIOLATION); 759 DTRACE_PROBE3(conflict3, 760 smb_ofile_t, of, 761 uint32_t, desired_access, 762 uint32_t, share_access); 763 smb_llist_exit(&node->n_ofile_list); 764 return (status); 765 } 766 } 767 768 smb_llist_exit(&node->n_ofile_list); 769 return (NT_STATUS_SUCCESS); 770 } 771 772 uint32_t 773 smb_node_rename_check(smb_node_t *node) 774 { 775 smb_ofile_t *of; 776 uint32_t status; 777 778 SMB_NODE_VALID(node); 779 780 /* 781 * Intra-CIFS check 782 */ 783 smb_llist_enter(&node->n_ofile_list, RW_READER); 784 of = smb_llist_head(&node->n_ofile_list); 785 while (of) { 786 status = smb_ofile_rename_check(of); 787 788 switch (status) { 789 case NT_STATUS_INVALID_HANDLE: 790 case NT_STATUS_SUCCESS: 791 of = smb_llist_next(&node->n_ofile_list, of); 792 break; 793 default: 794 ASSERT(status == NT_STATUS_SHARING_VIOLATION); 795 DTRACE_PROBE1(conflict1, smb_ofile_t, of); 796 smb_llist_exit(&node->n_ofile_list); 797 return (status); 798 } 799 } 800 smb_llist_exit(&node->n_ofile_list); 801 return (NT_STATUS_SUCCESS); 802 } 803 804 uint32_t 805 smb_node_delete_check(smb_node_t *node) 806 { 807 smb_ofile_t *of; 808 uint32_t status; 809 810 SMB_NODE_VALID(node); 811 812 if (smb_node_is_dir(node)) 813 return (NT_STATUS_SUCCESS); 814 815 if (smb_node_is_reparse(node)) 816 return (NT_STATUS_ACCESS_DENIED); 817 818 /* 819 * intra-CIFS check 820 */ 821 smb_llist_enter(&node->n_ofile_list, RW_READER); 822 of = smb_llist_head(&node->n_ofile_list); 823 while (of) { 824 status = smb_ofile_delete_check(of); 825 826 switch (status) { 827 case NT_STATUS_INVALID_HANDLE: 828 case NT_STATUS_SUCCESS: 829 of = smb_llist_next(&node->n_ofile_list, of); 830 break; 831 default: 832 ASSERT(status == NT_STATUS_SHARING_VIOLATION); 833 DTRACE_PROBE1(conflict1, smb_ofile_t, of); 834 smb_llist_exit(&node->n_ofile_list); 835 return (status); 836 } 837 } 838 smb_llist_exit(&node->n_ofile_list); 839 return (NT_STATUS_SUCCESS); 840 } 841 842 /* 843 * smb_node_share_check 844 * 845 * Returns: TRUE - ofiles have non-zero share access 846 * B_FALSE - ofile with share access NONE. 847 */ 848 boolean_t 849 smb_node_share_check(smb_node_t *node) 850 { 851 smb_ofile_t *of; 852 boolean_t status = B_TRUE; 853 854 SMB_NODE_VALID(node); 855 856 smb_llist_enter(&node->n_ofile_list, RW_READER); 857 of = smb_llist_head(&node->n_ofile_list); 858 if (of) 859 status = smb_ofile_share_check(of); 860 smb_llist_exit(&node->n_ofile_list); 861 862 return (status); 863 } 864 865 /* 866 * SMB Change Notification 867 */ 868 869 void 870 smb_node_fcn_subscribe(smb_node_t *node) 871 { 872 873 mutex_enter(&node->n_mutex); 874 if (node->n_fcn_count == 0) 875 (void) smb_fem_fcn_install(node); 876 node->n_fcn_count++; 877 mutex_exit(&node->n_mutex); 878 } 879 880 void 881 smb_node_fcn_unsubscribe(smb_node_t *node) 882 { 883 884 mutex_enter(&node->n_mutex); 885 node->n_fcn_count--; 886 if (node->n_fcn_count == 0) 887 smb_fem_fcn_uninstall(node); 888 mutex_exit(&node->n_mutex); 889 } 890 891 void 892 smb_node_notify_change(smb_node_t *node, uint_t action, const char *name) 893 { 894 smb_ofile_t *of; 895 896 SMB_NODE_VALID(node); 897 898 smb_llist_enter(&node->n_ofile_list, RW_READER); 899 of = smb_llist_head(&node->n_ofile_list); 900 while (of) { 901 /* 902 * We'd rather deliver events only to ofiles that have 903 * subscribed. There's no explicit synchronization with 904 * where this flag is set, but other actions cause this 905 * value to reach visibility soon enough for events to 906 * start arriving by the time we need them to start. 907 * Once nc_subscribed is set, it stays set for the 908 * life of the ofile. 909 */ 910 if (of->f_notify.nc_subscribed) 911 smb_notify_ofile(of, action, name); 912 of = smb_llist_next(&node->n_ofile_list, of); 913 } 914 smb_llist_exit(&node->n_ofile_list); 915 916 /* 917 * After changes that add or remove a name, 918 * we know the directory attributes changed, 919 * and we can tell the immediate parent. 920 */ 921 switch (action) { 922 case FILE_ACTION_ADDED: 923 case FILE_ACTION_REMOVED: 924 case FILE_ACTION_RENAMED_NEW_NAME: 925 /* 926 * Note: FILE_ACTION_RENAMED_OLD_NAME is intentionally 927 * omitted, because it's always followed by another 928 * event with FILE_ACTION_RENAMED_NEW_NAME posted to 929 * the same directory, and we only need/want one. 930 */ 931 if (node->n_dnode != NULL) { 932 smb_node_notify_change(node->n_dnode, 933 FILE_ACTION_MODIFIED, node->od_name); 934 } 935 break; 936 } 937 938 /* 939 * If we wanted to support recursive notify events 940 * (where a notify call on some directory receives 941 * events from all objects below that directory), 942 * we might deliver _SUBDIR_CHANGED to all our 943 * parents, grandparents etc, here. However, we 944 * don't currently subscribe to changes on all the 945 * child (and grandchild) objects that would be 946 * needed to make that work. It's prohibitively 947 * expensive to do that, and support for recursive 948 * notify is optional anyway, so don't bother. 949 */ 950 } 951 952 /* 953 * smb_node_start_crit() 954 * 955 * Enter critical region for share reservations. 956 * See comments above smb_fsop_shrlock(). 957 */ 958 void 959 smb_node_start_crit(smb_node_t *node, krw_t mode) 960 { 961 rw_enter(&node->n_lock, mode); 962 nbl_start_crit(node->vp, mode); 963 } 964 965 /* 966 * smb_node_end_crit() 967 * 968 * Exit critical region for share reservations. 969 */ 970 void 971 smb_node_end_crit(smb_node_t *node) 972 { 973 nbl_end_crit(node->vp); 974 rw_exit(&node->n_lock); 975 } 976 977 int 978 smb_node_in_crit(smb_node_t *node) 979 { 980 return (nbl_in_crit(node->vp) && RW_LOCK_HELD(&node->n_lock)); 981 } 982 983 void 984 smb_node_rdlock(smb_node_t *node) 985 { 986 rw_enter(&node->n_lock, RW_READER); 987 } 988 989 void 990 smb_node_wrlock(smb_node_t *node) 991 { 992 rw_enter(&node->n_lock, RW_WRITER); 993 } 994 995 void 996 smb_node_unlock(smb_node_t *node) 997 { 998 rw_exit(&node->n_lock); 999 } 1000 1001 void 1002 smb_node_add_ofile(smb_node_t *node, smb_ofile_t *of) 1003 { 1004 SMB_NODE_VALID(node); 1005 1006 smb_llist_enter(&node->n_ofile_list, RW_WRITER); 1007 smb_llist_insert_tail(&node->n_ofile_list, of); 1008 smb_llist_exit(&node->n_ofile_list); 1009 } 1010 1011 void 1012 smb_node_rem_ofile(smb_node_t *node, smb_ofile_t *of) 1013 { 1014 SMB_NODE_VALID(node); 1015 1016 smb_llist_enter(&node->n_ofile_list, RW_WRITER); 1017 smb_llist_remove(&node->n_ofile_list, of); 1018 smb_llist_exit(&node->n_ofile_list); 1019 } 1020 1021 /* 1022 * smb_node_inc_open_ofiles 1023 */ 1024 void 1025 smb_node_inc_open_ofiles(smb_node_t *node) 1026 { 1027 SMB_NODE_VALID(node); 1028 atomic_inc_32(&node->n_open_count); 1029 } 1030 1031 /* 1032 * smb_node_dec_open_ofiles 1033 * returns new value 1034 */ 1035 uint32_t 1036 smb_node_dec_open_ofiles(smb_node_t *node) 1037 { 1038 SMB_NODE_VALID(node); 1039 return (atomic_dec_32_nv(&node->n_open_count)); 1040 } 1041 1042 /* 1043 * smb_node_inc_opening_count 1044 */ 1045 void 1046 smb_node_inc_opening_count(smb_node_t *node) 1047 { 1048 SMB_NODE_VALID(node); 1049 atomic_inc_32(&node->n_opening_count); 1050 } 1051 1052 /* 1053 * smb_node_dec_opening_count 1054 */ 1055 void 1056 smb_node_dec_opening_count(smb_node_t *node) 1057 { 1058 SMB_NODE_VALID(node); 1059 atomic_dec_32(&node->n_opening_count); 1060 } 1061 1062 /* 1063 * smb_node_getmntpath 1064 */ 1065 int 1066 smb_node_getmntpath(smb_node_t *node, char *buf, uint32_t buflen) 1067 { 1068 vnode_t *vp, *root_vp; 1069 vfs_t *vfsp; 1070 int err; 1071 1072 ASSERT(node); 1073 ASSERT(node->vp); 1074 ASSERT(node->vp->v_vfsp); 1075 1076 vp = node->vp; 1077 vfsp = vp->v_vfsp; 1078 1079 if (VFS_ROOT(vfsp, &root_vp)) 1080 return (ENOENT); 1081 1082 VN_HOLD(vp); 1083 1084 /* NULL is passed in as we want to start at "/" */ 1085 err = vnodetopath(NULL, root_vp, buf, buflen, zone_kcred()); 1086 1087 VN_RELE(vp); 1088 VN_RELE(root_vp); 1089 return (err); 1090 } 1091 1092 /* 1093 * smb_node_getshrpath 1094 * 1095 * Determine the absolute pathname of 'node' within the share (tree). 1096 * For example if the node represents file "test1.txt" in directory 1097 * "dir1" the pathname would be: \dir1\test1.txt 1098 */ 1099 int 1100 smb_node_getshrpath(smb_node_t *node, smb_tree_t *tree, 1101 char *buf, uint32_t buflen) 1102 { 1103 int rc; 1104 1105 ASSERT(node); 1106 ASSERT(tree); 1107 ASSERT(tree->t_snode); 1108 1109 rc = smb_node_getpath(node, tree->t_snode->vp, buf, buflen); 1110 (void) strsubst(buf, '/', '\\'); 1111 return (rc); 1112 } 1113 1114 /* 1115 * smb_node_getpath 1116 * 1117 * Determine the absolute pathname of 'node' from 'rootvp'. 1118 * 1119 * Using vnodetopath is only reliable for directory nodes (due to 1120 * its reliance on the DNLC for non-directory nodes). Thus, if node 1121 * represents a file, construct the pathname for the parent dnode 1122 * and append filename. 1123 * If node represents a named stream, construct the pathname for the 1124 * associated unnamed stream and append the stream name. 1125 * 1126 * The pathname returned in buf will be '/' separated. 1127 */ 1128 int 1129 smb_node_getpath(smb_node_t *node, vnode_t *rootvp, char *buf, uint32_t buflen) 1130 { 1131 int rc; 1132 vnode_t *vp; 1133 smb_node_t *unode, *dnode; 1134 cred_t *kcr = zone_kcred(); 1135 1136 unode = (SMB_IS_STREAM(node)) ? node->n_unode : node; 1137 dnode = (smb_node_is_dir(unode)) ? unode : unode->n_dnode; 1138 1139 /* find path to directory node */ 1140 vp = dnode->vp; 1141 VN_HOLD(vp); 1142 if (rootvp) { 1143 VN_HOLD(rootvp); 1144 rc = vnodetopath(rootvp, vp, buf, buflen, kcr); 1145 VN_RELE(rootvp); 1146 } else { 1147 rc = vnodetopath(NULL, vp, buf, buflen, kcr); 1148 } 1149 VN_RELE(vp); 1150 1151 if (rc != 0) 1152 return (rc); 1153 1154 /* append filename if necessary */ 1155 if (!smb_node_is_dir(unode)) { 1156 if (buf[strlen(buf) - 1] != '/') 1157 (void) strlcat(buf, "/", buflen); 1158 (void) strlcat(buf, unode->od_name, buflen); 1159 } 1160 1161 /* append named stream name if necessary */ 1162 if (SMB_IS_STREAM(node)) 1163 (void) strlcat(buf, node->od_name, buflen); 1164 1165 return (rc); 1166 } 1167 1168 /* 1169 * smb_node_alloc 1170 */ 1171 static smb_node_t * 1172 smb_node_alloc( 1173 char *od_name, 1174 vnode_t *vp, 1175 smb_llist_t *bucket, 1176 uint32_t hashkey) 1177 { 1178 smb_node_t *node; 1179 vnode_t *root_vp; 1180 1181 node = kmem_cache_alloc(smb_node_cache, KM_SLEEP); 1182 1183 if (node->n_audit_buf != NULL) 1184 node->n_audit_buf->anb_index = 0; 1185 1186 node->flags = 0; 1187 VN_HOLD(vp); 1188 node->vp = vp; 1189 node->n_refcnt = 1; 1190 node->n_hash_bucket = bucket; 1191 node->n_hashkey = hashkey; 1192 node->n_open_count = 0; 1193 node->n_allocsz = 0; 1194 node->n_dnode = NULL; 1195 node->n_unode = NULL; 1196 node->delete_on_close_cred = NULL; 1197 node->n_delete_on_close_flags = 0; 1198 node->n_oplock.ol_fem = B_FALSE; 1199 1200 (void) strlcpy(node->od_name, od_name, sizeof (node->od_name)); 1201 if (strcmp(od_name, XATTR_DIR) == 0) 1202 node->flags |= NODE_XATTR_DIR; 1203 1204 if (VFS_ROOT(vp->v_vfsp, &root_vp) == 0) { 1205 if (vp == root_vp) 1206 node->flags |= NODE_FLAGS_VFSROOT; 1207 VN_RELE(root_vp); 1208 } 1209 1210 node->n_state = SMB_NODE_STATE_AVAILABLE; 1211 node->n_magic = SMB_NODE_MAGIC; 1212 1213 return (node); 1214 } 1215 1216 /* 1217 * smb_node_free 1218 */ 1219 static void 1220 smb_node_free(smb_node_t *node) 1221 { 1222 SMB_NODE_VALID(node); 1223 1224 node->n_magic = 0; 1225 VERIFY(!list_link_active(&node->n_lnd)); 1226 VERIFY(node->n_lock_list.ll_count == 0); 1227 VERIFY(node->n_wlock_list.ll_count == 0); 1228 VERIFY(node->n_ofile_list.ll_count == 0); 1229 VERIFY(node->n_oplock.ol_fem == B_FALSE); 1230 VERIFY(MUTEX_NOT_HELD(&node->n_mutex)); 1231 VERIFY(!RW_LOCK_HELD(&node->n_lock)); 1232 VN_RELE(node->vp); 1233 kmem_cache_free(smb_node_cache, node); 1234 } 1235 1236 /* 1237 * smb_node_constructor 1238 */ 1239 static int 1240 smb_node_constructor(void *buf, void *un, int kmflags) 1241 { 1242 _NOTE(ARGUNUSED(kmflags, un)) 1243 1244 smb_node_t *node = (smb_node_t *)buf; 1245 1246 bzero(node, sizeof (smb_node_t)); 1247 1248 smb_llist_constructor(&node->n_ofile_list, sizeof (smb_ofile_t), 1249 offsetof(smb_ofile_t, f_node_lnd)); 1250 smb_llist_constructor(&node->n_lock_list, sizeof (smb_lock_t), 1251 offsetof(smb_lock_t, l_lnd)); 1252 smb_llist_constructor(&node->n_wlock_list, sizeof (smb_lock_t), 1253 offsetof(smb_lock_t, l_lnd)); 1254 mutex_init(&node->n_oplock.ol_mutex, NULL, MUTEX_DEFAULT, NULL); 1255 cv_init(&node->n_oplock.WaitingOpenCV, NULL, CV_DEFAULT, NULL); 1256 rw_init(&node->n_lock, NULL, RW_DEFAULT, NULL); 1257 mutex_init(&node->n_mutex, NULL, MUTEX_DEFAULT, NULL); 1258 smb_node_create_audit_buf(node, kmflags); 1259 return (0); 1260 } 1261 1262 /* 1263 * smb_node_destructor 1264 */ 1265 static void 1266 smb_node_destructor(void *buf, void *un) 1267 { 1268 _NOTE(ARGUNUSED(un)) 1269 1270 smb_node_t *node = (smb_node_t *)buf; 1271 1272 smb_node_destroy_audit_buf(node); 1273 mutex_destroy(&node->n_mutex); 1274 rw_destroy(&node->n_lock); 1275 cv_destroy(&node->n_oplock.WaitingOpenCV); 1276 mutex_destroy(&node->n_oplock.ol_mutex); 1277 smb_llist_destructor(&node->n_lock_list); 1278 smb_llist_destructor(&node->n_wlock_list); 1279 smb_llist_destructor(&node->n_ofile_list); 1280 } 1281 1282 /* 1283 * smb_node_create_audit_buf 1284 */ 1285 static void 1286 smb_node_create_audit_buf(smb_node_t *node, int kmflags) 1287 { 1288 smb_audit_buf_node_t *abn; 1289 1290 if (smb_audit_flags & SMB_AUDIT_NODE) { 1291 abn = kmem_zalloc(sizeof (smb_audit_buf_node_t), kmflags); 1292 abn->anb_max_index = SMB_AUDIT_BUF_MAX_REC - 1; 1293 node->n_audit_buf = abn; 1294 } 1295 } 1296 1297 /* 1298 * smb_node_destroy_audit_buf 1299 */ 1300 static void 1301 smb_node_destroy_audit_buf(smb_node_t *node) 1302 { 1303 if (node->n_audit_buf != NULL) { 1304 kmem_free(node->n_audit_buf, sizeof (smb_audit_buf_node_t)); 1305 node->n_audit_buf = NULL; 1306 } 1307 } 1308 1309 /* 1310 * smb_node_audit 1311 * 1312 * This function saves the calling stack in the audit buffer of the node passed 1313 * in. 1314 */ 1315 static void 1316 smb_node_audit(smb_node_t *node) 1317 { 1318 #ifdef _KERNEL 1319 smb_audit_buf_node_t *abn; 1320 smb_audit_record_node_t *anr; 1321 1322 if (node->n_audit_buf) { 1323 abn = node->n_audit_buf; 1324 anr = abn->anb_records; 1325 anr += abn->anb_index; 1326 abn->anb_index++; 1327 abn->anb_index &= abn->anb_max_index; 1328 anr->anr_refcnt = node->n_refcnt; 1329 anr->anr_depth = getpcstack(anr->anr_stack, 1330 SMB_AUDIT_STACK_DEPTH); 1331 } 1332 #else /* _KERNEL */ 1333 _NOTE(ARGUNUSED(node)) 1334 #endif /* _KERNEL */ 1335 } 1336 1337 static smb_llist_t * 1338 smb_node_get_hash(fsid_t *fsid, smb_attr_t *attr, uint32_t *phashkey) 1339 { 1340 uint32_t hashkey; 1341 1342 hashkey = fsid->val[0] + attr->sa_vattr.va_nodeid; 1343 hashkey += (hashkey >> 24) + (hashkey >> 16) + (hashkey >> 8); 1344 *phashkey = hashkey; 1345 return (&smb_node_hash_table[(hashkey & SMBND_HASH_MASK)]); 1346 } 1347 1348 boolean_t 1349 smb_node_is_file(smb_node_t *node) 1350 { 1351 SMB_NODE_VALID(node); 1352 return (node->vp->v_type == VREG); 1353 } 1354 1355 boolean_t 1356 smb_node_is_dir(smb_node_t *node) 1357 { 1358 SMB_NODE_VALID(node); 1359 return ((node->vp->v_type == VDIR) || 1360 (node->flags & NODE_FLAGS_DFSLINK)); 1361 } 1362 1363 boolean_t 1364 smb_node_is_symlink(smb_node_t *node) 1365 { 1366 SMB_NODE_VALID(node); 1367 return ((node->vp->v_type == VLNK) && 1368 ((node->flags & NODE_FLAGS_REPARSE) == 0)); 1369 } 1370 1371 boolean_t 1372 smb_node_is_dfslink(smb_node_t *node) 1373 { 1374 SMB_NODE_VALID(node); 1375 return ((node->vp->v_type == VLNK) && 1376 (node->flags & NODE_FLAGS_DFSLINK)); 1377 } 1378 1379 boolean_t 1380 smb_node_is_reparse(smb_node_t *node) 1381 { 1382 SMB_NODE_VALID(node); 1383 return ((node->vp->v_type == VLNK) && 1384 (node->flags & NODE_FLAGS_REPARSE)); 1385 } 1386 1387 boolean_t 1388 smb_node_is_vfsroot(smb_node_t *node) 1389 { 1390 SMB_NODE_VALID(node); 1391 return ((node->flags & NODE_FLAGS_VFSROOT) == NODE_FLAGS_VFSROOT); 1392 } 1393 1394 boolean_t 1395 smb_node_is_system(smb_node_t *node) 1396 { 1397 SMB_NODE_VALID(node); 1398 return ((node->flags & NODE_FLAGS_SYSTEM) == NODE_FLAGS_SYSTEM); 1399 } 1400 1401 /* 1402 * smb_node_file_is_readonly 1403 * 1404 * Checks if the file (which node represents) is marked readonly 1405 * in the filesystem. Note that there may be handles open with 1406 * modify rights, and those continue to allow access even after 1407 * the DOS read-only flag has been set in the file system. 1408 */ 1409 boolean_t 1410 smb_node_file_is_readonly(smb_node_t *node) 1411 { 1412 smb_attr_t attr; 1413 1414 if (node == NULL) 1415 return (B_FALSE); /* pipes */ 1416 1417 bzero(&attr, sizeof (smb_attr_t)); 1418 attr.sa_mask = SMB_AT_DOSATTR; 1419 (void) smb_fsop_getattr(NULL, zone_kcred(), node, &attr); 1420 return ((attr.sa_dosattr & FILE_ATTRIBUTE_READONLY) != 0); 1421 } 1422 1423 /* 1424 * smb_node_setattr 1425 * 1426 * The sr may be NULL, for example when closing an ofile. 1427 * The ofile may be NULL, for example when a client request 1428 * specifies the file by pathname. 1429 * 1430 * Returns: errno 1431 * 1432 * Timestamps 1433 * 1434 * Windows and Unix have different models for timestamp updates. 1435 * [MS-FSA 2.1.5.14 Server Requests Setting of File Information] 1436 * 1437 * An open "handle" in Windows can control whether and when 1438 * any timestamp updates happen for that handle. For example, 1439 * timestamps set via some handle are no longer updated by I/O 1440 * operations on that handle. In Unix we don't really have any 1441 * way to avoid the timestamp updates that the file system does. 1442 * Therefore, we need to make some compromises, and simulate the 1443 * more important parts of the Windows file system semantics. 1444 * 1445 * For example, when an SMB client sets file times, set those 1446 * times in the file system (so the change will be visible to 1447 * other clients, at least until they change again) but we also 1448 * make those times "sticky" in our open handle, and reapply 1449 * those times when the handle is closed. That reapply on close 1450 * simulates the Windows behavior where the timestamp updates 1451 * would be discontinued after they were set. These "sticky" 1452 * attributes are returned in any query on the handle where 1453 * they are stored. 1454 * 1455 * Other than the above, the file system layer takes care of the 1456 * normal time stamp updates, such as updating the mtime after a 1457 * write, and ctime after an attribute change. 1458 * 1459 * Dos Attributes are stored persistently, but with a twist: 1460 * In Windows, when you set the "read-only" bit on some file, 1461 * existing writable handles to that file continue to have 1462 * write access. (because access check happens at open) 1463 * If we were to set the read-only bit directly, we would 1464 * cause errors in subsequent writes on any of our open 1465 * (and writable) file handles. So here too, we have to 1466 * simulate the Windows behavior. We keep the read-only 1467 * bit "pending" in the smb_node (so it will be visible in 1468 * any new opens of the file) and apply it on close. 1469 * 1470 * File allocation size is also simulated, and not persistent. 1471 * When the file allocation size is set it is first rounded up 1472 * to block size. If the file size is smaller than the allocation 1473 * size the file is truncated by setting the filesize to allocsz. 1474 */ 1475 int 1476 smb_node_setattr(smb_request_t *sr, smb_node_t *node, 1477 cred_t *cr, smb_ofile_t *of, smb_attr_t *attr) 1478 { 1479 int rc; 1480 uint_t times_mask; 1481 smb_attr_t tmp_attr; 1482 smb_node_t *unnamed_node; 1483 1484 SMB_NODE_VALID(node); 1485 1486 /* set attributes specified in attr */ 1487 if (attr->sa_mask == 0) 1488 return (0); /* nothing to do (caller bug?) */ 1489 1490 /* 1491 * Allocation size and EOF position interact. 1492 * We don't persistently store the allocation size 1493 * but make it look like we do while there are opens. 1494 * Note: We update the caller's attr in the cases 1495 * where they're setting only one of allocsz|size. 1496 */ 1497 switch (attr->sa_mask & (SMB_AT_ALLOCSZ | SMB_AT_SIZE)) { 1498 1499 case SMB_AT_ALLOCSZ: 1500 /* 1501 * Setting the allocation size but not EOF position. 1502 * Get the current EOF in tmp_attr and (if necessary) 1503 * truncate to the (rounded up) allocation size. 1504 * Using kcred here because if we don't have access, 1505 * we want to fail at setattr below and not here. 1506 */ 1507 bzero(&tmp_attr, sizeof (smb_attr_t)); 1508 tmp_attr.sa_mask = SMB_AT_SIZE; 1509 rc = smb_fsop_getattr(NULL, zone_kcred(), node, &tmp_attr); 1510 if (rc != 0) 1511 return (rc); 1512 attr->sa_allocsz = SMB_ALLOCSZ(attr->sa_allocsz); 1513 if (tmp_attr.sa_vattr.va_size > attr->sa_allocsz) { 1514 /* truncate the file to allocsz */ 1515 attr->sa_vattr.va_size = attr->sa_allocsz; 1516 attr->sa_mask |= SMB_AT_SIZE; 1517 } 1518 break; 1519 1520 case SMB_AT_SIZE: 1521 /* 1522 * Setting the EOF position but not allocation size. 1523 * If the new EOF position would be greater than 1524 * the allocation size, increase the latter. 1525 */ 1526 if (node->n_allocsz < attr->sa_vattr.va_size) { 1527 attr->sa_mask |= SMB_AT_ALLOCSZ; 1528 attr->sa_allocsz = 1529 SMB_ALLOCSZ(attr->sa_vattr.va_size); 1530 } 1531 break; 1532 1533 case SMB_AT_ALLOCSZ | SMB_AT_SIZE: 1534 /* 1535 * Setting both. Increase alloc size if needed. 1536 */ 1537 if (attr->sa_allocsz < attr->sa_vattr.va_size) 1538 attr->sa_allocsz = 1539 SMB_ALLOCSZ(attr->sa_vattr.va_size); 1540 break; 1541 1542 default: 1543 break; 1544 } 1545 1546 /* 1547 * When operating on an open file, some settable attributes 1548 * become "sticky" in the open file object until close. 1549 * (see above re. timestamps) 1550 */ 1551 times_mask = attr->sa_mask & SMB_AT_TIMES; 1552 if (of != NULL && times_mask != 0) { 1553 smb_attr_t *pa; 1554 1555 SMB_OFILE_VALID(of); 1556 mutex_enter(&of->f_mutex); 1557 pa = &of->f_pending_attr; 1558 1559 pa->sa_mask |= times_mask; 1560 1561 if (times_mask & SMB_AT_ATIME) 1562 pa->sa_vattr.va_atime = 1563 attr->sa_vattr.va_atime; 1564 if (times_mask & SMB_AT_MTIME) 1565 pa->sa_vattr.va_mtime = 1566 attr->sa_vattr.va_mtime; 1567 if (times_mask & SMB_AT_CTIME) 1568 pa->sa_vattr.va_ctime = 1569 attr->sa_vattr.va_ctime; 1570 if (times_mask & SMB_AT_CRTIME) 1571 pa->sa_crtime = 1572 attr->sa_crtime; 1573 1574 mutex_exit(&of->f_mutex); 1575 1576 /* 1577 * The f_pending_attr times are reapplied in 1578 * smb_ofile_close(). 1579 */ 1580 1581 /* 1582 * If this change is coming directly from a client 1583 * (sr != NULL) and it's a persistent handle, save 1584 * the "sticky times" in the handle. 1585 */ 1586 if (sr != NULL && of->dh_persist) { 1587 smb2_dh_update_times(sr, of, attr); 1588 } 1589 } 1590 1591 if ((attr->sa_mask & SMB_AT_ALLOCSZ) != 0) { 1592 mutex_enter(&node->n_mutex); 1593 /* 1594 * Simulate n_allocsz persistence only while 1595 * there are opens. See smb_node_getattr 1596 */ 1597 if (node->n_open_count != 0) 1598 node->n_allocsz = attr->sa_allocsz; 1599 mutex_exit(&node->n_mutex); 1600 } 1601 1602 rc = smb_fsop_setattr(sr, cr, node, attr); 1603 if (rc != 0) 1604 return (rc); 1605 1606 if (node->n_dnode != NULL) { 1607 smb_node_notify_change(node->n_dnode, 1608 FILE_ACTION_MODIFIED, node->od_name); 1609 } 1610 1611 if ((unnamed_node = SMB_IS_STREAM(node)) != NULL) { 1612 ASSERT(unnamed_node->n_magic == SMB_NODE_MAGIC); 1613 ASSERT(unnamed_node->n_state != SMB_NODE_STATE_DESTROYING); 1614 smb_node_notify_change(node->n_dnode, 1615 FILE_ACTION_MODIFIED_STREAM, node->od_name); 1616 } 1617 1618 return (0); 1619 } 1620 1621 /* 1622 * smb_node_getattr 1623 * 1624 * Get attributes from the file system and apply any smb-specific 1625 * overrides for size, dos attributes and timestamps 1626 * 1627 * When node->n_pending_readonly is set on a node, pretend that 1628 * we've already set this node readonly at the filesystem level. 1629 * We can't actually do that until all writable handles are closed 1630 * or those writable handles would suddenly loose their access. 1631 * 1632 * Returns: errno 1633 */ 1634 int 1635 smb_node_getattr(smb_request_t *sr, smb_node_t *node, cred_t *cr, 1636 smb_ofile_t *of, smb_attr_t *attr) 1637 { 1638 int rc; 1639 uint_t want_mask, pend_mask; 1640 boolean_t isdir; 1641 1642 SMB_NODE_VALID(node); 1643 1644 /* Deal with some interdependencies */ 1645 if (attr->sa_mask & SMB_AT_ALLOCSZ) 1646 attr->sa_mask |= SMB_AT_SIZE; 1647 if (attr->sa_mask & SMB_AT_DOSATTR) 1648 attr->sa_mask |= SMB_AT_TYPE; 1649 1650 rc = smb_fsop_getattr(sr, cr, node, attr); 1651 if (rc != 0) 1652 return (rc); 1653 1654 isdir = smb_node_is_dir(node); 1655 1656 mutex_enter(&node->n_mutex); 1657 1658 if (attr->sa_mask & SMB_AT_DOSATTR) { 1659 if (attr->sa_dosattr == 0) { 1660 attr->sa_dosattr = (isdir) ? 1661 FILE_ATTRIBUTE_DIRECTORY: 1662 FILE_ATTRIBUTE_NORMAL; 1663 } 1664 } 1665 1666 /* 1667 * Also fix-up sa_allocsz, which is not persistent. 1668 * When there are no open files, allocsz is faked. 1669 * While there are open files, we pretend we have a 1670 * persistent allocation size in n_allocsz, and 1671 * keep that up-to-date here, increasing it when 1672 * we see the file size grow past it. 1673 */ 1674 if (attr->sa_mask & SMB_AT_ALLOCSZ) { 1675 if (isdir) { 1676 attr->sa_allocsz = 0; 1677 } else if (node->n_open_count == 0) { 1678 attr->sa_allocsz = 1679 SMB_ALLOCSZ(attr->sa_vattr.va_size); 1680 } else { 1681 if (node->n_allocsz < attr->sa_vattr.va_size) 1682 node->n_allocsz = 1683 SMB_ALLOCSZ(attr->sa_vattr.va_size); 1684 attr->sa_allocsz = node->n_allocsz; 1685 } 1686 } 1687 1688 mutex_exit(&node->n_mutex); 1689 1690 if (isdir) { 1691 attr->sa_vattr.va_size = 0; 1692 attr->sa_vattr.va_nlink = 1; 1693 } 1694 1695 /* 1696 * getattr with an ofile gets any "pending" times that 1697 * might have been previously set via this ofile. 1698 * This is what makes these times "sticky". 1699 */ 1700 want_mask = attr->sa_mask & SMB_AT_TIMES; 1701 if (of != NULL && want_mask != 0) { 1702 smb_attr_t *pa; 1703 1704 SMB_OFILE_VALID(of); 1705 mutex_enter(&of->f_mutex); 1706 pa = &of->f_pending_attr; 1707 1708 pend_mask = pa->sa_mask; 1709 1710 if (want_mask & pend_mask & SMB_AT_ATIME) 1711 attr->sa_vattr.va_atime = 1712 pa->sa_vattr.va_atime; 1713 if (want_mask & pend_mask & SMB_AT_MTIME) 1714 attr->sa_vattr.va_mtime = 1715 pa->sa_vattr.va_mtime; 1716 if (want_mask & pend_mask & SMB_AT_CTIME) 1717 attr->sa_vattr.va_ctime = 1718 pa->sa_vattr.va_ctime; 1719 if (want_mask & pend_mask & SMB_AT_CRTIME) 1720 attr->sa_crtime = 1721 pa->sa_crtime; 1722 1723 mutex_exit(&of->f_mutex); 1724 } 1725 1726 1727 return (0); 1728 } 1729 1730 1731 #ifndef _KERNEL 1732 extern int reparse_vnode_parse(vnode_t *vp, nvlist_t *nvl); 1733 #endif /* _KERNEL */ 1734 1735 /* 1736 * Check to see if the node represents a reparse point. 1737 * If yes, whether the reparse point contains a DFS link. 1738 */ 1739 static void 1740 smb_node_init_reparse(smb_node_t *node, smb_attr_t *attr) 1741 { 1742 nvlist_t *nvl; 1743 nvpair_t *rec; 1744 char *rec_type; 1745 1746 if ((attr->sa_dosattr & FILE_ATTRIBUTE_REPARSE_POINT) == 0) 1747 return; 1748 1749 if ((nvl = reparse_init()) == NULL) 1750 return; 1751 1752 if (reparse_vnode_parse(node->vp, nvl) != 0) { 1753 reparse_free(nvl); 1754 return; 1755 } 1756 1757 node->flags |= NODE_FLAGS_REPARSE; 1758 1759 rec = nvlist_next_nvpair(nvl, NULL); 1760 while (rec != NULL) { 1761 rec_type = nvpair_name(rec); 1762 if ((rec_type != NULL) && 1763 (strcasecmp(rec_type, DFS_REPARSE_SVCTYPE) == 0)) { 1764 node->flags |= NODE_FLAGS_DFSLINK; 1765 break; 1766 } 1767 rec = nvlist_next_nvpair(nvl, rec); 1768 } 1769 1770 reparse_free(nvl); 1771 } 1772 1773 /* 1774 * smb_node_init_system 1775 * 1776 * If the node represents a special system file set NODE_FLAG_SYSTEM. 1777 * System files: 1778 * - any node whose parent dnode has NODE_FLAG_SYSTEM set 1779 * - any node whose associated unnamed stream node (unode) has 1780 * NODE_FLAG_SYSTEM set 1781 * - .$EXTEND at root of share (quota management) 1782 */ 1783 static void 1784 smb_node_init_system(smb_node_t *node) 1785 { 1786 smb_node_t *dnode = node->n_dnode; 1787 smb_node_t *unode = node->n_unode; 1788 1789 if ((dnode) && (dnode->flags & NODE_FLAGS_SYSTEM)) { 1790 node->flags |= NODE_FLAGS_SYSTEM; 1791 return; 1792 } 1793 1794 if ((unode) && (unode->flags & NODE_FLAGS_SYSTEM)) { 1795 node->flags |= NODE_FLAGS_SYSTEM; 1796 return; 1797 } 1798 1799 if ((dnode) && (smb_node_is_vfsroot(node->n_dnode) && 1800 (strcasecmp(node->od_name, ".$EXTEND") == 0))) { 1801 node->flags |= NODE_FLAGS_SYSTEM; 1802 } 1803 } 1804