Print this page
NEX-19152 MacOS HighSierra Finder crashes...
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-19025 CIFS gets confused with filenames containing enhanced Unicode
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
and: (fix build, check-rtime)
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-4820 intended nbmand locking functionality is confused
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-17289 Minimal SMB 3.0.2 support
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-16157 Removal of "Read Attributes" prevents reading directory over SMB
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-16157 Removal of "Read Attributes" prevents reading directory over SMB
Reviewed by: Gordon Ross <gordon.ross@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-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-15069 smtorture smb2.create.blob is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-6116 Failures in smbtorture raw.open (2)
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-6276 SMB sparse file support
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-6096 Enable compile warnings re. parentheses in smbsrv
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Jean McCormack <jean.mccormack@nexenta.com>
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 (data structure changes)
Many things move to the smb_server_t object, and
many functions gain an sv arg (which server).
re #7815 SMB server delivers old modification time...
        
*** 18,28 ****
   *
   * CDDL HEADER END
   */
  /*
   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
!  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
   */
  
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <sys/uio.h>
--- 18,28 ----
   *
   * CDDL HEADER END
   */
  /*
   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
!  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
   */
  
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <sys/uio.h>
*** 248,263 ****
   * XXX - Extended attributes support in the file system assumed.
   * This is needed for full NT Streams functionality.
   */
  
  int
! smb_vop_read(vnode_t *vp, uio_t *uiop, cred_t *cr)
  {
          int error;
  
          (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, &smb_ct);
!         error = VOP_READ(vp, uiop, 0, cr, &smb_ct);
          VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &smb_ct);
          return (error);
  }
  
  int
--- 248,263 ----
   * XXX - Extended attributes support in the file system assumed.
   * This is needed for full NT Streams functionality.
   */
  
  int
! smb_vop_read(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr)
  {
          int error;
  
          (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, &smb_ct);
!         error = VOP_READ(vp, uiop, ioflag, cr, &smb_ct);
          VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &smb_ct);
          return (error);
  }
  
  int
*** 277,286 ****
--- 277,303 ----
          *lcount -= uiop->uio_resid;
  
          return (error);
  }
  
+ int
+ smb_vop_ioctl(vnode_t *vp, int cmd, void *arg, cred_t *cr)
+ {
+         int error, rval = 0;
+         uint_t flags = 0;
+ 
+ #ifdef  FKIOCTL
+         flags |= FKIOCTL;
+ #endif
+         error = VOP_IOCTL(vp, cmd, (intptr_t)arg, (int)flags, cr,
+             &rval, &smb_ct);
+         if (error != 0)
+                 rval = error;
+ 
+         return (rval);
+ }
+ 
  /*
   * smb_vop_getattr()
   *
   * smb_fsop_getattr()/smb_vop_getattr() should always be called from the CIFS
   * service (instead of calling VOP_GETATTR directly) to retrieve attributes
*** 527,550 ****
          int error = 0;
  
          if (mode == 0)
                  return (0);
  
!         if ((flags == V_ACE_MASK) && (mode & ACE_DELETE)) {
!                 if (dir_vp) {
                          error = VOP_ACCESS(dir_vp, ACE_DELETE_CHILD, flags,
                              cr, NULL);
  
                          if (error == 0)
                                  mode &= ~ACE_DELETE;
                  }
          }
  
!         if (mode) {
                  error = VOP_ACCESS(vp, mode, flags, cr, NULL);
-         }
  
          return (error);
  }
  
  /*
   * smb_vop_lookup
--- 544,582 ----
          int error = 0;
  
          if (mode == 0)
                  return (0);
  
!         error = VOP_ACCESS(vp, mode, flags, cr, NULL);
! 
!         if (error == 0)
!                 return (0);
! 
!         if ((mode & (ACE_DELETE|ACE_READ_ATTRIBUTES)) == 0 ||
!             flags != V_ACE_MASK || dir_vp == NULL)
!                 return (error);
! 
!         smb_audit_save();
!         if ((mode & ACE_DELETE) != 0) {
                  error = VOP_ACCESS(dir_vp, ACE_DELETE_CHILD, flags,
                      cr, NULL);
  
                  if (error == 0)
                          mode &= ~ACE_DELETE;
          }
+         if ((mode & ACE_READ_ATTRIBUTES) != 0) {
+                 error = VOP_ACCESS(dir_vp, ACE_LIST_DIRECTORY, flags,
+                     cr, NULL);
+ 
+                 if (error == 0)
+                         mode &= ~ACE_READ_ATTRIBUTES;
          }
  
!         if (mode != 0)
                  error = VOP_ACCESS(vp, mode, flags, cr, NULL);
  
+         smb_audit_load();
          return (error);
  }
  
  /*
   * smb_vop_lookup
*** 618,635 ****
          if (flags & SMB_CATIA)
                  np = smb_vop_catia_v5tov4(name, namebuf, sizeof (namebuf));
  
          pn_alloc(&rpn);
  
          error = VOP_LOOKUP(dvp, np, vpp, NULL, option_flags, NULL, cr,
              &smb_ct, direntflags, &rpn);
  
          if (error == 0) {
                  if (od_name) {
                          bzero(od_name, MAXNAMELEN);
!                         np = (option_flags == FIGNORECASE) ? rpn.pn_buf : name;
! 
                          if (flags & SMB_CATIA)
                                  smb_vop_catia_v4tov5(np, od_name, MAXNAMELEN);
                          else
                                  (void) strlcpy(od_name, np, MAXNAMELEN);
                  }
--- 650,676 ----
          if (flags & SMB_CATIA)
                  np = smb_vop_catia_v5tov4(name, namebuf, sizeof (namebuf));
  
          pn_alloc(&rpn);
  
+         /*
+          * Easier to not have junk in rpn, as not every FS type
+          * will necessarily fill that in for us.
+          */
+         bzero(rpn.pn_buf, rpn.pn_bufsize);
+ 
          error = VOP_LOOKUP(dvp, np, vpp, NULL, option_flags, NULL, cr,
              &smb_ct, direntflags, &rpn);
  
          if (error == 0) {
                  if (od_name) {
                          bzero(od_name, MAXNAMELEN);
!                         if ((option_flags & FIGNORECASE) != 0 &&
!                             rpn.pn_buf[0] != '\0')
!                                 np = rpn.pn_buf;
!                         else
!                                 np = name;
                          if (flags & SMB_CATIA)
                                  smb_vop_catia_v4tov5(np, od_name, MAXNAMELEN);
                          else
                                  (void) strlcpy(od_name, np, MAXNAMELEN);
                  }
*** 676,685 ****
--- 717,740 ----
          }
  
          error = VOP_CREATE(dvp, np, vap, EXCL, attr->sa_vattr.va_mode,
              vpp, cr, option_flags, &smb_ct, vsap);
  
+         /*
+          * One could argue that filesystems should obey the size
+          * if specified in the create attributes.  Unfortunately,
+          * they only appear to let you truncate the size to zero.
+          * SMB needs to set a non-zero size, so work-around.
+          */
+         if (error == 0 && *vpp != NULL &&
+             (vap->va_mask & AT_SIZE) != 0 &&
+             vap->va_size > 0) {
+                 vattr_t ta = *vap;
+                 ta.va_mask = AT_SIZE;
+                 (void) VOP_SETATTR(*vpp, &ta, 0, cr, &smb_ct);
+         }
+ 
          return (error);
  }
  
  int
  smb_vop_remove(vnode_t *dvp, char *name, int flags, cred_t *cr)
*** 968,978 ****
          struct iovec aiov;
  
          if (vp->v_type != VDIR)
                  return (ENOTDIR);
  
!         if (vfs_has_feature(vp->v_vfsp, VFSFT_DIRENTFLAGS)) {
                  flags |= V_RDDIR_ENTFLAGS;
                  rdirent_size = sizeof (edirent_t);
          } else {
                  rdirent_size = sizeof (dirent64_t);
          }
--- 1023,1034 ----
          struct iovec aiov;
  
          if (vp->v_type != VDIR)
                  return (ENOTDIR);
  
!         if ((rddir_flag & SMB_EDIRENT) != 0 &&
!             vfs_has_feature(vp->v_vfsp, VFSFT_DIRENTFLAGS)) {
                  flags |= V_RDDIR_ENTFLAGS;
                  rdirent_size = sizeof (edirent_t);
          } else {
                  rdirent_size = sizeof (dirent64_t);
          }
*** 1216,1226 ****
  
          default:
                  return (EINVAL);
          }
  
!         if (error = VOP_GETSECATTR(vp, &vsecattr, flags, cr, &smb_ct))
                  return (error);
  
          *aclp = smb_fsacl_from_vsa(&vsecattr, acl_type);
          if (vp->v_type == VDIR)
                  (*aclp)->acl_flags |= ACL_IS_DIR;
