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

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/smbsrv/smb_vops.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb_vops.c
↓ open down ↓ 12 lines elided ↑ open up ↑
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23      - * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
       23 + * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  24   24   */
  25   25  
  26   26  #include <sys/types.h>
  27   27  #include <sys/stat.h>
  28   28  #include <sys/uio.h>
  29   29  #include <sys/statvfs.h>
  30   30  #include <sys/vnode.h>
  31   31  #include <sys/thread.h>
  32   32  #include <sys/pathname.h>
  33   33  #include <sys/cred.h>
↓ open down ↓ 209 lines elided ↑ open up ↑
 243  243   * (Higher-level CIFS service code should never skip the smb_fsop_* layer
 244  244   * to call smb_vop_* layer functions directly.)
 245  245   */
 246  246  
 247  247  /*
 248  248   * XXX - Extended attributes support in the file system assumed.
 249  249   * This is needed for full NT Streams functionality.
 250  250   */
 251  251  
 252  252  int
 253      -smb_vop_read(vnode_t *vp, uio_t *uiop, cred_t *cr)
      253 +smb_vop_read(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr)
 254  254  {
 255  255          int error;
 256  256  
 257  257          (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, &smb_ct);
 258      -        error = VOP_READ(vp, uiop, 0, cr, &smb_ct);
      258 +        error = VOP_READ(vp, uiop, ioflag, cr, &smb_ct);
 259  259          VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &smb_ct);
 260  260          return (error);
 261  261  }
 262  262  
 263  263  int
 264  264  smb_vop_write(vnode_t *vp, uio_t *uiop, int ioflag, uint32_t *lcount,
 265  265      cred_t *cr)
 266  266  {
 267  267          int error;
 268  268  
↓ open down ↓ 3 lines elided ↑ open up ↑
 272  272  
 273  273          (void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, &smb_ct);
 274  274          error = VOP_WRITE(vp, uiop, ioflag, cr, &smb_ct);
 275  275          VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, &smb_ct);
 276  276  
 277  277          *lcount -= uiop->uio_resid;
 278  278  
 279  279          return (error);
 280  280  }
 281  281  
      282 +int
      283 +smb_vop_ioctl(vnode_t *vp, int cmd, void *arg, cred_t *cr)
      284 +{
      285 +        int error, rval = 0;
      286 +        uint_t flags = 0;
      287 +
      288 +#ifdef  FKIOCTL
      289 +        flags |= FKIOCTL;
      290 +#endif
      291 +        error = VOP_IOCTL(vp, cmd, (intptr_t)arg, (int)flags, cr,
      292 +            &rval, &smb_ct);
      293 +        if (error != 0)
      294 +                rval = error;
      295 +
      296 +        return (rval);
      297 +}
      298 +
 282  299  /*
 283  300   * smb_vop_getattr()
 284  301   *
 285  302   * smb_fsop_getattr()/smb_vop_getattr() should always be called from the CIFS
 286  303   * service (instead of calling VOP_GETATTR directly) to retrieve attributes
 287  304   * due to special processing needed for streams files.
 288  305   *
 289  306   * All attributes are retrieved.
 290  307   *
 291  308   * When vp denotes a named stream, then unnamed_vp should be passed in (denoting
↓ open down ↓ 202 lines elided ↑ open up ↑
 494  511                  attr->sa_vattr.va_mask = AT_SIZE;
 495  512                  error = VOP_SETATTR(vp, &attr->sa_vattr, flags,
 496  513                      zone_kcred(), &smb_ct);
 497  514          }
 498  515  
 499  516          return (error);
 500  517  }
 501  518  
 502  519  int
 503  520  smb_vop_space(vnode_t *vp, int cmd, flock64_t *bfp, int flags,
 504      -        offset_t offset, cred_t *cr)
      521 +    offset_t offset, cred_t *cr)
 505  522  {
 506  523          int error;
 507  524  
 508  525          error = VOP_SPACE(vp, cmd, bfp, flags, offset, cr, &smb_ct);
 509  526  
 510  527          return (error);
 511  528  }
 512  529  
 513  530  /*
 514  531   * smb_vop_access
↓ open down ↓ 7 lines elided ↑ open up ↑
 522  539   * permissions.
 523  540   */
 524  541  int
 525  542  smb_vop_access(vnode_t *vp, int mode, int flags, vnode_t *dir_vp, cred_t *cr)
 526  543  {
 527  544          int error = 0;
 528  545  
 529  546          if (mode == 0)
 530  547                  return (0);
 531  548  
 532      -        if ((flags == V_ACE_MASK) && (mode & ACE_DELETE)) {
 533      -                if (dir_vp) {
 534      -                        error = VOP_ACCESS(dir_vp, ACE_DELETE_CHILD, flags,
 535      -                            cr, NULL);
      549 +        error = VOP_ACCESS(vp, mode, flags, cr, NULL);
 536  550  
 537      -                        if (error == 0)
 538      -                                mode &= ~ACE_DELETE;
 539      -                }
      551 +        if (error == 0)
      552 +                return (0);
      553 +
      554 +        if ((mode & (ACE_DELETE|ACE_READ_ATTRIBUTES)) == 0 ||
      555 +            flags != V_ACE_MASK || dir_vp == NULL)
      556 +                return (error);
      557 +
      558 +        smb_audit_save();
      559 +        if ((mode & ACE_DELETE) != 0) {
      560 +                error = VOP_ACCESS(dir_vp, ACE_DELETE_CHILD, flags,
      561 +                    cr, NULL);
      562 +
      563 +                if (error == 0)
      564 +                        mode &= ~ACE_DELETE;
 540  565          }
      566 +        if ((mode & ACE_READ_ATTRIBUTES) != 0) {
      567 +                error = VOP_ACCESS(dir_vp, ACE_LIST_DIRECTORY, flags,
      568 +                    cr, NULL);
 541  569  
 542      -        if (mode) {
 543      -                error = VOP_ACCESS(vp, mode, flags, cr, NULL);
      570 +                if (error == 0)
      571 +                        mode &= ~ACE_READ_ATTRIBUTES;
 544  572          }
 545  573  
      574 +        if (mode != 0)
      575 +                error = VOP_ACCESS(vp, mode, flags, cr, NULL);
      576 +
      577 +        smb_audit_load();
 546  578          return (error);
 547  579  }
 548  580  
 549  581  /*
 550  582   * smb_vop_lookup
 551  583   *
 552  584   * dvp:         directory vnode (in)
 553  585   * name:        name of file to be looked up (in)
 554  586   * vpp:         looked-up vnode (out)
 555  587   * od_name:     on-disk name of file (out).
 556  588   *              This parameter is optional.  If a pointer is passed in, it
 557      - *              must be allocated with MAXNAMELEN bytes
      589 + *              must be allocated with MAXNAMELEN bytes
 558  590   * rootvp:      vnode of the tree root (in)
 559  591   *              This parameter is always passed in non-NULL except at the time
 560  592   *              of share set up.
 561  593   * direntflags: dirent flags returned from VOP_LOOKUP
 562  594   */
 563  595  int
 564  596  smb_vop_lookup(
 565  597      vnode_t             *dvp,
 566  598      char                *name,
 567  599      vnode_t             **vpp,
↓ open down ↓ 45 lines elided ↑ open up ↑
 613  645          }
 614  646  
 615  647          if (flags & SMB_IGNORE_CASE)
 616  648                  option_flags = FIGNORECASE;
 617  649  
 618  650          if (flags & SMB_CATIA)
 619  651                  np = smb_vop_catia_v5tov4(name, namebuf, sizeof (namebuf));
 620  652  
 621  653          pn_alloc(&rpn);
 622  654  
      655 +        /*
      656 +         * Easier to not have junk in rpn, as not every FS type
      657 +         * will necessarily fill that in for us.
      658 +         */
      659 +        bzero(rpn.pn_buf, rpn.pn_bufsize);
      660 +
 623  661          error = VOP_LOOKUP(dvp, np, vpp, NULL, option_flags, NULL, cr,
 624  662              &smb_ct, direntflags, &rpn);
 625  663  
 626  664          if (error == 0) {
 627  665                  if (od_name) {
 628  666                          bzero(od_name, MAXNAMELEN);
 629      -                        np = (option_flags == FIGNORECASE) ? rpn.pn_buf : name;
 630      -
      667 +                        if ((option_flags & FIGNORECASE) != 0 &&
      668 +                            rpn.pn_buf[0] != '\0')
      669 +                                np = rpn.pn_buf;
      670 +                        else
      671 +                                np = name;
 631  672                          if (flags & SMB_CATIA)
 632  673                                  smb_vop_catia_v4tov5(np, od_name, MAXNAMELEN);
 633  674                          else
 634  675                                  (void) strlcpy(od_name, np, MAXNAMELEN);
 635  676                  }
 636  677  
 637  678                  if (attr != NULL) {
 638  679                          attr->sa_mask = SMB_AT_ALL;
 639  680                          (void) smb_vop_getattr(*vpp, NULL, attr, 0,
 640  681                              zone_kcred());
↓ open down ↓ 30 lines elided ↑ open up ↑
 671  712  
 672  713          if (flags & SMB_CATIA) {
 673  714                  np = smb_vop_catia_v5tov4(name, namebuf, sizeof (namebuf));
 674  715                  if (strchr(np, '/') != NULL)
 675  716                          return (EILSEQ);
 676  717          }
 677  718  
 678  719          error = VOP_CREATE(dvp, np, vap, EXCL, attr->sa_vattr.va_mode,
 679  720              vpp, cr, option_flags, &smb_ct, vsap);
 680  721  
      722 +        /*
      723 +         * One could argue that filesystems should obey the size
      724 +         * if specified in the create attributes.  Unfortunately,
      725 +         * they only appear to let you truncate the size to zero.
      726 +         * SMB needs to set a non-zero size, so work-around.
      727 +         */
      728 +        if (error == 0 && *vpp != NULL &&
      729 +            (vap->va_mask & AT_SIZE) != 0 &&
      730 +            vap->va_size > 0) {
      731 +                vattr_t ta = *vap;
      732 +                ta.va_mask = AT_SIZE;
      733 +                (void) VOP_SETATTR(*vpp, &ta, 0, cr, &smb_ct);
      734 +        }
      735 +
 681  736          return (error);
 682  737  }
 683  738  
 684  739  int
 685  740  smb_vop_remove(vnode_t *dvp, char *name, int flags, cred_t *cr)
 686  741  {
 687  742          int error;
 688  743          int option_flags = 0;
 689  744          char *np = name;
 690  745          char namebuf[MAXNAMELEN];
↓ open down ↓ 272 lines elided ↑ open up ↑
 963 1018  {
 964 1019          int error = 0;
 965 1020          int flags = 0;
 966 1021          int rdirent_size;
 967 1022          struct uio auio;
 968 1023          struct iovec aiov;
 969 1024  
 970 1025          if (vp->v_type != VDIR)
 971 1026                  return (ENOTDIR);
 972 1027  
 973      -        if (vfs_has_feature(vp->v_vfsp, VFSFT_DIRENTFLAGS)) {
     1028 +        if ((rddir_flag & SMB_EDIRENT) != 0 &&
     1029 +            vfs_has_feature(vp->v_vfsp, VFSFT_DIRENTFLAGS)) {
 974 1030                  flags |= V_RDDIR_ENTFLAGS;
 975 1031                  rdirent_size = sizeof (edirent_t);
 976 1032          } else {
 977 1033                  rdirent_size = sizeof (dirent64_t);
 978 1034          }
 979 1035  
 980 1036          if (*count < rdirent_size)
 981 1037                  return (EINVAL);
 982 1038  
 983 1039          if (rddir_flag & SMB_ABE)
↓ open down ↓ 227 lines elided ↑ open up ↑
1211 1267                  break;
1212 1268  
1213 1269          case ACE_T:
1214 1270                  vsecattr.vsa_mask = VSA_ACE | VSA_ACECNT | VSA_ACE_ACLFLAGS;
1215 1271                  break;
1216 1272  
1217 1273          default:
1218 1274                  return (EINVAL);
1219 1275          }
1220 1276  
1221      -        if (error = VOP_GETSECATTR(vp, &vsecattr, flags, cr, &smb_ct))
     1277 +        if ((error = VOP_GETSECATTR(vp, &vsecattr, flags, cr, &smb_ct)) != 0)
1222 1278                  return (error);
1223 1279  
1224 1280          *aclp = smb_fsacl_from_vsa(&vsecattr, acl_type);
1225 1281          if (vp->v_type == VDIR)
1226 1282                  (*aclp)->acl_flags |= ACL_IS_DIR;
1227 1283  
1228 1284          return (0);
1229 1285  }
1230 1286  
1231 1287  /*
↓ open down ↓ 209 lines elided ↑ open up ↑
1441 1497          shr.s_sysid = smb_ct.cc_sysid;
1442 1498          shr.s_pid = uniq_fid;
1443 1499          shr.s_own_len = sizeof (shr_own);
1444 1500          shr.s_owner = (caddr_t)&shr_own;
1445 1501          shr_own.sl_id = shr.s_sysid;
1446 1502          shr_own.sl_pid = shr.s_pid;
1447 1503  
1448 1504          return (VOP_SHRLOCK(vp, F_UNSHARE, &shr, 0, cr, NULL));
1449 1505  }
1450 1506  
     1507 +/*
     1508 + * Note about mandatory vs advisory locks:
     1509 + *
     1510 + * The SMB server really should always request mandatory locks, and
     1511 + * if the file system does not support them, the SMB server should
     1512 + * just tell the client it could not get the lock. If we were to
     1513 + * tell the SMB client "you got the lock" when what they really
     1514 + * got was only an advisory lock, we would be lying to the client
     1515 + * about their having exclusive access to the locked range, which
     1516 + * could easily lead to data corruption.  If someone really wants
     1517 + * the (dangerous) behavior they can set: smb_allow_advisory_locks
     1518 + */
1451 1519  int
1452 1520  smb_vop_frlock(vnode_t *vp, cred_t *cr, int flag, flock64_t *bf)
1453 1521  {
1454      -        int cmd = nbl_need_check(vp) ? F_SETLK_NBMAND : F_SETLK;
1455 1522          flk_callback_t flk_cb;
     1523 +        int cmd = F_SETLK_NBMAND;
1456 1524  
     1525 +        if (smb_allow_advisory_locks != 0 && !nbl_need_check(vp)) {
     1526 +                /*
     1527 +                 * The file system does not support nbmand, and
     1528 +                 * smb_allow_advisory_locks is enabled. (danger!)
     1529 +                 */
     1530 +                cmd = F_SETLK;
     1531 +        }
     1532 +
1457 1533          flk_init_callback(&flk_cb, smb_lock_frlock_callback, NULL);
1458 1534  
1459 1535          return (VOP_FRLOCK(vp, cmd, bf, flag, 0, &flk_cb, cr, &smb_ct));
1460 1536  }
1461 1537  
1462 1538  static callb_cpr_t *
1463 1539  /* ARGSUSED */
1464 1540  smb_lock_frlock_callback(flk_cb_when_t when, void *error)
1465 1541  {
1466 1542          return (0);
↓ open down ↓ 57 lines elided ↑ open up ↑
1524 1600   * encountered in the filename. The translated name is returned in buf.
1525 1601   *
1526 1602   * If an error occurs the conversion terminates and name is returned,
1527 1603   * otherwise buf is returned.
1528 1604   */
1529 1605  char *
1530 1606  smb_vop_catia_v5tov4(char *name, char *buf, int buflen)
1531 1607  {
1532 1608          int v4_idx, numbytes, inc;
1533 1609          int space_left = buflen - 1; /* one byte reserved for null */
1534      -        smb_wchar_t wc;
     1610 +        uint32_t wc;
1535 1611          char mbstring[MTS_MB_CHAR_MAX];
1536 1612          char *p, *src = name, *dst = buf;
1537 1613  
1538 1614          ASSERT(name);
1539 1615          ASSERT(buf);
1540 1616  
1541 1617          if (!buf || !name)
1542 1618                  return (name);
1543 1619  
1544 1620          bzero(buf, buflen);
↓ open down ↓ 36 lines elided ↑ open up ↑
1581 1657   *
1582 1658   * The translated name is returned in buf.
1583 1659   * If an error occurs the conversion terminates and the original name
1584 1660   * is returned in buf.
1585 1661   */
1586 1662  void
1587 1663  smb_vop_catia_v4tov5(char *name, char *buf, int buflen)
1588 1664  {
1589 1665          int v5_idx, numbytes;
1590 1666          int space_left = buflen - 1; /* one byte reserved for null */
1591      -        smb_wchar_t wc;
     1667 +        uint32_t wc;
1592 1668          char mbstring[MTS_MB_CHAR_MAX];
1593 1669          char *src = name, *dst = buf;
1594 1670  
1595 1671          ASSERT(name);
1596 1672          ASSERT(buf);
1597 1673  
1598 1674          if (!buf || !name)
1599 1675                  return;
1600 1676  
1601 1677          (void) bzero(buf, buflen);
↓ open down ↓ 26 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX