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