Print this page
NEX-13644 File access audit logging
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-17779 Creating named streams on existing files is not quite right
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-2807 Restoring previous versions from snapshots doesn't work with nested folders.
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15931 Panic removing files in SMB3 CA share
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Include in backports of:
  NEX-9808 SMB3 persistent handles
NEX-15931 Panic removing files in SMB3 CA share
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Include in backports of:
  NEX-9808 SMB3 persistent handles
NEX-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15578 SMB2 durable handle redesign
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-15069 smtorture smb2.create.blob is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15578 SMB2 durable handle redesign
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-15069 smtorture smb2.create.blob is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-13653 Obsolete SMB server work-around for ZFS read-only
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-9604 SMB: smb2 does not delete a read-only file, where smb1 does
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-6041 Should pass the smbtorture lock tests
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-5312 delete_on_close should be acted on earlier
Reviewed by: Gordon Ross <gwr@nexenta.com>
NEX-3906 Prefer that SMB change notify not tie up a worker thread
NEX-5278 SMB notify should buffer per file handle
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-4083 Upstream changes from illumos 5917 and 5995
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-3620 need upstream cleanups for smbsrv
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>
SMB-142 Deadlock in SMB2
SMB-131 Don't allow setting delete-on-close on non empty dirs
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
SMB-50 User-mode SMB server
 Includes work by these authors:
 Thomas Keiser <thomas.keiser@nexenta.com>
 Albert Lee <trisk@nexenta.com>
SMB-65 SMB server in non-global zones (use zone_kcred())
SMB-65 SMB server in non-global zones (kmem_caches)
common kmem_cache instances across zones
separate GZ-only init from NGZ init
SUP-599 smb_oplock_acquire thread deadlock
re #7815 SMB server delivers old modification time... (fix allocsz)
re #13470 rb4432 Sync some SMB differences from illumos
re #7815 SMB server delivers old modification time...
re #11215 rb3676 sesctl to SGI JBOD hangs in biowait() with a command stuck in mptsas driver
re #10734 NT Trans. Notify returning too quickly


   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 2014 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  |


  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 


 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.


 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);


 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_notify_event(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  *


 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, smb_request_t *sr)
 851 {
 852         smb_node_fcn_t          *fcn = &node->n_fcn;
 853 
 854         mutex_enter(&fcn->fcn_mutex);
 855         if (fcn->fcn_count == 0)
 856                 (void) smb_fem_fcn_install(node);
 857         fcn->fcn_count++;
 858         list_insert_tail(&fcn->fcn_watchers, sr);
 859         mutex_exit(&fcn->fcn_mutex);
 860 }
 861 
 862 void
 863 smb_node_fcn_unsubscribe(smb_node_t *node, smb_request_t *sr)
 864 {
 865         smb_node_fcn_t          *fcn = &node->n_fcn;
 866 
 867         mutex_enter(&fcn->fcn_mutex);
 868         list_remove(&fcn->fcn_watchers, sr);
 869         fcn->fcn_count--;
 870         if (fcn->fcn_count == 0)
 871                 smb_fem_fcn_uninstall(node);
 872         mutex_exit(&fcn->fcn_mutex);
 873 }
 874 
 875 void
 876 smb_node_notify_change(smb_node_t *node, uint_t action, const char *name)
 877 {


 878         SMB_NODE_VALID(node);
 879 
 880         smb_notify_event(node, action, name);
 881 

 882         /*
 883          * These two events come as a pair:
 884          *   FILE_ACTION_RENAMED_OLD_NAME
 885          *   FILE_ACTION_RENAMED_NEW_NAME
 886          * Only do the parent notify for "new".



 887          */
 888         if (action == FILE_ACTION_RENAMED_OLD_NAME)
 889                 return;



 890 
 891         smb_node_notify_parents(node);
 892 }
 893 
 894 /*
 895  * smb_node_notify_parents
 896  *
 897  * Iterate up the directory tree notifying any parent
 898  * directories that are being watched for changes in
 899  * their sub directories.
 900  * Stop at the root node, which has a NULL parent node.
 901  */
 902 void
 903 smb_node_notify_parents(smb_node_t *dnode)
 904 {
 905         smb_node_t *pnode;      /* parent */
 906 
 907         SMB_NODE_VALID(dnode);
 908         pnode = dnode->n_dnode;
 909 
 910         while (pnode != NULL) {
 911                 SMB_NODE_VALID(pnode);
 912                 smb_notify_event(pnode, FILE_ACTION_SUBDIR_CHANGED, NULL);
 913                 /* cd .. */
 914                 dnode = pnode;
 915                 pnode = dnode->n_dnode;
 916         }















 917 }
 918 
 919 /*
 920  * smb_node_start_crit()
 921  *
 922  * Enter critical region for share reservations.
 923  * See comments above smb_fsop_shrlock().
 924  */
 925 void
 926 smb_node_start_crit(smb_node_t *node, krw_t mode)
 927 {
 928         rw_enter(&node->n_lock, mode);
 929         nbl_start_crit(node->vp, mode);
 930 }
 931 
 932 /*
 933  * smb_node_end_crit()
 934  *
 935  * Exit critical region for share reservations.
 936  */


1116         VN_RELE(vp);
1117 
1118         if (rc != 0)
1119                 return (rc);
1120 
1121         /* append filename if necessary */
1122         if (!smb_node_is_dir(unode)) {
1123                 if (buf[strlen(buf) - 1] != '/')
1124                         (void) strlcat(buf, "/", buflen);
1125                 (void) strlcat(buf, unode->od_name, buflen);
1126         }
1127 
1128         /* append named stream name if necessary */
1129         if (SMB_IS_STREAM(node))
1130                 (void) strlcat(buf, node->od_name, buflen);
1131 
1132         return (rc);
1133 }
1134 
1135 /*







































































































































1136  * smb_node_alloc
1137  */
1138 static smb_node_t *
1139 smb_node_alloc(
1140     char        *od_name,
1141     vnode_t     *vp,
1142     smb_llist_t *bucket,
1143     uint32_t    hashkey)
1144 {
1145         smb_node_t      *node;
1146         vnode_t         *root_vp;
1147 
1148         node = kmem_cache_alloc(smb_node_cache, KM_SLEEP);
1149 
1150         if (node->n_audit_buf != NULL)
1151                 node->n_audit_buf->anb_index = 0;
1152 
1153         node->flags = 0;
1154         VN_HOLD(vp);
1155         node->vp = vp;
1156         node->n_refcnt = 1;
1157         node->n_hash_bucket = bucket;
1158         node->n_hashkey = hashkey;
1159         node->n_pending_dosattr = 0;
1160         node->n_open_count = 0;
1161         node->n_allocsz = 0;
1162         node->n_dnode = NULL;
1163         node->n_unode = NULL;
1164         node->delete_on_close_cred = NULL;
1165         node->n_delete_on_close_flags = 0;
1166         node->n_oplock.ol_fem = B_FALSE;
1167         node->n_oplock.ol_xthread = NULL;
1168         node->n_oplock.ol_count = 0;
1169         node->n_oplock.ol_break = SMB_OPLOCK_NO_BREAK;
1170 
1171         (void) strlcpy(node->od_name, od_name, sizeof (node->od_name));
1172         if (strcmp(od_name, XATTR_DIR) == 0)
1173                 node->flags |= NODE_XATTR_DIR;
1174 
1175         if (VFS_ROOT(vp->v_vfsp, &root_vp) == 0) {
1176                 if (vp == root_vp)
1177                         node->flags |= NODE_FLAGS_VFSROOT;
1178                 VN_RELE(root_vp);
1179         }
1180 
1181         node->n_state = SMB_NODE_STATE_AVAILABLE;
1182         node->n_magic = SMB_NODE_MAGIC;
1183 
1184         return (node);
1185 }
1186 
1187 /*
1188  * smb_node_free
1189  */
1190 static void
1191 smb_node_free(smb_node_t *node)
1192 {
1193         SMB_NODE_VALID(node);
1194 
1195         node->n_magic = 0;
1196         VERIFY(!list_link_active(&node->n_lnd));
1197         VERIFY(node->n_lock_list.ll_count == 0);

1198         VERIFY(node->n_ofile_list.ll_count == 0);
1199         VERIFY(node->n_oplock.ol_count == 0);
1200         VERIFY(node->n_oplock.ol_xthread == NULL);
1201         VERIFY(node->n_oplock.ol_fem == B_FALSE);
1202         VERIFY(MUTEX_NOT_HELD(&node->n_mutex));
1203         VERIFY(!RW_LOCK_HELD(&node->n_lock));
1204         VN_RELE(node->vp);
1205         kmem_cache_free(smb_node_cache, node);
1206 }
1207 
1208 /*
1209  * smb_node_constructor
1210  */
1211 static int
1212 smb_node_constructor(void *buf, void *un, int kmflags)
1213 {
1214         _NOTE(ARGUNUSED(kmflags, un))
1215 
1216         smb_node_t      *node = (smb_node_t *)buf;
1217 
1218         bzero(node, sizeof (smb_node_t));
1219 
1220         smb_llist_constructor(&node->n_ofile_list, sizeof (smb_ofile_t),
1221             offsetof(smb_ofile_t, f_nnd));
1222         smb_llist_constructor(&node->n_lock_list, sizeof (smb_lock_t),
1223             offsetof(smb_lock_t, l_lnd));
1224         mutex_init(&node->n_fcn.fcn_mutex, NULL, MUTEX_DEFAULT, NULL);
1225         list_create(&node->n_fcn.fcn_watchers, sizeof (smb_request_t),
1226             offsetof(smb_request_t, sr_ncr.nc_lnd));
1227         cv_init(&node->n_oplock.ol_cv, NULL, CV_DEFAULT, NULL);
1228         mutex_init(&node->n_oplock.ol_mutex, NULL, MUTEX_DEFAULT, NULL);
1229         list_create(&node->n_oplock.ol_grants, sizeof (smb_oplock_grant_t),
1230             offsetof(smb_oplock_grant_t, og_lnd));
1231         rw_init(&node->n_lock, NULL, RW_DEFAULT, NULL);
1232         mutex_init(&node->n_mutex, NULL, MUTEX_DEFAULT, NULL);
1233         smb_node_create_audit_buf(node, kmflags);
1234         return (0);
1235 }
1236 
1237 /*
1238  * smb_node_destructor
1239  */
1240 static void
1241 smb_node_destructor(void *buf, void *un)
1242 {
1243         _NOTE(ARGUNUSED(un))
1244 
1245         smb_node_t      *node = (smb_node_t *)buf;
1246 
1247         smb_node_destroy_audit_buf(node);
1248         mutex_destroy(&node->n_mutex);
1249         rw_destroy(&node->n_lock);
1250         cv_destroy(&node->n_oplock.ol_cv);
1251         mutex_destroy(&node->n_oplock.ol_mutex);
1252         list_destroy(&node->n_fcn.fcn_watchers);
1253         mutex_destroy(&node->n_fcn.fcn_mutex);
1254         smb_llist_destructor(&node->n_lock_list);

1255         smb_llist_destructor(&node->n_ofile_list);
1256         list_destroy(&node->n_oplock.ol_grants);
1257 }
1258 
1259 /*
1260  * smb_node_create_audit_buf
1261  */
1262 static void
1263 smb_node_create_audit_buf(smb_node_t *node, int kmflags)
1264 {
1265         smb_audit_buf_node_t    *abn;
1266 
1267         if (smb_audit_flags & SMB_AUDIT_NODE) {
1268                 abn = kmem_zalloc(sizeof (smb_audit_buf_node_t), kmflags);
1269                 abn->anb_max_index = SMB_AUDIT_BUF_MAX_REC - 1;
1270                 node->n_audit_buf = abn;
1271         }
1272 }
1273 
1274 /*
1275  * smb_node_destroy_audit_buf
1276  */


1362 }
1363 
1364 boolean_t
1365 smb_node_is_vfsroot(smb_node_t *node)
1366 {
1367         SMB_NODE_VALID(node);
1368         return ((node->flags & NODE_FLAGS_VFSROOT) == NODE_FLAGS_VFSROOT);
1369 }
1370 
1371 boolean_t
1372 smb_node_is_system(smb_node_t *node)
1373 {
1374         SMB_NODE_VALID(node);
1375         return ((node->flags & NODE_FLAGS_SYSTEM) == NODE_FLAGS_SYSTEM);
1376 }
1377 
1378 /*
1379  * smb_node_file_is_readonly
1380  *
1381  * Checks if the file (which node represents) is marked readonly
1382  * in the filesystem. No account is taken of any pending readonly
1383  * in the node, which must be handled by the callers.
1384  * (See SMB_OFILE_IS_READONLY and SMB_PATHFILE_IS_READONLY)
1385  */
1386 boolean_t
1387 smb_node_file_is_readonly(smb_node_t *node)
1388 {
1389         smb_attr_t attr;
1390 
1391         if (node == NULL)
1392                 return (B_FALSE);       /* pipes */
1393 
1394         if (node->n_pending_dosattr & FILE_ATTRIBUTE_READONLY)
1395                 return (B_TRUE);
1396 
1397         bzero(&attr, sizeof (smb_attr_t));
1398         attr.sa_mask = SMB_AT_DOSATTR;
1399         (void) smb_fsop_getattr(NULL, zone_kcred(), node, &attr);
1400         return ((attr.sa_dosattr & FILE_ATTRIBUTE_READONLY) != 0);
1401 }
1402 
1403 /*
1404  * smb_node_setattr
1405  *
1406  * The sr may be NULL, for example when closing an ofile.
1407  * The ofile may be NULL, for example when a client request
1408  * specifies the file by pathname.
1409  *
1410  * Returns: errno
1411  *
1412  * Timestamps
1413  *
1414  * Windows and Unix have different models for timestamp updates.
1415  * [MS-FSA 2.1.5.14 Server Requests Setting of File Information]
1416  *


1442  * write access.  (because access check happens at open)
1443  * If we were to set the read-only bit directly, we would
1444  * cause errors in subsequent writes on any of our open
1445  * (and writable) file handles.  So here too, we have to
1446  * simulate the Windows behavior.  We keep the read-only
1447  * bit "pending" in the smb_node (so it will be visible in
1448  * any new opens of the file) and apply it on close.
1449  *
1450  * File allocation size is also simulated, and not persistent.
1451  * When the file allocation size is set it is first rounded up
1452  * to block size. If the file size is smaller than the allocation
1453  * size the file is truncated by setting the filesize to allocsz.
1454  */
1455 int
1456 smb_node_setattr(smb_request_t *sr, smb_node_t *node,
1457     cred_t *cr, smb_ofile_t *of, smb_attr_t *attr)
1458 {
1459         int rc;
1460         uint_t times_mask;
1461         smb_attr_t tmp_attr;

1462 
1463         SMB_NODE_VALID(node);
1464 
1465         /* set attributes specified in attr */
1466         if (attr->sa_mask == 0)
1467                 return (0);  /* nothing to do (caller bug?) */
1468 
1469         /*
1470          * Allocation size and EOF position interact.
1471          * We don't persistently store the allocation size
1472          * but make it look like we do while there are opens.
1473          * Note: We update the caller's attr in the cases
1474          * where they're setting only one of allocsz|size.
1475          */
1476         switch (attr->sa_mask & (SMB_AT_ALLOCSZ | SMB_AT_SIZE)) {
1477 
1478         case SMB_AT_ALLOCSZ:
1479                 /*
1480                  * Setting the allocation size but not EOF position.
1481                  * Get the current EOF in tmp_attr and (if necessary)


1542                 SMB_OFILE_VALID(of);
1543                 mutex_enter(&of->f_mutex);
1544                 pa = &of->f_pending_attr;
1545 
1546                 pa->sa_mask |= times_mask;
1547 
1548                 if (times_mask & SMB_AT_ATIME)
1549                         pa->sa_vattr.va_atime =
1550                             attr->sa_vattr.va_atime;
1551                 if (times_mask & SMB_AT_MTIME)
1552                         pa->sa_vattr.va_mtime =
1553                             attr->sa_vattr.va_mtime;
1554                 if (times_mask & SMB_AT_CTIME)
1555                         pa->sa_vattr.va_ctime =
1556                             attr->sa_vattr.va_ctime;
1557                 if (times_mask & SMB_AT_CRTIME)
1558                         pa->sa_crtime =
1559                             attr->sa_crtime;
1560 
1561                 mutex_exit(&of->f_mutex);

1562                 /*
1563                  * The f_pending_attr times are reapplied in
1564                  * smb_ofile_close().
1565                  */
1566         }
1567 
1568         /*
1569          * After this point, tmp_attr is what we will actually
1570          * store in the file system _now_, which may differ
1571          * from the callers attr and f_pending_attr w.r.t.
1572          * the DOS readonly flag etc.
1573          */
1574         bcopy(attr, &tmp_attr, sizeof (tmp_attr));
1575         if (attr->sa_mask & (SMB_AT_DOSATTR | SMB_AT_ALLOCSZ)) {
1576                 mutex_enter(&node->n_mutex);
1577                 if ((attr->sa_mask & SMB_AT_DOSATTR) != 0) {
1578                         tmp_attr.sa_dosattr &= smb_vop_dosattr_settable;
1579                         if (((tmp_attr.sa_dosattr &
1580                             FILE_ATTRIBUTE_READONLY) != 0) &&
1581                             (node->n_open_count != 0)) {
1582                                 /* Delay setting readonly */
1583                                 node->n_pending_dosattr =
1584                                     tmp_attr.sa_dosattr;
1585                                 tmp_attr.sa_dosattr &=
1586                                     ~FILE_ATTRIBUTE_READONLY;
1587                         } else {
1588                                 node->n_pending_dosattr = 0;
1589                         }
1590                 }



1591                 /*
1592                  * Simulate n_allocsz persistence only while
1593                  * there are opens.  See smb_node_getattr
1594                  */
1595                 if ((attr->sa_mask & SMB_AT_ALLOCSZ) != 0 &&
1596                     node->n_open_count != 0)
1597                         node->n_allocsz = attr->sa_allocsz;
1598                 mutex_exit(&node->n_mutex);
1599         }
1600 
1601         rc = smb_fsop_setattr(sr, cr, node, &tmp_attr);
1602         if (rc != 0)
1603                 return (rc);
1604 
1605         if (node->n_dnode != NULL) {
1606                 smb_node_notify_change(node->n_dnode,
1607                     FILE_ACTION_MODIFIED, node->od_name);
1608         }
1609 







1610         return (0);
1611 }
1612 
1613 /*
1614  * smb_node_getattr
1615  *
1616  * Get attributes from the file system and apply any smb-specific
1617  * overrides for size, dos attributes and timestamps
1618  *
1619  * When node->n_pending_readonly is set on a node, pretend that
1620  * we've already set this node readonly at the filesystem level.
1621  * We can't actually do that until all writable handles are closed
1622  * or those writable handles would suddenly loose their access.
1623  *
1624  * Returns: errno
1625  */
1626 int
1627 smb_node_getattr(smb_request_t *sr, smb_node_t *node, cred_t *cr,
1628     smb_ofile_t *of, smb_attr_t *attr)
1629 {
1630         int rc;
1631         uint_t want_mask, pend_mask;
1632         boolean_t isdir;
1633 
1634         SMB_NODE_VALID(node);
1635 
1636         /* Deal with some interdependencies */
1637         if (attr->sa_mask & SMB_AT_ALLOCSZ)
1638                 attr->sa_mask |= SMB_AT_SIZE;
1639         if (attr->sa_mask & SMB_AT_DOSATTR)
1640                 attr->sa_mask |= SMB_AT_TYPE;
1641 
1642         rc = smb_fsop_getattr(sr, cr, node, attr);
1643         if (rc != 0)
1644                 return (rc);
1645 
1646         isdir = smb_node_is_dir(node);
1647 
1648         mutex_enter(&node->n_mutex);
1649 
1650         /*
1651          * When there are open handles, and one of them has
1652          * set the DOS readonly flag (in n_pending_dosattr),
1653          * it will not have been stored in the file system.
1654          * In this case use n_pending_dosattr. Note that
1655          * n_pending_dosattr has only the settable bits,
1656          * (setattr masks it with smb_vop_dosattr_settable)
1657          * so we need to keep any non-settable bits we got
1658          * from the file-system above.
1659          */
1660         if (attr->sa_mask & SMB_AT_DOSATTR) {
1661                 if (node->n_pending_dosattr) {
1662                         attr->sa_dosattr &= ~smb_vop_dosattr_settable;
1663                         attr->sa_dosattr |= node->n_pending_dosattr;
1664                 }
1665                 if (attr->sa_dosattr == 0) {
1666                         attr->sa_dosattr = (isdir) ?
1667                             FILE_ATTRIBUTE_DIRECTORY:
1668                             FILE_ATTRIBUTE_NORMAL;
1669                 }
1670         }
1671 
1672         /*
1673          * Also fix-up sa_allocsz, which is not persistent.
1674          * When there are no open files, allocsz is faked.
1675          * While there are open files, we pretend we have a
1676          * persistent allocation size in n_allocsz, and
1677          * keep that up-to-date here, increasing it when
1678          * we see the file size grow past it.
1679          */
1680         if (attr->sa_mask & SMB_AT_ALLOCSZ) {
1681                 if (isdir) {
1682                         attr->sa_allocsz = 0;
1683                 } else if (node->n_open_count == 0) {
1684                         attr->sa_allocsz =




   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 2018 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  |


  71  *    rule:
  72  *
  73  *    There's a mutex embedded in the node used to protect its fields and
  74  *    there's a lock embedded in the bucket of the hash table the node belongs
  75  *    to. To increment or to decrement the reference count the mutex must be
  76  *    entered. To insert the node into the bucket and to remove it from the
  77  *    bucket the lock must be entered in RW_WRITER mode. When both (mutex and
  78  *    lock) have to be entered, the lock has always to be entered first then
  79  *    the mutex. This prevents a deadlock between smb_node_lookup() and
  80  *    smb_node_release() from occurring. However, in smb_node_release() when the
  81  *    reference count drops to zero and triggers the deletion of the node, the
  82  *    mutex has to be released before entering the lock of the bucket (to
  83  *    remove the node). This creates a window during which the node that is
  84  *    about to be freed could be given out by smb_node_lookup(). To close that
  85  *    window the node is moved to the state SMB_NODE_STATE_DESTROYING before
  86  *    releasing the mutex. That way, even if smb_node_lookup() finds it, the
  87  *    state will indicate that the node should be treated as non existent (of
  88  *    course the state of the node should be tested/updated under the
  89  *    protection of the mutex).
  90  */
  91 #include <smbsrv/smb2_kproto.h>
  92 #include <smbsrv/smb_fsops.h>
  93 #include <smbsrv/smb_kstat.h>
  94 #include <sys/ddi.h>
  95 #include <sys/extdirent.h>
  96 #include <sys/pathname.h>
  97 #include <sys/sdt.h>
  98 #include <sys/nbmlock.h>
  99 #include <fs/fs_reparse.h>
 100 
 101 uint32_t smb_is_executable(char *);

 102 static void smb_node_create_audit_buf(smb_node_t *, int);
 103 static void smb_node_destroy_audit_buf(smb_node_t *);
 104 static void smb_node_audit(smb_node_t *);
 105 static smb_node_t *smb_node_alloc(char *, vnode_t *, smb_llist_t *, uint32_t);
 106 static void smb_node_free(smb_node_t *);
 107 static int smb_node_constructor(void *, void *, int);
 108 static void smb_node_destructor(void *, void *);
 109 static smb_llist_t *smb_node_get_hash(fsid_t *, smb_attr_t *, uint32_t *);
 110 
 111 static void smb_node_init_reparse(smb_node_t *, smb_attr_t *);
 112 static void smb_node_init_system(smb_node_t *);
 113 
 114 #define VALIDATE_DIR_NODE(_dir_, _node_) \
 115     ASSERT((_dir_)->n_magic == SMB_NODE_MAGIC); \
 116     ASSERT(((_dir_)->vp->v_xattrdir) || ((_dir_)->vp->v_type == VDIR)); \
 117     ASSERT((_dir_)->n_dnode != (_node_));
 118 
 119 /* round sz to DEV_BSIZE block */
 120 #define SMB_ALLOCSZ(sz) (((sz) + DEV_BSIZE-1) & ~(DEV_BSIZE-1))
 121 


 172  * smb_node_fini
 173  *
 174  * This function is not multi-thread safe. The caller must make sure only one
 175  * thread makes the call.
 176  */
 177 void
 178 smb_node_fini(void)
 179 {
 180         int     i;
 181 
 182         if (smb_root_node != NULL) {
 183                 smb_node_release(smb_root_node);
 184                 smb_root_node = NULL;
 185         }
 186 
 187         if (smb_node_cache == NULL)
 188                 return;
 189 
 190 #ifdef DEBUG
 191         for (i = 0; i <= SMBND_HASH_MASK; i++) {
 192                 smb_llist_t     *bucket;
 193                 smb_node_t      *node;
 194 
 195                 /*
 196                  * The following sequence is just intended for sanity check.
 197                  * This will have to be modified when the code goes into
 198                  * production.
 199                  *
 200                  * The SMB node hash table should be emtpy at this point. If the
 201                  * hash table is not empty a panic will be triggered.
 202                  *
 203                  * The reason why SMB nodes are still remaining in the hash
 204                  * table is problably due to a mismatch between calls to
 205                  * smb_node_lookup() and smb_node_release(). You must track that
 206                  * down.
 207                  */
 208                 bucket = &smb_node_hash_table[i];
 209                 node = smb_llist_head(bucket);
 210                 while (node != NULL) {
 211                         cmn_err(CE_NOTE, "leaked node: 0x%p %s",
 212                             (void *)node, node->od_name);
 213                         node = smb_llist_next(bucket, node);
 214                 }
 215         }
 216 #endif
 217 
 218         for (i = 0; i <= SMBND_HASH_MASK; i++) {
 219                 smb_llist_destructor(&smb_node_hash_table[i]);
 220         }
 221         kmem_cache_destroy(smb_node_cache);
 222         smb_node_cache = NULL;
 223 }
 224 
 225 /*
 226  * smb_node_lookup()
 227  *
 228  * NOTE: This routine should only be called by the file system interface layer,
 229  * and not by SMB.
 230  *
 231  * smb_node_lookup() is called upon successful lookup, mkdir, and create
 232  * (for both non-streams and streams).  In each of these cases, a held vnode is
 233  * passed into this routine.  If a new smb_node is created it will take its
 234  * own hold on the vnode.  The caller's hold therefore still belongs to, and
 235  * should be released by, the caller.


 470 {
 471         SMB_NODE_VALID(node);
 472 
 473         mutex_enter(&node->n_mutex);
 474         ASSERT(node->n_refcnt);
 475         DTRACE_PROBE1(smb_node_release, smb_node_t *, node);
 476         if (--node->n_refcnt == 0) {
 477                 switch (node->n_state) {
 478 
 479                 case SMB_NODE_STATE_AVAILABLE:
 480                         node->n_state = SMB_NODE_STATE_DESTROYING;
 481                         mutex_exit(&node->n_mutex);
 482 
 483                         smb_llist_enter(node->n_hash_bucket, RW_WRITER);
 484                         smb_llist_remove(node->n_hash_bucket, node);
 485                         smb_llist_exit(node->n_hash_bucket);
 486 
 487                         /*
 488                          * Check if the file was deleted
 489                          */
 490                         if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
 491                                 smb_node_delete_on_close(node);
 492                         }
 493 
 494                         if (node->n_dnode) {
 495                                 ASSERT(node->n_dnode->n_magic ==
 496                                     SMB_NODE_MAGIC);
 497                                 smb_node_release(node->n_dnode);
 498                         }
 499 
 500                         if (node->n_unode) {
 501                                 ASSERT(node->n_unode->n_magic ==
 502                                     SMB_NODE_MAGIC);
 503                                 smb_node_release(node->n_unode);
 504                         }
 505 
 506                         smb_node_free(node);
 507                         return;
 508 
 509                 default:
 510                         SMB_PANIC();
 511                 }
 512         }
 513         smb_node_audit(node);
 514         mutex_exit(&node->n_mutex);
 515 }
 516 
 517 void
 518 smb_node_delete_on_close(smb_node_t *node)
 519 {
 520         smb_node_t      *d_snode;
 521         int             rc = 0;
 522         uint32_t        flags = 0;
 523 
 524         d_snode = node->n_dnode;
 525 
 526         ASSERT((node->flags & NODE_FLAGS_DELETE_ON_CLOSE) != 0);
 527 
 528         node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE;
 529         node->flags |= NODE_FLAGS_DELETE_COMMITTED;
 530         flags = node->n_delete_on_close_flags;
 531         ASSERT(node->od_name != NULL);
 532 
 533         if (smb_node_is_dir(node))
 534                 rc = smb_fsop_rmdir(0, node->delete_on_close_cred,
 535                     d_snode, node->od_name, flags);
 536         else
 537                 rc = smb_fsop_remove(0, node->delete_on_close_cred,
 538                     d_snode, node->od_name, flags);
 539         crfree(node->delete_on_close_cred);
 540         node->delete_on_close_cred = NULL;
 541 
 542         if (rc != 0)
 543                 cmn_err(CE_WARN, "File %s could not be removed, rc=%d\n",
 544                     node->od_name, rc);
 545         DTRACE_PROBE2(smb_node_delete_on_close, int, rc, smb_node_t *, node);
 546 }
 547 
 548 /*
 549  * smb_node_rename()
 550  *
 551  */
 552 void
 553 smb_node_rename(
 554     smb_node_t  *from_dnode,
 555     smb_node_t  *ret_node,
 556     smb_node_t  *to_dnode,
 557     char        *to_name)
 558 {
 559         SMB_NODE_VALID(from_dnode);
 560         SMB_NODE_VALID(to_dnode);
 561         SMB_NODE_VALID(ret_node);


 582 
 583 /*
 584  * Find/create an SMB node for the root of this zone and store it
 585  * in *svrootp.  Also create nodes leading to this directory.
 586  */
 587 int
 588 smb_node_root_init(smb_server_t *sv, smb_node_t **svrootp)
 589 {
 590         zone_t          *zone = curzone;
 591         int             error;
 592 
 593         ASSERT(zone->zone_id == sv->sv_zid);
 594         if (smb_root_node == NULL)
 595                 return (ENOENT);
 596 
 597         /*
 598          * We're getting smb nodes below the zone root here,
 599          * so need to use kcred, not zone_kcred().
 600          */
 601         error = smb_pathname(NULL, zone->zone_rootpath, 0,
 602             smb_root_node, smb_root_node, NULL, svrootp, kcred, NULL);
 603 
 604         return (error);
 605 }
 606 
 607 /*
 608  * Helper function for smb_node_set_delete_on_close(). Assumes node is a dir.
 609  * Return 0 if this is an empty dir. Otherwise return a NT_STATUS code.
 610  * Unfortunately, to find out if a directory is empty, we have to read it
 611  * and check for anything other than "." or ".." in the readdir buf.
 612  */
 613 static uint32_t
 614 smb_rmdir_possible(smb_node_t *n)
 615 {
 616         ASSERT(n->vp->v_type == VDIR);
 617         char *buf;
 618         char *bufptr;
 619         struct dirent64 *dp;
 620         uint32_t status = NT_STATUS_SUCCESS;
 621         int bsize = SMB_ODIR_BUFSIZE;
 622         int eof = 0;
 623 
 624         buf = kmem_alloc(SMB_ODIR_BUFSIZE, KM_SLEEP);







 625 
 626         /* Flags zero: no edirent, no ABE wanted here */
 627         if (smb_vop_readdir(n->vp, 0, buf, &bsize, &eof, 0, zone_kcred())) {
 628                 status = NT_STATUS_INTERNAL_ERROR;
 629                 goto out;
 630         }
 631 
 632         bufptr = buf;
 633         while (bsize > 0) {
 634                 /* LINTED pointer alignment */
 635                 dp = (struct dirent64 *)bufptr;
 636 
 637                 bufptr += dp->d_reclen;
 638                 bsize  -= dp->d_reclen;
 639                 if (bsize < 0) {
 640                         /* partial record */
 641                         status = NT_STATUS_DIRECTORY_NOT_EMPTY;
 642                         break;
 643                 }
 644 
 645                 if (strcmp(dp->d_name, ".") != 0 &&
 646                     strcmp(dp->d_name, "..") != 0) {
 647                         status = NT_STATUS_DIRECTORY_NOT_EMPTY;
 648                         break;
 649                 }
 650         }
 651 
 652 out:
 653         kmem_free(buf, SMB_ODIR_BUFSIZE);
 654         return (status);
 655 }
 656 
 657 /*
 658  * When DeleteOnClose is set on an smb_node, the common open code will
 659  * reject subsequent open requests for the file. Observation of Windows
 660  * 2000 indicates that subsequent opens should be allowed (assuming
 661  * there would be no sharing violation) until the file is closed using
 662  * the fid on which the DeleteOnClose was requested.
 663  *
 664  * If there are multiple opens with delete-on-close create options,
 665  * whichever the first file handle is closed will trigger the node to be
 666  * marked as delete-on-close. The credentials of that ofile will be used
 667  * as the delete-on-close credentials of the node.
 668  *
 669  * Note that "read-only" tests have already happened before this call.
 670  */
 671 uint32_t
 672 smb_node_set_delete_on_close(smb_node_t *node, cred_t *cr, uint32_t flags)
 673 {

 674         uint32_t status;

 675 










 676         /*
 677          * If the directory is not empty we should fail setting del-on-close
 678          * with STATUS_DIRECTORY_NOT_EMPTY. see MS's
 679          * "File System Behavior Overview" doc section 4.3.2
 680          */
 681         if (smb_node_is_dir(node)) {
 682                 status = smb_rmdir_possible(node);
 683                 if (status != 0) {
 684                         return (status);
 685                 }
 686         }
 687 
 688         mutex_enter(&node->n_mutex);
 689         if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
 690                 /* It was already marked.  We're done. */
 691                 mutex_exit(&node->n_mutex);
 692                 return (NT_STATUS_SUCCESS);
 693         }
 694 
 695         crhold(cr);
 696         node->delete_on_close_cred = cr;
 697         node->n_delete_on_close_flags = flags;
 698         node->flags |= NODE_FLAGS_DELETE_ON_CLOSE;
 699         mutex_exit(&node->n_mutex);
 700 
 701         /*
 702          * Tell any change notify calls to close their handles
 703          * and get out of the way.  FILE_ACTION_DELETE_PENDING
 704          * is a special, internal-only action for this purpose.
 705          */
 706         smb_node_notify_change(node, FILE_ACTION_DELETE_PENDING, NULL);
 707 
 708         return (NT_STATUS_SUCCESS);
 709 }
 710 
 711 void
 712 smb_node_reset_delete_on_close(smb_node_t *node)
 713 {
 714         mutex_enter(&node->n_mutex);
 715         if (node->flags & NODE_FLAGS_DELETE_ON_CLOSE) {
 716                 node->flags &= ~NODE_FLAGS_DELETE_ON_CLOSE;
 717                 crfree(node->delete_on_close_cred);
 718                 node->delete_on_close_cred = NULL;
 719                 node->n_delete_on_close_flags = 0;
 720         }
 721         mutex_exit(&node->n_mutex);
 722 }
 723 
 724 /*
 725  * smb_node_open_check
 726  *


 734 smb_node_open_check(smb_node_t *node, uint32_t desired_access,
 735     uint32_t share_access)
 736 {
 737         smb_ofile_t *of;
 738         uint32_t status;
 739 
 740         SMB_NODE_VALID(node);
 741 
 742         smb_llist_enter(&node->n_ofile_list, RW_READER);
 743         of = smb_llist_head(&node->n_ofile_list);
 744         while (of) {
 745                 status = smb_ofile_open_check(of, desired_access, share_access);
 746 
 747                 switch (status) {
 748                 case NT_STATUS_INVALID_HANDLE:
 749                 case NT_STATUS_SUCCESS:
 750                         of = smb_llist_next(&node->n_ofile_list, of);
 751                         break;
 752                 default:
 753                         ASSERT(status == NT_STATUS_SHARING_VIOLATION);
 754                         DTRACE_PROBE3(conflict3,
 755                             smb_ofile_t, of,
 756                             uint32_t, desired_access,
 757                             uint32_t, share_access);
 758                         smb_llist_exit(&node->n_ofile_list);
 759                         return (status);
 760                 }
 761         }
 762 
 763         smb_llist_exit(&node->n_ofile_list);
 764         return (NT_STATUS_SUCCESS);
 765 }
 766 
 767 uint32_t
 768 smb_node_rename_check(smb_node_t *node)
 769 {
 770         smb_ofile_t     *of;
 771         uint32_t        status;
 772 
 773         SMB_NODE_VALID(node);
 774 
 775         /*
 776          * Intra-CIFS check
 777          */
 778         smb_llist_enter(&node->n_ofile_list, RW_READER);
 779         of = smb_llist_head(&node->n_ofile_list);
 780         while (of) {
 781                 status = smb_ofile_rename_check(of);
 782 
 783                 switch (status) {
 784                 case NT_STATUS_INVALID_HANDLE:
 785                 case NT_STATUS_SUCCESS:
 786                         of = smb_llist_next(&node->n_ofile_list, of);
 787                         break;
 788                 default:
 789                         ASSERT(status == NT_STATUS_SHARING_VIOLATION);
 790                         DTRACE_PROBE1(conflict1, smb_ofile_t, of);
 791                         smb_llist_exit(&node->n_ofile_list);
 792                         return (status);
 793                 }
 794         }
 795         smb_llist_exit(&node->n_ofile_list);
 796         return (NT_STATUS_SUCCESS);
 797 }
 798 
 799 uint32_t
 800 smb_node_delete_check(smb_node_t *node)
 801 {
 802         smb_ofile_t     *of;
 803         uint32_t        status;
 804 
 805         SMB_NODE_VALID(node);
 806 
 807         if (smb_node_is_dir(node))
 808                 return (NT_STATUS_SUCCESS);
 809 
 810         if (smb_node_is_reparse(node))
 811                 return (NT_STATUS_ACCESS_DENIED);
 812 
 813         /*
 814          * intra-CIFS check
 815          */
 816         smb_llist_enter(&node->n_ofile_list, RW_READER);
 817         of = smb_llist_head(&node->n_ofile_list);
 818         while (of) {
 819                 status = smb_ofile_delete_check(of);
 820 
 821                 switch (status) {
 822                 case NT_STATUS_INVALID_HANDLE:
 823                 case NT_STATUS_SUCCESS:
 824                         of = smb_llist_next(&node->n_ofile_list, of);
 825                         break;
 826                 default:
 827                         ASSERT(status == NT_STATUS_SHARING_VIOLATION);
 828                         DTRACE_PROBE1(conflict1, smb_ofile_t, of);
 829                         smb_llist_exit(&node->n_ofile_list);
 830                         return (status);
 831                 }
 832         }
 833         smb_llist_exit(&node->n_ofile_list);
 834         return (NT_STATUS_SUCCESS);
 835 }
 836 
 837 /*
 838  * smb_node_share_check
 839  *
 840  * Returns: TRUE    - ofiles have non-zero share access
 841  *          B_FALSE - ofile with share access NONE.
 842  */
 843 boolean_t
 844 smb_node_share_check(smb_node_t *node)
 845 {
 846         smb_ofile_t     *of;
 847         boolean_t       status = B_TRUE;
 848 
 849         SMB_NODE_VALID(node);
 850 
 851         smb_llist_enter(&node->n_ofile_list, RW_READER);
 852         of = smb_llist_head(&node->n_ofile_list);
 853         if (of)
 854                 status = smb_ofile_share_check(of);
 855         smb_llist_exit(&node->n_ofile_list);
 856 
 857         return (status);
 858 }
 859 
 860 /*
 861  * SMB Change Notification
 862  */
 863 
 864 void
 865 smb_node_fcn_subscribe(smb_node_t *node)
 866 {

 867 
 868         mutex_enter(&node->n_mutex);
 869         if (node->n_fcn_count == 0)
 870                 (void) smb_fem_fcn_install(node);
 871         node->n_fcn_count++;
 872         mutex_exit(&node->n_mutex);

 873 }
 874 
 875 void
 876 smb_node_fcn_unsubscribe(smb_node_t *node)
 877 {

 878 
 879         mutex_enter(&node->n_mutex);
 880         node->n_fcn_count--;
 881         if (node->n_fcn_count == 0)

 882                 smb_fem_fcn_uninstall(node);
 883         mutex_exit(&node->n_mutex);
 884 }
 885 
 886 void
 887 smb_node_notify_change(smb_node_t *node, uint_t action, const char *name)
 888 {
 889         smb_ofile_t     *of;
 890 
 891         SMB_NODE_VALID(node);
 892 
 893         smb_llist_enter(&node->n_ofile_list, RW_READER);
 894         of = smb_llist_head(&node->n_ofile_list);
 895         while (of) {
 896                 /*
 897                  * We'd rather deliver events only to ofiles that have
 898                  * subscribed.  There's no explicit synchronization with
 899                  * where this flag is set, but other actions cause this
 900                  * value to reach visibility soon enough for events to
 901                  * start arriving by the time we need them to start.
 902                  * Once nc_subscribed is set, it stays set for the
 903                  * life of the ofile.
 904                  */
 905                 if (of->f_notify.nc_subscribed)
 906                         smb_notify_ofile(of, action, name);
 907                 of = smb_llist_next(&node->n_ofile_list, of);
 908         }
 909         smb_llist_exit(&node->n_ofile_list);
 910 
 911         /*
 912          * After changes that add or remove a name,
 913          * we know the directory attributes changed,
 914          * and we can tell the immediate parent.






 915          */
 916         switch (action) {
 917         case FILE_ACTION_ADDED:
 918         case FILE_ACTION_REMOVED:
 919         case FILE_ACTION_RENAMED_NEW_NAME:
 920                 /*
 921                  * Note: FILE_ACTION_RENAMED_OLD_NAME is intentionally
 922                  * omitted, because it's always followed by another
 923                  * event with FILE_ACTION_RENAMED_NEW_NAME posted to
 924                  * the same directory, and we only need/want one.
 925                  */
 926                 if (node->n_dnode != NULL) {
 927                         smb_node_notify_change(node->n_dnode,
 928                             FILE_ACTION_MODIFIED, node->od_name);

 929                 }
 930                 break;
 931         }
 932 
 933         /*
 934          * If we wanted to support recursive notify events
 935          * (where a notify call on some directory receives
 936          * events from all objects below that directory),
 937          * we might deliver _SUBDIR_CHANGED to all our
 938          * parents, grandparents etc, here.  However, we
 939          * don't currently subscribe to changes on all the
 940          * child (and grandchild) objects that would be
 941          * needed to make that work. It's prohibitively
 942          * expensive to do that, and support for recursive
 943          * notify is optional anyway, so don't bother.
 944          */
 945 }
 946 
 947 /*
 948  * smb_node_start_crit()
 949  *
 950  * Enter critical region for share reservations.
 951  * See comments above smb_fsop_shrlock().
 952  */
 953 void
 954 smb_node_start_crit(smb_node_t *node, krw_t mode)
 955 {
 956         rw_enter(&node->n_lock, mode);
 957         nbl_start_crit(node->vp, mode);
 958 }
 959 
 960 /*
 961  * smb_node_end_crit()
 962  *
 963  * Exit critical region for share reservations.
 964  */


