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