--- 1272,1282 ----
  
          default:
                  return (EINVAL);
          }
  
!         if ((error = VOP_GETSECATTR(vp, &vsecattr, flags, cr, &smb_ct)) != 0)
                  return (error);
  
          *aclp = smb_fsacl_from_vsa(&vsecattr, acl_type);
          if (vp->v_type == VDIR)
                  (*aclp)->acl_flags |= ACL_IS_DIR;
*** 1446,1461 ****
          shr_own.sl_pid = shr.s_pid;
  
          return (VOP_SHRLOCK(vp, F_UNSHARE, &shr, 0, cr, NULL));
  }
  
  int
  smb_vop_frlock(vnode_t *vp, cred_t *cr, int flag, flock64_t *bf)
  {
-         int cmd = nbl_need_check(vp) ? F_SETLK_NBMAND : F_SETLK;
          flk_callback_t flk_cb;
  
          flk_init_callback(&flk_cb, smb_lock_frlock_callback, NULL);
  
          return (VOP_FRLOCK(vp, cmd, bf, flag, 0, &flk_cb, cr, &smb_ct));
  }
  
--- 1502,1537 ----
          shr_own.sl_pid = shr.s_pid;
  
          return (VOP_SHRLOCK(vp, F_UNSHARE, &shr, 0, cr, NULL));
  }
  
+ /*
+  * Note about mandatory vs advisory locks:
+  *
+  * The SMB server really should always request mandatory locks, and
+  * if the file system does not support them, the SMB server should
+  * just tell the client it could not get the lock. If we were to
+  * tell the SMB client "you got the lock" when what they really
+  * got was only an advisory lock, we would be lying to the client
+  * about their having exclusive access to the locked range, which
+  * could easily lead to data corruption.  If someone really wants
+  * the (dangerous) behavior they can set: smb_allow_advisory_locks
+  */
  int
  smb_vop_frlock(vnode_t *vp, cred_t *cr, int flag, flock64_t *bf)
  {
          flk_callback_t flk_cb;
+         int cmd = F_SETLK_NBMAND;
  
+         if (smb_allow_advisory_locks != 0 && !nbl_need_check(vp)) {
+                 /*
+                  * The file system does not support nbmand, and
+                  * smb_allow_advisory_locks is enabled. (danger!)
+                  */
+                 cmd = F_SETLK;
+         }
+ 
          flk_init_callback(&flk_cb, smb_lock_frlock_callback, NULL);
  
          return (VOP_FRLOCK(vp, cmd, bf, flag, 0, &flk_cb, cr, &smb_ct));
  }
  
*** 1529,1539 ****
  char *
  smb_vop_catia_v5tov4(char *name, char *buf, int buflen)
  {
          int v4_idx, numbytes, inc;
          int space_left = buflen - 1; /* one byte reserved for null */
!         smb_wchar_t wc;
          char mbstring[MTS_MB_CHAR_MAX];
          char *p, *src = name, *dst = buf;
  
          ASSERT(name);
          ASSERT(buf);
--- 1605,1615 ----
  char *
  smb_vop_catia_v5tov4(char *name, char *buf, int buflen)
  {
          int v4_idx, numbytes, inc;
          int space_left = buflen - 1; /* one byte reserved for null */
!         uint32_t wc;
          char mbstring[MTS_MB_CHAR_MAX];
          char *p, *src = name, *dst = buf;
  
          ASSERT(name);
          ASSERT(buf);
*** 1586,1596 ****
  void
  smb_vop_catia_v4tov5(char *name, char *buf, int buflen)
  {
          int v5_idx, numbytes;
          int space_left = buflen - 1; /* one byte reserved for null */
!         smb_wchar_t wc;
          char mbstring[MTS_MB_CHAR_MAX];
          char *src = name, *dst = buf;
  
          ASSERT(name);
          ASSERT(buf);
--- 1662,1672 ----
  void
  smb_vop_catia_v4tov5(char *name, char *buf, int buflen)
  {
          int v5_idx, numbytes;
          int space_left = buflen - 1; /* one byte reserved for null */
!         uint32_t wc;
          char mbstring[MTS_MB_CHAR_MAX];
          char *src = name, *dst = buf;
  
          ASSERT(name);
          ASSERT(buf);