1144         VN_RELE(vp);
1145 
1146         if (rc != 0)
1147                 return (rc);
1148 
1149         /* append filename if necessary */
1150         if (!smb_node_is_dir(unode)) {
1151                 if (buf[strlen(buf) - 1] != '/')
1152                         (void) strlcat(buf, "/", buflen);
1153                 (void) strlcat(buf, unode->od_name, buflen);
1154         }
1155 
1156         /* append named stream name if necessary */
1157         if (SMB_IS_STREAM(node))
1158                 (void) strlcat(buf, node->od_name, buflen);
1159 
1160         return (rc);
1161 }
1162 
1163 /*
1164  * smb_node_getpath_nofail
1165  *
1166  * Same as smb_node_getpath, but try to reconstruct on failure,
1167  * and truncate from the beginning if we can't.
1168  */
1169 void
1170 smb_node_getpath_nofail(smb_node_t *node, vnode_t *rootvp, char *buf,
1171     uint32_t buflen)
1172 {
1173         int rc, len, addlen;
1174         vnode_t *vp;
1175         smb_node_t *unode, *dnode;
1176         cred_t *kcr = zone_kcred();
1177         boolean_t is_dir, is_stream;
1178 
1179         is_stream = (SMB_IS_STREAM(node) != NULL);
1180         unode = (is_stream) ? node->n_unode : node;
1181         is_dir = smb_node_is_dir(unode);
1182         dnode = (is_dir) ? unode : unode->n_dnode;
1183 
1184         /* find path to directory node */
1185         vp = dnode->vp;
1186         VN_HOLD(vp);
1187         if (rootvp) {
1188                 VN_HOLD(rootvp);
1189                 rc = vnodetopath(rootvp, vp, buf, buflen, kcr);
1190                 VN_RELE(rootvp);
1191         } else {
1192                 rc = vnodetopath(NULL, vp, buf, buflen, kcr);
1193         }
1194         VN_RELE(vp);
1195 
1196         /* On failure, reconstruct the path from the node_t's */
1197         if (rc != 0) {
1198                 smb_node_t *nodep = unode;
1199                 char *p = buf + buflen;
1200 
1201                 /* append named stream name if necessary */
1202                 if (is_stream) {
1203                         len = strlen(node->od_name) + 1;
1204                         ASSERT3U(buflen, >=, len);
1205                         p -= len;
1206                         (void) strcpy(p, node->od_name);
1207                 }
1208 
1209                 len = strlen(nodep->od_name) + 1;
1210                 p -= len;
1211                 while (nodep->n_dnode != NULL && nodep->vp != rootvp &&
1212                     p >= buf) {
1213                         (void) strcpy(p, nodep->od_name);
1214                         p[len - 1] = '/';
1215                         nodep = nodep->n_dnode;
1216                         len = strlen(nodep->od_name) + 1;
1217                         p -= len;
1218                 }
1219                 if (nodep->n_dnode != NULL && nodep->vp != rootvp) {
1220                         /* something went horribly wrong... */
1221 #ifdef DEBUG
1222                         cmn_err(CE_WARN,
1223                             "smb_node_getpath_nofail: buffer too small: "
1224                             "size %d", buflen);
1225 #else
1226                         cmn_err(CE_WARN,
1227                             "smb_node_getpath_nofail: couldn't get full path");
1228 #endif
1229                         p = buf;
1230                         *p = '*';
1231                 } else {
1232                         p += len - 1;
1233                         if (p >= buf)
1234                                 *p = '/';
1235                 }
1236 
1237                 buf[buflen - 1] = '\0';
1238                 (void) memmove(buf, p, strlen(p) + 1);
1239                 cmn_err(CE_NOTE,
1240                     "smb_node_getpath_nofail: vnodetopath failed, rc=%d", rc);
1241                 return;
1242         }
1243 
1244         len = strlen(buf) + 1;
1245 
1246         /* append filename if necessary */
1247         if (!is_dir) {
1248                 if (buf[len - 2] != '/' && strlcat(buf, "/", buflen) >= buflen)
1249                         goto trunc;
1250                 if (strlcat(buf, unode->od_name, buflen) >= buflen)
1251                         goto trunc;
1252         }
1253 
1254         /* append named stream name if necessary */
1255         if (!is_stream || strlcat(buf, node->od_name, buflen) < buflen)
1256                 return;
1257 
1258 trunc:
1259         buf[len - 1] = '\0';
1260         addlen = 0;
1261         /* append filename if necessary */
1262         if (!is_dir) {
1263                 if (buf[len - 2] != '/')
1264                         addlen++;
1265                 addlen += strlen(unode->od_name);
1266         }
1267 
1268         /* append named stream name if necessary */
1269         if (is_stream)
1270                 addlen += strlen(node->od_name);
1271 
1272         if ((buflen - len) < addlen) {
1273 #ifdef DEBUG
1274                 cmn_err(CE_WARN,
1275                     "smb_node_getpath_nofail: vnodetopath succeeded, "
1276                     "but buffer too small for filename");
1277 #else
1278                 cmn_err(CE_WARN,
1279                     "smb_node_getpath_nofail: couldn't get full path");
1280 #endif
1281                 addlen = addlen - (buflen - len);
1282                 (void) memmove(buf, buf + addlen, len - addlen);
1283                 buf[0] = '*';
1284         }
1285 
1286         /* append filename if necessary */
1287         if (!is_dir) {
1288                 if (buf[len - 2] != '/')
1289                         (void) strlcat(buf, "/", buflen);
1290                 (void) strlcat(buf, unode->od_name, buflen);
1291         }
1292 
1293         /* append named stream name if necessary */
1294         if (is_stream)
1295                 (void) strlcat(buf, node->od_name, buflen);
1296 }
1297 
1298 /*
1299  * smb_node_alloc
1300  */
1301 static smb_node_t *
1302 smb_node_alloc(
1303     char        *od_name,
1304     vnode_t     *vp,
1305     smb_llist_t *bucket,
1306     uint32_t    hashkey)
1307 {
1308         smb_node_t      *node;
1309         vnode_t         *root_vp;
1310 
1311         node = kmem_cache_alloc(smb_node_cache, KM_SLEEP);
1312 
1313         if (node->n_audit_buf != NULL)
1314                 node->n_audit_buf->anb_index = 0;
1315 
1316         node->flags = 0;
1317         VN_HOLD(vp);
1318         node->vp = vp;
1319         node->n_refcnt = 1;
1320         node->n_hash_bucket = bucket;
1321         node->n_hashkey = hashkey;

1322         node->n_open_count = 0;
1323         node->n_allocsz = 0;
1324         node->n_dnode = NULL;
1325         node->n_unode = NULL;
1326         node->delete_on_close_cred = NULL;
1327         node->n_delete_on_close_flags = 0;
1328         node->n_oplock.ol_fem = B_FALSE;



1329 
1330         (void) strlcpy(node->od_name, od_name, sizeof (node->od_name));
1331         if (strcmp(od_name, XATTR_DIR) == 0)
1332                 node->flags |= NODE_XATTR_DIR;
1333 
1334         if (VFS_ROOT(vp->v_vfsp, &root_vp) == 0) {
1335                 if (vp == root_vp)
1336                         node->flags |= NODE_FLAGS_VFSROOT;
1337                 VN_RELE(root_vp);
1338         }
1339 
1340         node->n_state = SMB_NODE_STATE_AVAILABLE;
1341         node->n_magic = SMB_NODE_MAGIC;
1342 
1343         return (node);
1344 }
1345 
1346 /*
1347  * smb_node_free
1348  */
1349 static void
1350 smb_node_free(smb_node_t *node)
1351 {
1352         SMB_NODE_VALID(node);
1353 
1354         node->n_magic = 0;
1355         VERIFY(!list_link_active(&node->n_lnd));
1356         VERIFY(node->n_lock_list.ll_count == 0);
1357         VERIFY(node->n_wlock_list.ll_count == 0);
1358         VERIFY(node->n_ofile_list.ll_count == 0);


1359         VERIFY(node->n_oplock.ol_fem == B_FALSE);
1360         VERIFY(MUTEX_NOT_HELD(&node->n_mutex));
1361         VERIFY(!RW_LOCK_HELD(&node->n_lock));
1362         VN_RELE(node->vp);
1363         kmem_cache_free(smb_node_cache, node);
1364 }
1365 
1366 /*
1367  * smb_node_constructor
1368  */
1369 static int
1370 smb_node_constructor(void *buf, void *un, int kmflags)
1371 {
1372         _NOTE(ARGUNUSED(kmflags, un))
1373 
1374         smb_node_t      *node = (smb_node_t *)buf;
1375 
1376         bzero(node, sizeof (smb_node_t));
1377 
1378         smb_llist_constructor(&node->n_ofile_list, sizeof (smb_ofile_t),
1379             offsetof(smb_ofile_t, f_node_lnd));
1380         smb_llist_constructor(&node->n_lock_list, sizeof (smb_lock_t),
1381             offsetof(smb_lock_t, l_lnd));
1382         smb_llist_constructor(&node->n_wlock_list, sizeof (smb_lock_t),
1383             offsetof(smb_lock_t, l_lnd));


1384         mutex_init(&node->n_oplock.ol_mutex, NULL, MUTEX_DEFAULT, NULL);
1385         cv_init(&node->n_oplock.WaitingOpenCV, NULL, CV_DEFAULT, NULL);

1386         rw_init(&node->n_lock, NULL, RW_DEFAULT, NULL);
1387         mutex_init(&node->n_mutex, NULL, MUTEX_DEFAULT, NULL);
1388         smb_node_create_audit_buf(node, kmflags);
1389         return (0);
1390 }
1391 
1392 /*
1393  * smb_node_destructor
1394  */
1395 static void
1396 smb_node_destructor(void *buf, void *un)
1397 {
1398         _NOTE(ARGUNUSED(un))
1399 
1400         smb_node_t      *node = (smb_node_t *)buf;
1401 
1402         smb_node_destroy_audit_buf(node);
1403         mutex_destroy(&node->n_mutex);
1404         rw_destroy(&node->n_lock);
1405         cv_destroy(&node->n_oplock.WaitingOpenCV);
1406         mutex_destroy(&node->n_oplock.ol_mutex);


1407         smb_llist_destructor(&node->n_lock_list);
1408         smb_llist_destructor(&node->n_wlock_list);
1409         smb_llist_destructor(&node->n_ofile_list);

1410 }
1411 
1412 /*
1413  * smb_node_create_audit_buf
1414  */
1415 static void
1416 smb_node_create_audit_buf(smb_node_t *node, int kmflags)
1417 {
1418         smb_audit_buf_node_t    *abn;
1419 
1420         if (smb_audit_flags & SMB_AUDIT_NODE) {
1421                 abn = kmem_zalloc(sizeof (smb_audit_buf_node_t), kmflags);
1422                 abn->anb_max_index = SMB_AUDIT_BUF_MAX_REC - 1;
1423                 node->n_audit_buf = abn;
1424         }
1425 }
1426 
1427 /*
1428  * smb_node_destroy_audit_buf
1429  */


1515 }
1516 
1517 boolean_t
1518 smb_node_is_vfsroot(smb_node_t *node)
1519 {
1520         SMB_NODE_VALID(node);
1521         return ((node->flags & NODE_FLAGS_VFSROOT) == NODE_FLAGS_VFSROOT);
1522 }
1523 
1524 boolean_t
1525 smb_node_is_system(smb_node_t *node)
1526 {
1527         SMB_NODE_VALID(node);
1528         return ((node->flags & NODE_FLAGS_SYSTEM) == NODE_FLAGS_SYSTEM);
1529 }
1530 
1531 /*
1532  * smb_node_file_is_readonly
1533  *
1534  * Checks if the file (which node represents) is marked readonly
1535  * in the filesystem.  Note that there may be handles open with
1536  * modify rights, and those continue to allow access even after
1537  * the DOS read-only flag has been set in the file system.
1538  */
1539 boolean_t
1540 smb_node_file_is_readonly(smb_node_t *node)
1541 {
1542         smb_attr_t attr;
1543 
1544         if (node == NULL)
1545                 return (B_FALSE);       /* pipes */
1546 



1547         bzero(&attr, sizeof (smb_attr_t));
1548         attr.sa_mask = SMB_AT_DOSATTR;
1549         (void) smb_fsop_getattr(NULL, zone_kcred(), node, &attr);
1550         return ((attr.sa_dosattr & FILE_ATTRIBUTE_READONLY) != 0);
1551 }
1552 
1553 /*
1554  * smb_node_setattr
1555  *
1556  * The sr may be NULL, for example when closing an ofile.
1557  * The ofile may be NULL, for example when a client request
1558  * specifies the file by pathname.
1559  *
1560  * Returns: errno
1561  *
1562  * Timestamps
1563  *
1564  * Windows and Unix have different models for timestamp updates.
1565  * [MS-FSA 2.1.5.14 Server Requests Setting of File Information]
1566  *


1592  * write access.  (because access check happens at open)
1593  * If we were to set the read-only bit directly, we would
1594  * cause errors in subsequent writes on any of our open
1595  * (and writable) file handles.  So here too, we have to
1596  * simulate the Windows behavior.  We keep the read-only
1597  * bit "pending" in the smb_node (so it will be visible in
1598  * any new opens of the file) and apply it on close.
1599  *
1600  * File allocation size is also simulated, and not persistent.
1601  * When the file allocation size is set it is first rounded up
1602  * to block size. If the file size is smaller than the allocation
1603  * size the file is truncated by setting the filesize to allocsz.
1604  */
1605 int
1606 smb_node_setattr(smb_request_t *sr, smb_node_t *node,
1607     cred_t *cr, smb_ofile_t *of, smb_attr_t *attr)
1608 {
1609         int rc;
1610         uint_t times_mask;
1611         smb_attr_t tmp_attr;
1612         smb_node_t *unnamed_node;
1613 
1614         SMB_NODE_VALID(node);
1615 
1616         /* set attributes specified in attr */
1617         if (attr->sa_mask == 0)
1618                 return (0);  /* nothing to do (caller bug?) */
1619 
1620         /*
1621          * Allocation size and EOF position interact.
1622          * We don't persistently store the allocation size
1623          * but make it look like we do while there are opens.
1624          * Note: We update the caller's attr in the cases
1625          * where they're setting only one of allocsz|size.
1626          */
1627         switch (attr->sa_mask & (SMB_AT_ALLOCSZ | SMB_AT_SIZE)) {
1628 
1629         case SMB_AT_ALLOCSZ:
1630                 /*
1631                  * Setting the allocation size but not EOF position.
1632                  * Get the current EOF in tmp_attr and (if necessary)


1693                 SMB_OFILE_VALID(of);
1694                 mutex_enter(&of->f_mutex);
1695                 pa = &of->f_pending_attr;
1696 
1697                 pa->sa_mask |= times_mask;
1698 
1699                 if (times_mask & SMB_AT_ATIME)
1700                         pa->sa_vattr.va_atime =
1701                             attr->sa_vattr.va_atime;
1702                 if (times_mask & SMB_AT_MTIME)
1703                         pa->sa_vattr.va_mtime =
1704                             attr->sa_vattr.va_mtime;
1705                 if (times_mask & SMB_AT_CTIME)
1706                         pa->sa_vattr.va_ctime =
1707                             attr->sa_vattr.va_ctime;
1708                 if (times_mask & SMB_AT_CRTIME)
1709                         pa->sa_crtime =
1710                             attr->sa_crtime;
1711 
1712                 mutex_exit(&of->f_mutex);
1713 
1714                 /*
1715                  * The f_pending_attr times are reapplied in
1716                  * smb_ofile_close().
1717                  */

1718 
1719                 /*
1720                  * If this change is comming directly from a client
1721                  * (sr != NULL) and it's a persistent handle, save
1722                  * the "sticky times" in the handle.

1723                  */
1724                 if (sr != NULL && of->dh_persist) {
1725                         smb2_dh_update_times(sr, of, attr);













1726                 }
1727         }
1728 
1729         if ((attr->sa_mask & SMB_AT_ALLOCSZ) != 0) {
1730                 mutex_enter(&node->n_mutex);
1731                 /*
1732                  * Simulate n_allocsz persistence only while
1733                  * there are opens.  See smb_node_getattr
1734                  */
1735                 if (node->n_open_count != 0)

1736                         node->n_allocsz = attr->sa_allocsz;
1737                 mutex_exit(&node->n_mutex);
1738         }
1739 
1740         rc = smb_fsop_setattr(sr, cr, node, attr);
1741         if (rc != 0)
1742                 return (rc);
1743 
1744         if (node->n_dnode != NULL) {
1745                 smb_node_notify_change(node->n_dnode,
1746                     FILE_ACTION_MODIFIED, node->od_name);
1747         }
1748 
1749         if ((unnamed_node = SMB_IS_STREAM(node)) != NULL) {
1750                 ASSERT(unnamed_node->n_magic == SMB_NODE_MAGIC);
1751                 ASSERT(unnamed_node->n_state != SMB_NODE_STATE_DESTROYING);
1752                 smb_node_notify_change(node->n_dnode,
1753                     FILE_ACTION_MODIFIED_STREAM, node->od_name);
1754         }
1755 
1756         return (0);
1757 }
1758 
1759 /*
1760  * smb_node_getattr
1761  *
1762  * Get attributes from the file system and apply any smb-specific
1763  * overrides for size, dos attributes and timestamps
1764  *
1765  * When node->n_pending_readonly is set on a node, pretend that
1766  * we've already set this node readonly at the filesystem level.
1767  * We can't actually do that until all writable handles are closed
1768  * or those writable handles would suddenly loose their access.
1769  *
1770  * Returns: errno
1771  */
1772 int
1773 smb_node_getattr(smb_request_t *sr, smb_node_t *node, cred_t *cr,
1774     smb_ofile_t *of, smb_attr_t *attr)
1775 {
1776         int rc;
1777         uint_t want_mask, pend_mask;
1778         boolean_t isdir;
1779 
1780         SMB_NODE_VALID(node);
1781 
1782         /* Deal with some interdependencies */
1783         if (attr->sa_mask & SMB_AT_ALLOCSZ)
1784                 attr->sa_mask |= SMB_AT_SIZE;
1785         if (attr->sa_mask & SMB_AT_DOSATTR)
1786                 attr->sa_mask |= SMB_AT_TYPE;
1787 
1788         rc = smb_fsop_getattr(sr, cr, node, attr);
1789         if (rc != 0)
1790                 return (rc);
1791 
1792         isdir = smb_node_is_dir(node);
1793 
1794         mutex_enter(&node->n_mutex);
1795 










1796         if (attr->sa_mask & SMB_AT_DOSATTR) {




1797                 if (attr->sa_dosattr == 0) {
1798                         attr->sa_dosattr = (isdir) ?
1799                             FILE_ATTRIBUTE_DIRECTORY:
1800                             FILE_ATTRIBUTE_NORMAL;
1801                 }
1802         }
1803 
1804         /*
1805          * Also fix-up sa_allocsz, which is not persistent.
1806          * When there are no open files, allocsz is faked.
1807          * While there are open files, we pretend we have a
1808          * persistent allocation size in n_allocsz, and
1809          * keep that up-to-date here, increasing it when
1810          * we see the file size grow past it.
1811          */
1812         if (attr->sa_mask & SMB_AT_ALLOCSZ) {
1813                 if (isdir) {
1814                         attr->sa_allocsz = 0;
1815                 } else if (node->n_open_count == 0) {
1816                         attr->sa_allocsz =