Print this page
NEX-19378 Access problem with SMB server
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-19152 MacOS HighSierra Finder crashes...
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
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-17289 Minimal SMB 3.0.2 support
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@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-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-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-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-5844 want SMB2 ioctl FSCTL_SRV_COPYCHUNK
NEX-6124 smb_fsop_read/write should allow file != sr->fid_ofile
NEX-6125 smbtorture invalid response with smb2.ioctl
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@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-4474 SMB open with access=MAXIMUM_ALLOWED fails after NEX-3232
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@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-58 smbsrv should be immune to its own FEM hooks
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-63 taskq_create_proc ... TQ_DYNAMIC puts tasks in p0
re #11974 CIFS Share - Tree connect fails from Windows 7 Clients
SUS-172 Excel 2003 warning dialog when re-saving a file
SUS-173 Open fails if the client does not ask for read_attribute permission
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

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/smbsrv/smb_fsops.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb_fsops.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 2015 Nexenta Systems, Inc.  All rights reserved.
       23 + * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  24   24   */
  25   25  
  26   26  #include <sys/sid.h>
  27   27  #include <sys/nbmlock.h>
  28   28  #include <smbsrv/smb_fsops.h>
  29   29  #include <smbsrv/smb_kproto.h>
  30   30  #include <acl/acl_common.h>
  31   31  #include <sys/fcntl.h>
       32 +#include <sys/filio.h>
  32   33  #include <sys/flock.h>
  33   34  #include <fs/fs_subr.h>
  34   35  
  35   36  extern caller_context_t smb_ct;
  36   37  
  37      -static int smb_fsop_create_stream(smb_request_t *, cred_t *, smb_node_t *,
  38      -    char *, char *, int, smb_attr_t *, smb_node_t **);
       38 +static int smb_fsop_create_file_with_stream(smb_request_t *, cred_t *,
       39 +    smb_node_t *, char *, char *, int, smb_attr_t *, smb_node_t **);
  39   40  
  40   41  static int smb_fsop_create_file(smb_request_t *, cred_t *, smb_node_t *,
  41   42      char *, int, smb_attr_t *, smb_node_t **);
  42   43  
  43   44  #ifdef  _KERNEL
  44   45  static int smb_fsop_create_with_sd(smb_request_t *, cred_t *, smb_node_t *,
  45   46      char *, smb_attr_t *, smb_node_t **, smb_fssd_t *);
  46   47  static int smb_fsop_sdinherit(smb_request_t *, smb_node_t *, smb_fssd_t *);
  47   48  #endif  /* _KERNEL */
  48   49  
↓ open down ↓ 77 lines elided ↑ open up ↑
 126  127          vsecattr_t *vsap;
 127  128          vsecattr_t vsecattr;
 128  129          smb_attr_t set_attr;
 129  130          acl_t *acl, *dacl, *sacl;
 130  131          vnode_t *vp;
 131  132          cred_t *kcr = zone_kcred();
 132  133          int aclbsize = 0;       /* size of acl list in bytes */
 133  134          int flags = 0;
 134  135          int rc;
 135  136          boolean_t is_dir;
      137 +        boolean_t do_audit;
 136  138  
 137  139          ASSERT(fs_sd);
      140 +        ASSERT(ret_snode != NULL);
 138  141  
 139  142          if (SMB_TREE_IS_CASEINSENSITIVE(sr))
 140  143                  flags = SMB_IGNORE_CASE;
 141  144          if (SMB_TREE_SUPPORTS_CATIA(sr))
 142  145                  flags |= SMB_CATIA;
 143  146  
 144  147          ASSERT(cr);
 145  148  
 146  149          is_dir = ((fs_sd->sd_flags & SMB_FSSD_FLAGS_DIR) != 0);
 147  150  
      151 +        do_audit = smb_audit_init(sr);
 148  152          if (smb_tree_has_feature(sr->tid_tree, SMB_TREE_ACLONCREATE)) {
 149  153                  if (fs_sd->sd_secinfo & SMB_ACL_SECINFO) {
 150  154                          dacl = fs_sd->sd_zdacl;
 151  155                          sacl = fs_sd->sd_zsacl;
 152  156                          ASSERT(dacl || sacl);
 153  157                          if (dacl && sacl) {
 154  158                                  acl = smb_fsacl_merge(dacl, sacl);
 155  159                          } else if (dacl) {
 156  160                                  acl = dacl;
 157  161                          } else {
↓ open down ↓ 18 lines elided ↑ open up ↑
 176  180                  if (is_dir) {
 177  181                          if (SMB_TREE_HAS_ACCESS(sr, ACE_ADD_SUBDIRECTORY) != 0)
 178  182                                  rc = smb_vop_mkdir(dnode->vp, name, attr,
 179  183                                      &vp, flags, cr, vsap);
 180  184                  } else {
 181  185                          if (SMB_TREE_HAS_ACCESS(sr, ACE_ADD_FILE) != 0)
 182  186                                  rc = smb_vop_create(dnode->vp, name, attr,
 183  187                                      &vp, flags, cr, vsap);
 184  188                  }
 185  189  
      190 +                if (do_audit) {
      191 +                        smb_audit_fini(sr,
      192 +                            is_dir ? ACE_ADD_SUBDIRECTORY : ACE_ADD_FILE,
      193 +                            dnode, rc == 0);
      194 +                }
      195 +
 186  196                  if (vsap != NULL)
 187  197                          kmem_free(vsap->vsa_aclentp, aclbsize);
 188  198  
 189  199                  if (rc != 0)
 190  200                          return (rc);
 191  201  
 192  202                  set_attr.sa_mask = 0;
 193  203  
 194  204                  /*
 195  205                   * Ideally we should be able to specify the owner and owning
↓ open down ↓ 34 lines elided ↑ open up ↑
 230  240                   */
 231  241  
 232  242                  if (is_dir) {
 233  243                          rc = smb_vop_mkdir(dnode->vp, name, attr, &vp,
 234  244                              flags, cr, NULL);
 235  245                  } else {
 236  246                          rc = smb_vop_create(dnode->vp, name, attr, &vp,
 237  247                              flags, cr, NULL);
 238  248                  }
 239  249  
      250 +                if (do_audit) {
      251 +                        smb_audit_fini(sr,
      252 +                            is_dir ? ACE_ADD_SUBDIRECTORY : ACE_ADD_FILE,
      253 +                            dnode, rc == 0);
      254 +                }
      255 +
 240  256                  if (rc != 0)
 241  257                          return (rc);
 242  258  
 243  259                  *ret_snode = smb_node_lookup(sr, &sr->arg.open, cr, vp,
 244  260                      name, dnode, NULL);
 245  261  
 246  262                  if (*ret_snode != NULL) {
 247  263                          if (!smb_tree_has_feature(sr->tid_tree,
 248  264                              SMB_TREE_NFS_MOUNTED))
 249  265                                  rc = smb_fsop_sdwrite(sr, kcr, *ret_snode,
↓ open down ↓ 62 lines elided ↑ open up ↑
 312  328          if (SMB_TREE_SUPPORTS_CATIA(sr))
 313  329                  flags |= SMB_CATIA;
 314  330          if (SMB_TREE_SUPPORTS_ABE(sr))
 315  331                  flags |= SMB_ABE;
 316  332  
 317  333          if (smb_is_stream_name(name)) {
 318  334                  fname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 319  335                  sname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 320  336                  smb_stream_parse_name(name, fname, sname);
 321  337  
 322      -                rc = smb_fsop_create_stream(sr, cr, dnode,
      338 +                rc = smb_fsop_create_file_with_stream(sr, cr, dnode,
 323  339                      fname, sname, flags, attr, ret_snode);
 324  340  
 325  341                  kmem_free(fname, MAXNAMELEN);
 326  342                  kmem_free(sname, MAXNAMELEN);
 327  343                  return (rc);
 328  344          }
 329  345  
 330  346          /* Not a named stream */
 331  347  
 332  348          if (SMB_TREE_SUPPORTS_SHORTNAMES(sr) && smb_maybe_mangled(name)) {
↓ open down ↓ 8 lines elided ↑ open up ↑
 341  357          }
 342  358  
 343  359          rc = smb_fsop_create_file(sr, cr, dnode, name, flags,
 344  360              attr, ret_snode);
 345  361          return (rc);
 346  362  
 347  363  }
 348  364  
 349  365  
 350  366  /*
 351      - * smb_fsop_create_stream
      367 + * smb_fsop_create_file_with_stream
 352  368   *
 353      - * Create NTFS named stream file (sname) on unnamed stream
 354      - * file (fname), creating the unnamed stream file if it
      369 + * Create named stream (sname) on file (fname), creating the file if it
 355  370   * doesn't exist.
 356      - * If we created the unnamed stream file and then creation
 357      - * of the named stream file fails, we delete the unnamed stream.
      371 + * If we created the file and then creation of the named stream fails,
      372 + * we delete the file.
 358  373   * Since we use the real file name for the smb_vop_remove we
 359  374   * clear the SMB_IGNORE_CASE flag to ensure a case sensitive
 360  375   * match.
 361  376   *
 362      - * The second parameter of smb_vop_setattr() is set to
 363      - * NULL, even though an unnamed stream exists.  This is
 364      - * because we want to set the UID and GID on the named
 365      - * stream in this case for consistency with the (unnamed
 366      - * stream) file (see comments for smb_vop_setattr()).
      377 + * Note that some stream "types" are "restricted" and only
      378 + * internal callers (cr == kcred) can create those.
 367  379   */
 368  380  static int
 369      -smb_fsop_create_stream(smb_request_t *sr, cred_t *cr,
      381 +smb_fsop_create_file_with_stream(smb_request_t *sr, cred_t *cr,
 370  382      smb_node_t *dnode, char *fname, char *sname, int flags,
 371  383      smb_attr_t *attr, smb_node_t **ret_snode)
 372  384  {
 373      -        smb_attr_t      fattr;
 374  385          smb_node_t      *fnode;
 375      -        vnode_t         *xattrdvp;
 376      -        vnode_t         *vp;
 377  386          cred_t          *kcr = zone_kcred();
 378  387          int             rc = 0;
 379  388          boolean_t       fcreate = B_FALSE;
 380  389  
      390 +        ASSERT(ret_snode != NULL);
      391 +
      392 +        if (cr != kcr && smb_strname_restricted(sname))
      393 +                return (EACCES);
      394 +
 381  395          /* Look up / create the unnamed stream, fname */
 382  396          rc = smb_fsop_lookup(sr, cr, flags | SMB_FOLLOW_LINKS,
 383  397              sr->tid_tree->t_snode, dnode, fname, &fnode);
 384  398          if (rc == ENOENT) {
 385  399                  fcreate = B_TRUE;
 386  400                  rc = smb_fsop_create_file(sr, cr, dnode, fname, flags,
 387  401                      attr, &fnode);
 388  402          }
 389  403          if (rc != 0)
 390  404                  return (rc);
 391  405  
 392      -        fattr.sa_mask = SMB_AT_UID | SMB_AT_GID;
 393      -        rc = smb_vop_getattr(fnode->vp, NULL, &fattr, 0, kcr);
      406 +        rc = smb_fsop_create_stream(sr, cr, dnode, fnode, sname, flags, attr,
      407 +            ret_snode);
 394  408  
 395      -        if (rc == 0) {
 396      -                /* create the named stream, sname */
 397      -                rc = smb_vop_stream_create(fnode->vp, sname, attr,
 398      -                    &vp, &xattrdvp, flags, cr);
 399      -        }
 400  409          if (rc != 0) {
 401  410                  if (fcreate) {
 402  411                          flags &= ~SMB_IGNORE_CASE;
 403  412                          (void) smb_vop_remove(dnode->vp,
 404  413                              fnode->od_name, flags, cr);
 405  414                  }
 406      -                smb_node_release(fnode);
 407      -                return (rc);
 408  415          }
 409  416  
      417 +        smb_node_release(fnode);
      418 +        return (rc);
      419 +}
      420 +
      421 +/*
      422 + * smb_fsop_create_stream
      423 + *
      424 + * Create named stream (sname) on existing file (fnode).
      425 + *
      426 + * The second parameter of smb_vop_setattr() is set to
      427 + * NULL, even though an unnamed stream exists.  This is
      428 + * because we want to set the UID and GID on the named
      429 + * stream in this case for consistency with the (unnamed
      430 + * stream) file (see comments for smb_vop_setattr()).
      431 + *
      432 + * Note that some stream "types" are "restricted" and only
      433 + * internal callers (cr == kcred) can create those.
      434 + */
      435 +int
      436 +smb_fsop_create_stream(smb_request_t *sr, cred_t *cr,
      437 +    smb_node_t *dnode, smb_node_t *fnode, char *sname, int flags,
      438 +    smb_attr_t *attr, smb_node_t **ret_snode)
      439 +{
      440 +        smb_attr_t      fattr;
      441 +        vnode_t         *xattrdvp;
      442 +        vnode_t         *vp;
      443 +        cred_t          *kcr = zone_kcred();
      444 +        int             rc = 0;
      445 +
      446 +        ASSERT(ret_snode != NULL);
      447 +
      448 +        if (cr != kcr && smb_strname_restricted(sname))
      449 +                return (EACCES);
      450 +
      451 +        bzero(&fattr, sizeof (fattr));
      452 +        fattr.sa_mask = SMB_AT_UID | SMB_AT_GID;
      453 +        rc = smb_vop_getattr(fnode->vp, NULL, &fattr, 0, kcr);
      454 +
      455 +        if (rc == 0) {
      456 +                /* create the named stream, sname */
      457 +                rc = smb_vop_stream_create(fnode->vp, sname,
      458 +                    attr, &vp, &xattrdvp, flags, cr);
      459 +        }
      460 +        if (rc != 0)
      461 +                return (rc);
      462 +
 410  463          attr->sa_vattr.va_uid = fattr.sa_vattr.va_uid;
 411  464          attr->sa_vattr.va_gid = fattr.sa_vattr.va_gid;
 412  465          attr->sa_mask = SMB_AT_UID | SMB_AT_GID;
 413  466  
 414  467          rc = smb_vop_setattr(vp, NULL, attr, 0, kcr);
 415  468          if (rc != 0) {
 416      -                smb_node_release(fnode);
      469 +                VN_RELE(xattrdvp);
      470 +                VN_RELE(vp);
 417  471                  return (rc);
 418  472          }
 419  473  
 420  474          *ret_snode = smb_stream_node_lookup(sr, cr, fnode, xattrdvp,
 421  475              vp, sname);
 422  476  
 423      -        smb_node_release(fnode);
 424  477          VN_RELE(xattrdvp);
 425  478          VN_RELE(vp);
 426  479  
 427  480          if (*ret_snode == NULL)
 428  481                  rc = ENOMEM;
 429  482  
 430  483          /* notify change to the unnamed stream */
 431  484          if (rc == 0)
 432  485                  smb_node_notify_change(dnode,
 433      -                    FILE_ACTION_ADDED_STREAM, fname);
      486 +                    FILE_ACTION_ADDED_STREAM, fnode->od_name);
 434  487  
 435  488          return (rc);
 436  489  }
 437  490  
 438  491  /*
 439  492   * smb_fsop_create_file
 440  493   */
 441  494  static int
 442  495  smb_fsop_create_file(smb_request_t *sr, cred_t *cr,
 443  496      smb_node_t *dnode, char *name, int flags,
 444  497      smb_attr_t *attr, smb_node_t **ret_snode)
 445  498  {
 446  499          smb_arg_open_t  *op = &sr->sr_open;
 447  500          vnode_t         *vp;
 448  501          int             rc;
 449  502  
      503 +        ASSERT(ret_snode != NULL);
      504 +
 450  505  #ifdef  _KERNEL
 451  506          smb_fssd_t      fs_sd;
 452  507          uint32_t        secinfo;
 453  508          uint32_t        status;
 454  509  
 455  510          if (op->sd) {
 456  511                  /*
 457  512                   * SD sent by client in Windows format. Needs to be
 458  513                   * converted to FS format. No inheritance.
 459  514                   */
↓ open down ↓ 21 lines elided ↑ open up ↑
 481  536                              name, attr, ret_snode, &fs_sd);
 482  537                  }
 483  538  
 484  539                  smb_fssd_term(&fs_sd);
 485  540          } else
 486  541  #endif  /* _KERNEL */
 487  542          {
 488  543                  /*
 489  544                   * No incoming SD and filesystem is not ZFS
 490  545                   * let the filesystem handles the inheritance.
      546 +                 *
      547 +                 * fsop_create_with_sd handles auditing in the other cases.
      548 +                 * Handle it explicitly here.
 491  549                   */
      550 +                boolean_t do_audit = smb_audit_init(sr);
      551 +
 492  552                  rc = smb_vop_create(dnode->vp, name, attr, &vp,
 493  553                      flags, cr, NULL);
 494  554  
      555 +                if (do_audit) {
      556 +                        smb_audit_fini(sr, ACE_ADD_FILE, dnode, rc == 0);
      557 +                }
      558 +
 495  559                  if (rc == 0) {
 496  560                          *ret_snode = smb_node_lookup(sr, op, cr, vp,
 497  561                              name, dnode, NULL);
 498  562  
 499  563                          if (*ret_snode == NULL)
 500  564                                  rc = ENOMEM;
 501  565  
 502  566                          VN_RELE(vp);
 503  567                  }
 504  568  
↓ open down ↓ 115 lines elided ↑ open up ↑
 620  684                  if (rc == 0) {
 621  685                          rc = smb_fsop_create_with_sd(sr, cr, dnode,
 622  686                              name, attr, ret_snode, &fs_sd);
 623  687                  }
 624  688  
 625  689                  smb_fssd_term(&fs_sd);
 626  690  
 627  691          } else
 628  692  #endif  /* _KERNEL */
 629  693          {
      694 +                /*
      695 +                 * fsop_create_with_sd handles auditing in the other cases.
      696 +                 * Handle it explicitly here.
      697 +                 */
      698 +                boolean_t do_audit = smb_audit_init(sr);
      699 +
 630  700                  rc = smb_vop_mkdir(dnode->vp, name, attr, &vp, flags, cr,
 631  701                      NULL);
 632  702  
      703 +                if (do_audit) {
      704 +                        smb_audit_fini(sr, ACE_ADD_SUBDIRECTORY, dnode,
      705 +                            rc == 0);
      706 +                }
      707 +
 633  708                  if (rc == 0) {
 634  709                          *ret_snode = smb_node_lookup(sr, op, cr, vp, name,
 635  710                              dnode, NULL);
 636  711  
 637  712                          if (*ret_snode == NULL)
 638  713                                  rc = ENOMEM;
 639  714  
 640  715                          VN_RELE(vp);
 641  716                  }
 642  717          }
↓ open down ↓ 8 lines elided ↑ open up ↑
 651  726   * smb_fsop_remove
 652  727   *
 653  728   * All SMB functions should use this wrapper to ensure that
 654  729   * the the calls are performed with the appropriate credentials.
 655  730   * Please document any direct call to explain the reason
 656  731   * for avoiding this wrapper.
 657  732   *
 658  733   * It is assumed that a reference exists on snode coming into this routine.
 659  734   *
 660  735   * A null smb_request might be passed to this function.
      736 + *
      737 + * Note that some stream "types" are "restricted" and only
      738 + * internal callers (cr == kcred) can remove those.
 661  739   */
 662  740  int
 663  741  smb_fsop_remove(
 664  742      smb_request_t       *sr,
 665  743      cred_t              *cr,
 666  744      smb_node_t          *dnode,
 667  745      char                *name,
 668  746      uint32_t            flags)
 669  747  {
 670  748          smb_node_t      *fnode;
↓ open down ↓ 15 lines elided ↑ open up ↑
 686  764              SMB_TREE_HAS_ACCESS(sr, ACE_DELETE) == 0)
 687  765                  return (EACCES);
 688  766  
 689  767          if (SMB_TREE_IS_READONLY(sr))
 690  768                  return (EROFS);
 691  769  
 692  770          fname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 693  771          sname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 694  772  
 695  773          if (dnode->flags & NODE_XATTR_DIR) {
      774 +                if (cr != zone_kcred() && smb_strname_restricted(name)) {
      775 +                        rc = EACCES;
      776 +                        goto out;
      777 +                }
      778 +
 696  779                  fnode = dnode->n_dnode;
 697  780                  rc = smb_vop_stream_remove(fnode->vp, name, flags, cr);
 698  781  
 699  782                  /* notify change to the unnamed stream */
 700  783                  if ((rc == 0) && fnode->n_dnode) {
 701  784                          smb_node_notify_change(fnode->n_dnode,
 702  785                              FILE_ACTION_REMOVED_STREAM, fnode->od_name);
 703  786                  }
 704  787          } else if (smb_is_stream_name(name)) {
 705  788                  smb_stream_parse_name(name, fname, sname);
 706  789  
      790 +                if (cr != zone_kcred() && smb_strname_restricted(sname)) {
      791 +                        rc = EACCES;
      792 +                        goto out;
      793 +                }
      794 +
 707  795                  /*
 708  796                   * Look up the unnamed stream (i.e. fname).
 709  797                   * Unmangle processing will be done on fname
 710  798                   * as well as any link target.
 711  799                   */
 712  800  
 713  801                  rc = smb_fsop_lookup(sr, cr, flags | SMB_FOLLOW_LINKS,
 714  802                      sr->tid_tree->t_snode, dnode, fname, &fnode);
 715  803  
 716  804                  if (rc != 0) {
 717      -                        kmem_free(fname, MAXNAMELEN);
 718      -                        kmem_free(sname, MAXNAMELEN);
 719      -                        return (rc);
      805 +                        goto out;
 720  806                  }
 721  807  
 722  808                  /*
 723  809                   * XXX
 724  810                   * Need to find out what permission is required by NTFS
 725  811                   * to remove a stream.
 726  812                   */
 727  813                  rc = smb_vop_stream_remove(fnode->vp, sname, flags, cr);
 728  814  
 729  815                  smb_node_release(fnode);
↓ open down ↓ 2 lines elided ↑ open up ↑
 732  818                  if (rc == 0) {
 733  819                          smb_node_notify_change(dnode,
 734  820                              FILE_ACTION_REMOVED_STREAM, fname);
 735  821                  }
 736  822          } else {
 737  823                  rc = smb_vop_remove(dnode->vp, name, flags, cr);
 738  824  
 739  825                  if (rc == ENOENT) {
 740  826                          if (!SMB_TREE_SUPPORTS_SHORTNAMES(sr) ||
 741  827                              !smb_maybe_mangled(name)) {
 742      -                                kmem_free(fname, MAXNAMELEN);
 743      -                                kmem_free(sname, MAXNAMELEN);
 744      -                                return (rc);
      828 +                                goto out;
 745  829                          }
 746  830                          longname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
 747  831  
 748  832                          if (SMB_TREE_SUPPORTS_ABE(sr))
 749  833                                  flags |= SMB_ABE;
 750  834  
 751  835                          rc = smb_unmangle(dnode, name, longname, MAXNAMELEN,
 752  836                              flags);
 753  837  
 754  838                          if (rc == 0) {
↓ open down ↓ 9 lines elided ↑ open up ↑
 764  848                                      flags, cr);
 765  849                          }
 766  850                          kmem_free(longname, MAXNAMELEN);
 767  851                  }
 768  852                  if (rc == 0) {
 769  853                          smb_node_notify_change(dnode,
 770  854                              FILE_ACTION_REMOVED, name);
 771  855                  }
 772  856          }
 773  857  
      858 +out:
 774  859          kmem_free(fname, MAXNAMELEN);
 775  860          kmem_free(sname, MAXNAMELEN);
 776  861  
 777  862          return (rc);
 778  863  }
 779  864  
 780  865  /*
 781  866   * smb_fsop_remove_streams
 782  867   *
 783  868   * This function removes a file's streams without removing the
↓ open down ↓ 25 lines elided ↑ open up ↑
 809  894          if (SMB_TREE_IS_CASEINSENSITIVE(sr))
 810  895                  flags = SMB_IGNORE_CASE;
 811  896  
 812  897          if (SMB_TREE_SUPPORTS_CATIA(sr))
 813  898                  flags |= SMB_CATIA;
 814  899  
 815  900          status = smb_odir_openat(sr, fnode, &od);
 816  901          switch (status) {
 817  902          case 0:
 818  903                  break;
      904 +        case NT_STATUS_OBJECT_NAME_NOT_FOUND:
 819  905          case NT_STATUS_NO_SUCH_FILE:
 820  906          case NT_STATUS_NOT_SUPPORTED:
 821  907                  /* No streams to remove. */
 822  908                  return (0);
 823  909          default:
 824  910                  return (status);
 825  911          }
 826  912  
 827  913          odirent = kmem_alloc(sizeof (smb_odirent_t), KM_SLEEP);
 828  914          for (;;) {
↓ open down ↓ 278 lines elided ↑ open up ↑
1107 1193           * on this on-disk name, possibly resulting in the wrong file).
1108 1194           */
1109 1195  
1110 1196          if (SMB_TREE_SUPPORTS_CATIA(sr))
1111 1197                  flags |= SMB_CATIA;
1112 1198  
1113 1199          /*
1114 1200           * XXX: Lock required through smb_node_release() below?
1115 1201           */
1116 1202  
     1203 +        /*
     1204 +         * Don't audit the lookup
     1205 +         */
     1206 +        smb_audit_save();
1117 1207          rc = smb_vop_lookup(from_dnode->vp, from_name, &from_vp, NULL,
1118 1208              flags, &ret_flags, NULL, &from_attr, cr);
     1209 +        smb_audit_load();
1119 1210  
1120 1211          if (rc != 0)
1121 1212                  return (rc);
1122 1213  
1123 1214          if (from_attr.sa_dosattr & FILE_ATTRIBUTE_REPARSE_POINT) {
1124 1215                  VN_RELE(from_vp);
1125 1216                  return (EACCES);
1126 1217          }
1127 1218  
1128 1219          isdir = ((from_attr.sa_dosattr & FILE_ATTRIBUTE_DIRECTORY) != 0);
↓ open down ↓ 19 lines elided ↑ open up ↑
1148 1239           *   ATTR_NOACLCHECK flag to ensure that the file system
1149 1240           *   does not check permissions on subsequent calls.
1150 1241           */
1151 1242          if (sr && sr->fid_ofile) {
1152 1243                  rc = smb_ofile_access(sr->fid_ofile, cr, DELETE);
1153 1244                  if (rc != NT_STATUS_SUCCESS) {
1154 1245                          VN_RELE(from_vp);
1155 1246                          return (EACCES);
1156 1247                  }
1157 1248  
     1249 +                /* TODO: rename drops ATTR_NOACLCHECK, so this is a no-op. */
1158 1250                  if (smb_tree_has_feature(sr->tid_tree,
1159 1251                      SMB_TREE_ACEMASKONACCESS))
1160 1252                          flags = ATTR_NOACLCHECK;
1161 1253          }
1162 1254  
1163 1255          rc = smb_vop_rename(from_dnode->vp, from_name, to_dnode->vp,
1164 1256              to_name, flags, cr);
1165 1257  
1166 1258          if (rc == 0) {
1167 1259                  from_snode = smb_node_lookup(sr, NULL, cr, from_vp, from_name,
↓ open down ↓ 64 lines elided ↑ open up ↑
1232 1324                  return (EACCES);
1233 1325  
1234 1326          if (SMB_TREE_IS_READONLY(sr))
1235 1327                  return (EROFS);
1236 1328  
1237 1329          if (SMB_TREE_HAS_ACCESS(sr,
1238 1330              ACE_WRITE_ATTRIBUTES | ACE_WRITE_NAMED_ATTRS) == 0)
1239 1331                  return (EACCES);
1240 1332  
1241 1333          /*
1242      -         * The file system cannot detect pending READDONLY
1243      -         * (i.e. if the file has been opened readonly but
1244      -         * not yet closed) so we need to test READONLY here.
1245      -         *
1246      -         * Note that file handle that were opened before the
1247      -         * READONLY flag was set in the node (or the FS) are
1248      -         * immune to that change, and remain writable.
1249      -         */
1250      -        if (sr && (set_attr->sa_mask & SMB_AT_SIZE)) {
1251      -                if (sr->fid_ofile) {
1252      -                        if (SMB_OFILE_IS_READONLY(sr->fid_ofile))
1253      -                                return (EACCES);
1254      -                } else {
1255      -                        if (SMB_PATHFILE_IS_READONLY(sr, snode))
1256      -                                return (EACCES);
1257      -                }
1258      -        }
1259      -
1260      -        /*
1261 1334           * SMB checks access on open and retains an access granted
1262 1335           * mask for use while the file is open.  ACL changes should
1263 1336           * not affect access to an open file.
1264 1337           *
1265 1338           * If the setattr is being performed on an ofile:
1266 1339           * - Check the ofile's access granted mask to see if the
1267 1340           *   setattr is permitted.
1268 1341           *   UID, GID - require WRITE_OWNER
1269 1342           *   SIZE, ALLOCSZ - require FILE_WRITE_DATA
1270 1343           *   all other attributes require FILE_WRITE_ATTRIBUTES
↓ open down ↓ 35 lines elided ↑ open up ↑
1306 1379                  ASSERT(unnamed_node->n_state != SMB_NODE_STATE_DESTROYING);
1307 1380                  unnamed_vp = unnamed_node->vp;
1308 1381          }
1309 1382  
1310 1383          rc = smb_vop_setattr(snode->vp, unnamed_vp, set_attr, flags, cr);
1311 1384          return (rc);
1312 1385  }
1313 1386  
1314 1387  /*
1315 1388   * Support for SMB2 setinfo FileValidDataLengthInformation.
1316      - * Free data from the specified offset to EoF.
1317      - *
1318      - * This can effectively truncate data.  It truncates the data
1319      - * leaving the file size as it was, leaving zeros after the
1320      - * offset specified here.  That is effectively modifying the
1321      - * file content, so for access control this is a write.
     1389 + * Free (zero out) data in the range off, off+len
1322 1390   */
1323 1391  int
1324      -smb_fsop_set_data_length(
     1392 +smb_fsop_freesp(
1325 1393      smb_request_t       *sr,
1326 1394      cred_t              *cr,
1327      -    smb_node_t          *node,
1328      -    offset_t            end_of_data)
     1395 +    smb_ofile_t         *ofile,
     1396 +    off64_t             off,
     1397 +    off64_t             len)
1329 1398  {
1330 1399          flock64_t flk;
     1400 +        smb_node_t *node = ofile->f_node;
1331 1401          uint32_t status;
1332 1402          uint32_t access = FILE_WRITE_DATA;
1333 1403          int rc;
1334 1404  
1335 1405          ASSERT(cr);
1336 1406          ASSERT(node);
1337 1407          ASSERT(node->n_magic == SMB_NODE_MAGIC);
1338 1408          ASSERT(node->n_state != SMB_NODE_STATE_DESTROYING);
1339 1409  
1340 1410          if (SMB_TREE_CONTAINS_NODE(sr, node) == 0)
1341 1411                  return (EACCES);
1342 1412  
1343 1413          if (SMB_TREE_IS_READONLY(sr))
1344 1414                  return (EROFS);
1345 1415  
1346 1416          if (SMB_TREE_HAS_ACCESS(sr, access) == 0)
1347 1417                  return (EACCES);
1348 1418  
1349 1419          /*
1350      -         * The file system cannot detect pending READDONLY
1351      -         * (i.e. if the file has been opened readonly but
1352      -         * not yet closed) so we need to test READONLY here.
1353      -         *
1354      -         * Note that file handle that were opened before the
1355      -         * READONLY flag was set in the node (or the FS) are
1356      -         * immune to that change, and remain writable.
1357      -         */
1358      -        if (sr->fid_ofile) {
1359      -                if (SMB_OFILE_IS_READONLY(sr->fid_ofile))
1360      -                        return (EACCES);
1361      -        } else {
1362      -                /* This requires an open file. */
1363      -                return (EACCES);
1364      -        }
1365      -
1366      -        /*
1367 1420           * SMB checks access on open and retains an access granted
1368 1421           * mask for use while the file is open.  ACL changes should
1369 1422           * not affect access to an open file.
1370 1423           *
1371 1424           * If the setattr is being performed on an ofile:
1372 1425           * - Check the ofile's access granted mask to see if this
1373 1426           *   modification should be permitted (FILE_WRITE_DATA)
1374 1427           */
1375 1428          status = smb_ofile_access(sr->fid_ofile, cr, access);
1376 1429          if (status != NT_STATUS_SUCCESS)
1377 1430                  return (EACCES);
1378 1431  
1379 1432          bzero(&flk, sizeof (flk));
1380      -        flk.l_start = end_of_data;
     1433 +        flk.l_start = off;
     1434 +        flk.l_len = len;
1381 1435  
1382 1436          rc = smb_vop_space(node->vp, F_FREESP, &flk, FWRITE, 0LL, cr);
1383 1437          return (rc);
1384 1438  }
1385 1439  
1386 1440  /*
1387 1441   * smb_fsop_read
1388 1442   *
1389 1443   * All SMB functions should use this wrapper to ensure that
1390 1444   * the the calls are performed with the appropriate credentials.
1391 1445   * Please document any direct call to explain the reason
1392 1446   * for avoiding this wrapper.
1393 1447   *
1394 1448   * It is assumed that a reference exists on snode coming into this routine.
     1449 + * Note that ofile may be different from sr->fid_ofile, or may be NULL.
1395 1450   */
1396 1451  int
1397      -smb_fsop_read(smb_request_t *sr, cred_t *cr, smb_node_t *snode, uio_t *uio)
     1452 +smb_fsop_read(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
     1453 +    smb_ofile_t *ofile, uio_t *uio, int ioflag)
1398 1454  {
1399 1455          caller_context_t ct;
1400 1456          cred_t *kcr = zone_kcred();
     1457 +        uint32_t amask;
1401 1458          int svmand;
1402 1459          int rc;
1403 1460  
1404 1461          ASSERT(cr);
1405 1462          ASSERT(snode);
1406 1463          ASSERT(snode->n_magic == SMB_NODE_MAGIC);
1407 1464          ASSERT(snode->n_state != SMB_NODE_STATE_DESTROYING);
1408 1465  
1409 1466          ASSERT(sr);
1410      -        ASSERT(sr->fid_ofile);
1411 1467  
1412      -        if (SMB_TREE_HAS_ACCESS(sr, ACE_READ_DATA) == 0)
1413      -                return (EACCES);
     1468 +        if (ofile != NULL) {
     1469 +                /*
     1470 +                 * Check tree access.  Not SMB_TREE_HAS_ACCESS
     1471 +                 * because we need to use ofile->f_tree
     1472 +                 */
     1473 +                if ((ofile->f_tree->t_access & ACE_READ_DATA) == 0)
     1474 +                        return (EACCES);
1414 1475  
1415      -        rc = smb_ofile_access(sr->fid_ofile, cr, FILE_READ_DATA);
1416      -        if ((rc != NT_STATUS_SUCCESS) &&
1417      -            (sr->smb_flg2 & SMB_FLAGS2_READ_IF_EXECUTE))
1418      -                rc = smb_ofile_access(sr->fid_ofile, cr, FILE_EXECUTE);
     1476 +                /*
     1477 +                 * Check ofile access.  Use in-line smb_ofile_access
     1478 +                 * so we can check both amask bits at the same time.
     1479 +                 * If any bit in amask is granted, allow this read.
     1480 +                 */
     1481 +                amask = FILE_READ_DATA;
     1482 +                if (sr->smb_flg2 & SMB_FLAGS2_READ_IF_EXECUTE)
     1483 +                        amask |= FILE_EXECUTE;
     1484 +                if (cr != kcr && (ofile->f_granted_access & amask) == 0)
     1485 +                        return (EACCES);
     1486 +        }
1419 1487  
1420      -        if (rc != NT_STATUS_SUCCESS)
1421      -                return (EACCES);
1422      -
1423 1488          /*
1424 1489           * Streams permission are checked against the unnamed stream,
1425 1490           * but in FS level they have their own permissions. To avoid
1426 1491           * rejection by FS due to lack of permission on the actual
1427 1492           * extended attr kcred is passed for streams.
1428 1493           */
1429 1494          if (SMB_IS_STREAM(snode))
1430 1495                  cr = kcr;
1431 1496  
1432 1497          smb_node_start_crit(snode, RW_READER);
1433 1498          rc = nbl_svmand(snode->vp, kcr, &svmand);
1434 1499          if (rc) {
1435 1500                  smb_node_end_crit(snode);
1436 1501                  return (rc);
1437 1502          }
1438 1503  
1439      -        ct = smb_ct;
1440      -        ct.cc_pid = sr->fid_ofile->f_uniqid;
1441      -        rc = nbl_lock_conflict(snode->vp, NBL_READ, uio->uio_loffset,
1442      -            uio->uio_iov->iov_len, svmand, &ct);
1443      -
1444      -        if (rc) {
1445      -                smb_node_end_crit(snode);
1446      -                return (ERANGE);
     1504 +        /*
     1505 +         * Note: SMB allows a zero-byte read, which should not
     1506 +         * conflict with any locks.  However nbl_lock_conflict
     1507 +         * takes a zero-byte length as lock to EOF, so we must
     1508 +         * special case that here.
     1509 +         */
     1510 +        if (uio->uio_resid > 0) {
     1511 +                ct = smb_ct;
     1512 +                if (ofile != NULL)
     1513 +                        ct.cc_pid = ofile->f_uniqid;
     1514 +                rc = nbl_lock_conflict(snode->vp, NBL_READ, uio->uio_loffset,
     1515 +                    uio->uio_resid, svmand, &ct);
     1516 +                if (rc != 0) {
     1517 +                        smb_node_end_crit(snode);
     1518 +                        return (ERANGE);
     1519 +                }
1447 1520          }
1448 1521  
1449      -        rc = smb_vop_read(snode->vp, uio, cr);
     1522 +        rc = smb_vop_read(snode->vp, uio, ioflag, cr);
1450 1523          smb_node_end_crit(snode);
1451 1524  
1452 1525          return (rc);
1453 1526  }
1454 1527  
1455 1528  /*
1456 1529   * smb_fsop_write
1457 1530   *
1458      - * This is a wrapper function used for smb_write and smb_write_raw operations.
1459      - *
1460 1531   * It is assumed that a reference exists on snode coming into this routine.
     1532 + * Note that ofile may be different from sr->fid_ofile, or may be NULL.
1461 1533   */
1462 1534  int
1463 1535  smb_fsop_write(
1464 1536      smb_request_t *sr,
1465 1537      cred_t *cr,
1466 1538      smb_node_t *snode,
     1539 +    smb_ofile_t *ofile,
1467 1540      uio_t *uio,
1468 1541      uint32_t *lcount,
1469 1542      int ioflag)
1470 1543  {
1471 1544          caller_context_t ct;
1472 1545          smb_attr_t attr;
     1546 +        cred_t *kcr = zone_kcred();
1473 1547          smb_node_t *u_node;
1474 1548          vnode_t *u_vp = NULL;
1475      -        smb_ofile_t *of;
1476 1549          vnode_t *vp;
1477      -        cred_t *kcr = zone_kcred();
     1550 +        uint32_t amask;
1478 1551          int svmand;
1479 1552          int rc;
1480 1553  
1481 1554          ASSERT(cr);
1482 1555          ASSERT(snode);
1483 1556          ASSERT(snode->n_magic == SMB_NODE_MAGIC);
1484 1557          ASSERT(snode->n_state != SMB_NODE_STATE_DESTROYING);
1485 1558  
1486 1559          ASSERT(sr);
1487      -        ASSERT(sr->tid_tree);
1488      -        of = sr->fid_ofile;
1489 1560          vp = snode->vp;
1490 1561  
1491      -        if (SMB_TREE_IS_READONLY(sr))
1492      -                return (EROFS);
     1562 +        if (ofile != NULL) {
     1563 +                amask = FILE_WRITE_DATA | FILE_APPEND_DATA;
1493 1564  
1494      -        if (SMB_OFILE_IS_READONLY(of) ||
1495      -            SMB_TREE_HAS_ACCESS(sr, ACE_WRITE_DATA | ACE_APPEND_DATA) == 0)
1496      -                return (EACCES);
     1565 +                /* Check tree access. */
     1566 +                if ((ofile->f_tree->t_access & amask) == 0)
     1567 +                        return (EROFS);
1497 1568  
1498      -        rc = smb_ofile_access(of, cr, FILE_WRITE_DATA);
1499      -        if (rc != NT_STATUS_SUCCESS) {
1500      -                rc = smb_ofile_access(of, cr, FILE_APPEND_DATA);
1501      -                if (rc != NT_STATUS_SUCCESS)
     1569 +                /*
     1570 +                 * Check ofile access.  Use in-line smb_ofile_access
     1571 +                 * so we can check both amask bits at the same time.
     1572 +                 * If any bit in amask is granted, allow this write.
     1573 +                 */
     1574 +                if (cr != kcr && (ofile->f_granted_access & amask) == 0)
1502 1575                          return (EACCES);
1503 1576          }
1504 1577  
1505 1578          /*
1506 1579           * Streams permission are checked against the unnamed stream,
1507 1580           * but in FS level they have their own permissions. To avoid
1508 1581           * rejection by FS due to lack of permission on the actual
1509 1582           * extended attr kcred is passed for streams.
1510 1583           */
1511 1584          u_node = SMB_IS_STREAM(snode);
↓ open down ↓ 4 lines elided ↑ open up ↑
1516 1589                  cr = kcr;
1517 1590          }
1518 1591  
1519 1592          smb_node_start_crit(snode, RW_WRITER);
1520 1593          rc = nbl_svmand(vp, kcr, &svmand);
1521 1594          if (rc) {
1522 1595                  smb_node_end_crit(snode);
1523 1596                  return (rc);
1524 1597          }
1525 1598  
1526      -        ct = smb_ct;
1527      -        ct.cc_pid = of->f_uniqid;
1528      -        rc = nbl_lock_conflict(vp, NBL_WRITE, uio->uio_loffset,
1529      -            uio->uio_iov->iov_len, svmand, &ct);
1530      -
1531      -        if (rc) {
1532      -                smb_node_end_crit(snode);
1533      -                return (ERANGE);
     1599 +        /*
     1600 +         * Note: SMB allows a zero-byte write, which should not
     1601 +         * conflict with any locks.  However nbl_lock_conflict
     1602 +         * takes a zero-byte length as lock to EOF, so we must
     1603 +         * special case that here.
     1604 +         */
     1605 +        if (uio->uio_resid > 0) {
     1606 +                ct = smb_ct;
     1607 +                if (ofile != NULL)
     1608 +                        ct.cc_pid = ofile->f_uniqid;
     1609 +                rc = nbl_lock_conflict(vp, NBL_WRITE, uio->uio_loffset,
     1610 +                    uio->uio_resid, svmand, &ct);
     1611 +                if (rc != 0) {
     1612 +                        smb_node_end_crit(snode);
     1613 +                        return (ERANGE);
     1614 +                }
1534 1615          }
1535 1616  
1536 1617          rc = smb_vop_write(vp, uio, ioflag, lcount, cr);
1537 1618  
1538 1619          /*
1539 1620           * Once the mtime has been set via this ofile, the
1540 1621           * automatic mtime changes from writes via this ofile
1541 1622           * should cease, preserving the mtime that was set.
1542 1623           * See: [MS-FSA] 2.1.5.14 and smb_node_setattr.
1543 1624           *
1544 1625           * The VFS interface does not offer a way to ask it to
1545 1626           * skip the mtime updates, so we simulate the desired
1546 1627           * behavior by re-setting the mtime after writes on a
1547 1628           * handle where the mtime has been set.
1548 1629           */
1549      -        if (of->f_pending_attr.sa_mask & SMB_AT_MTIME) {
1550      -                bcopy(&of->f_pending_attr, &attr, sizeof (attr));
     1630 +        if (ofile != NULL &&
     1631 +            (ofile->f_pending_attr.sa_mask & SMB_AT_MTIME) != 0) {
     1632 +                bcopy(&ofile->f_pending_attr, &attr, sizeof (attr));
1551 1633                  attr.sa_mask = SMB_AT_MTIME;
1552 1634                  (void) smb_vop_setattr(vp, u_vp, &attr, 0, kcr);
1553 1635          }
1554 1636  
1555 1637          smb_node_end_crit(snode);
1556 1638  
1557 1639          return (rc);
1558 1640  }
1559 1641  
1560 1642  /*
     1643 + * Find the next allocated range starting at or after
     1644 + * the offset (*datap), returning the start/end of
     1645 + * that range in (*datap, *holep)
     1646 + */
     1647 +int
     1648 +smb_fsop_next_alloc_range(
     1649 +    cred_t *cr,
     1650 +    smb_node_t *node,
     1651 +    off64_t *datap,
     1652 +    off64_t *holep)
     1653 +{
     1654 +        int err;
     1655 +
     1656 +        err = smb_vop_ioctl(node->vp, _FIO_SEEK_DATA, datap, cr);
     1657 +        if (err != 0)
     1658 +                return (err);
     1659 +
     1660 +        *holep = *datap;
     1661 +        err = smb_vop_ioctl(node->vp, _FIO_SEEK_HOLE, holep, cr);
     1662 +
     1663 +        return (err);
     1664 +}
     1665 +
     1666 +/*
1561 1667   * smb_fsop_statfs
1562 1668   *
1563 1669   * This is a wrapper function used for stat operations.
1564 1670   */
1565 1671  int
1566 1672  smb_fsop_statfs(
1567 1673      cred_t *cr,
1568 1674      smb_node_t *snode,
1569 1675      struct statvfs64 *statp)
1570 1676  {
↓ open down ↓ 11 lines elided ↑ open up ↑
1582 1688   * Named streams do not have separate permissions from the associated
1583 1689   * unnamed stream.  Thus, if node is a named stream, the permissions
1584 1690   * check will be performed on the associated unnamed stream.
1585 1691   *
1586 1692   * However, our named streams do have their own quarantine attribute,
1587 1693   * separate from that on the unnamed stream. If READ or EXECUTE
1588 1694   * access has been requested on a named stream, an additional access
1589 1695   * check is performed on the named stream in case it has been
1590 1696   * quarantined.  kcred is used to avoid issues with the permissions
1591 1697   * set on the extended attribute file representing the named stream.
     1698 + *
     1699 + * Note that some stream "types" are "restricted" and only
     1700 + * internal callers (cr == kcred) can access those.
1592 1701   */
1593 1702  int
1594 1703  smb_fsop_access(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
1595 1704      uint32_t faccess)
1596 1705  {
1597 1706          int access = 0;
1598 1707          int error;
1599 1708          vnode_t *dir_vp;
1600 1709          boolean_t acl_check = B_TRUE;
1601 1710          smb_node_t *unnamed_node;
↓ open down ↓ 10 lines elided ↑ open up ↑
1612 1721                      DELETE|WRITE_DAC|WRITE_OWNER)) {
1613 1722                          return (NT_STATUS_ACCESS_DENIED);
1614 1723                  }
1615 1724          }
1616 1725  
1617 1726          if (smb_node_is_reparse(snode) && (faccess & DELETE))
1618 1727                  return (NT_STATUS_ACCESS_DENIED);
1619 1728  
1620 1729          unnamed_node = SMB_IS_STREAM(snode);
1621 1730          if (unnamed_node) {
     1731 +                cred_t *kcr = zone_kcred();
     1732 +
1622 1733                  ASSERT(unnamed_node->n_magic == SMB_NODE_MAGIC);
1623 1734                  ASSERT(unnamed_node->n_state != SMB_NODE_STATE_DESTROYING);
1624 1735  
     1736 +                if (cr != kcr && smb_strname_restricted(snode->od_name))
     1737 +                        return (NT_STATUS_ACCESS_DENIED);
     1738 +
1625 1739                  /*
1626 1740                   * Perform VREAD access check on the named stream in case it
1627 1741                   * is quarantined. kcred is passed to smb_vop_access so it
1628 1742                   * doesn't fail due to lack of permission.
1629 1743                   */
1630 1744                  if (faccess & (FILE_READ_DATA | FILE_EXECUTE)) {
1631 1745                          error = smb_vop_access(snode->vp, VREAD,
1632      -                            0, NULL, zone_kcred());
     1746 +                            0, NULL, kcr);
1633 1747                          if (error)
1634 1748                                  return (NT_STATUS_ACCESS_DENIED);
1635 1749                  }
1636 1750  
1637 1751                  /*
1638 1752                   * Streams authorization should be performed against the
1639 1753                   * unnamed stream.
1640 1754                   */
1641 1755                  snode = unnamed_node;
1642 1756          }
↓ open down ↓ 42 lines elided ↑ open up ↑
1685 1799  
1686 1800                  error = smb_vop_access(snode->vp, access, 0, NULL, cr);
1687 1801          }
1688 1802  
1689 1803          return ((error) ? NT_STATUS_ACCESS_DENIED : NT_STATUS_SUCCESS);
1690 1804  }
1691 1805  
1692 1806  /*
1693 1807   * smb_fsop_lookup_name()
1694 1808   *
     1809 + * Lookup both the file and stream specified in 'name'.
1695 1810   * If name indicates that the file is a stream file, perform
1696 1811   * stream specific lookup, otherwise call smb_fsop_lookup.
1697 1812   *
     1813 + * On success, returns the found node in *ret_snode. This will be either a named
     1814 + * or unnamed stream node, depending on the name specified.
     1815 + *
1698 1816   * Return an error if the looked-up file is in outside the tree.
1699 1817   * (Required when invoked from open path.)
1700 1818   *
1701 1819   * Case sensitivity flags (SMB_IGNORE_CASE, SMB_CASE_SENSITIVE):
1702 1820   * if SMB_CASE_SENSITIVE is set, the SMB_IGNORE_CASE flag will NOT be set
1703 1821   * based on the tree's case sensitivity. However, if the SMB_IGNORE_CASE
1704 1822   * flag is set in the flags value passed as a parameter, a case insensitive
1705 1823   * lookup WILL be done (regardless of whether SMB_CASE_SENSITIVE is set
1706 1824   * or not).
1707 1825   */
↓ open down ↓ 1 lines elided ↑ open up ↑
1709 1827  int
1710 1828  smb_fsop_lookup_name(
1711 1829      smb_request_t *sr,
1712 1830      cred_t      *cr,
1713 1831      int         flags,
1714 1832      smb_node_t  *root_node,
1715 1833      smb_node_t  *dnode,
1716 1834      char        *name,
1717 1835      smb_node_t  **ret_snode)
1718 1836  {
1719      -        smb_node_t      *fnode;
1720      -        vnode_t         *xattrdirvp;
1721      -        vnode_t         *vp;
1722      -        char            *od_name;
     1837 +        char *sname = NULL;
     1838 +        int rc;
     1839 +        smb_node_t *tmp_node;
     1840 +
     1841 +        ASSERT(ret_snode != NULL);
     1842 +
     1843 +        rc = smb_fsop_lookup_file(sr, cr, flags, root_node, dnode, name,
     1844 +            &sname, ret_snode);
     1845 +
     1846 +        if (rc != 0 || sname == NULL)
     1847 +                return (rc);
     1848 +
     1849 +        tmp_node = *ret_snode;
     1850 +        rc = smb_fsop_lookup_stream(sr, cr, flags, root_node, tmp_node, sname,
     1851 +            ret_snode);
     1852 +        kmem_free(sname, MAXNAMELEN);
     1853 +        smb_node_release(tmp_node);
     1854 +
     1855 +        return (rc);
     1856 +}
     1857 +
     1858 +/*
     1859 + * smb_fsop_lookup_file()
     1860 + *
     1861 + * Look up of the file portion of 'name'. If a Stream is specified,
     1862 + * return the stream name in 'sname', which this allocates.
     1863 + * The caller must free 'sname'.
     1864 + *
     1865 + * Return an error if the looked-up file is outside the tree.
     1866 + * (Required when invoked from open path.)
     1867 + *
     1868 + * Case sensitivity flags (SMB_IGNORE_CASE, SMB_CASE_SENSITIVE):
     1869 + * if SMB_CASE_SENSITIVE is set, the SMB_IGNORE_CASE flag will NOT be set
     1870 + * based on the tree's case sensitivity. However, if the SMB_IGNORE_CASE
     1871 + * flag is set in the flags value passed as a parameter, a case insensitive
     1872 + * lookup WILL be done (regardless of whether SMB_CASE_SENSITIVE is set
     1873 + * or not).
     1874 + */
     1875 +
     1876 +int
     1877 +smb_fsop_lookup_file(
     1878 +    smb_request_t *sr,
     1879 +    cred_t      *cr,
     1880 +    int         flags,
     1881 +    smb_node_t  *root_node,
     1882 +    smb_node_t  *dnode,
     1883 +    char        *name,
     1884 +    char        **sname,
     1885 +    smb_node_t  **ret_snode)
     1886 +{
1723 1887          char            *fname;
1724      -        char            *sname;
1725 1888          int             rc;
1726 1889  
1727 1890          ASSERT(cr);
1728 1891          ASSERT(dnode);
1729 1892          ASSERT(dnode->n_magic == SMB_NODE_MAGIC);
1730 1893          ASSERT(dnode->n_state != SMB_NODE_STATE_DESTROYING);
     1894 +        ASSERT(ret_snode != NULL);
1731 1895  
1732 1896          /*
1733 1897           * The following check is required for streams processing, below
1734 1898           */
1735 1899  
1736 1900          if (!(flags & SMB_CASE_SENSITIVE)) {
1737 1901                  if (SMB_TREE_IS_CASEINSENSITIVE(sr))
1738 1902                          flags |= SMB_IGNORE_CASE;
1739 1903          }
1740 1904  
1741      -        fname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
1742      -        sname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
1743      -
     1905 +        *sname = NULL;
1744 1906          if (smb_is_stream_name(name)) {
1745      -                smb_stream_parse_name(name, fname, sname);
     1907 +                *sname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
     1908 +                fname = kmem_alloc(MAXNAMELEN, KM_SLEEP);
     1909 +                smb_stream_parse_name(name, fname, *sname);
1746 1910  
1747 1911                  /*
1748 1912                   * Look up the unnamed stream (i.e. fname).
1749 1913                   * Unmangle processing will be done on fname
1750 1914                   * as well as any link target.
1751 1915                   */
1752 1916                  rc = smb_fsop_lookup(sr, cr, flags, root_node, dnode,
1753      -                    fname, &fnode);
1754      -
1755      -                if (rc != 0) {
1756      -                        kmem_free(fname, MAXNAMELEN);
1757      -                        kmem_free(sname, MAXNAMELEN);
1758      -                        return (rc);
1759      -                }
1760      -
1761      -                od_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
1762      -
1763      -                /*
1764      -                 * od_name is the on-disk name of the stream, except
1765      -                 * without the prepended stream prefix (SMB_STREAM_PREFIX)
1766      -                 */
1767      -
1768      -                /*
1769      -                 * XXX
1770      -                 * What permissions NTFS requires for stream lookup if any?
1771      -                 */
1772      -                rc = smb_vop_stream_lookup(fnode->vp, sname, &vp, od_name,
1773      -                    &xattrdirvp, flags, root_node->vp, cr);
1774      -
1775      -                if (rc != 0) {
1776      -                        smb_node_release(fnode);
1777      -                        kmem_free(fname, MAXNAMELEN);
1778      -                        kmem_free(sname, MAXNAMELEN);
1779      -                        kmem_free(od_name, MAXNAMELEN);
1780      -                        return (rc);
1781      -                }
1782      -
1783      -                *ret_snode = smb_stream_node_lookup(sr, cr, fnode, xattrdirvp,
1784      -                    vp, od_name);
1785      -
1786      -                kmem_free(od_name, MAXNAMELEN);
1787      -                smb_node_release(fnode);
1788      -                VN_RELE(xattrdirvp);
1789      -                VN_RELE(vp);
1790      -
1791      -                if (*ret_snode == NULL) {
1792      -                        kmem_free(fname, MAXNAMELEN);
1793      -                        kmem_free(sname, MAXNAMELEN);
1794      -                        return (ENOMEM);
1795      -                }
     1917 +                    fname, ret_snode);
     1918 +                kmem_free(fname, MAXNAMELEN);
1796 1919          } else {
1797 1920                  rc = smb_fsop_lookup(sr, cr, flags, root_node, dnode, name,
1798 1921                      ret_snode);
1799 1922          }
1800 1923  
1801 1924          if (rc == 0) {
1802 1925                  ASSERT(ret_snode);
1803 1926                  if (SMB_TREE_CONTAINS_NODE(sr, *ret_snode) == 0) {
1804 1927                          smb_node_release(*ret_snode);
1805 1928                          *ret_snode = NULL;
1806 1929                          rc = EACCES;
1807 1930                  }
1808 1931          }
1809 1932  
1810      -        kmem_free(fname, MAXNAMELEN);
1811      -        kmem_free(sname, MAXNAMELEN);
     1933 +        if (rc != 0 && *sname != NULL) {
     1934 +                kmem_free(*sname, MAXNAMELEN);
     1935 +                *sname = NULL;
     1936 +        }
     1937 +        return (rc);
     1938 +}
1812 1939  
     1940 +/*
     1941 + * smb_fsop_lookup_stream
     1942 + *
     1943 + * The file exists, see if the stream exists.
     1944 + */
     1945 +int
     1946 +smb_fsop_lookup_stream(
     1947 +    smb_request_t *sr,
     1948 +    cred_t *cr,
     1949 +    int flags,
     1950 +    smb_node_t *root_node,
     1951 +    smb_node_t *fnode,
     1952 +    char *sname,
     1953 +    smb_node_t **ret_snode)
     1954 +{
     1955 +        char            *od_name;
     1956 +        vnode_t         *xattrdirvp;
     1957 +        vnode_t         *vp;
     1958 +        int rc;
     1959 +
     1960 +        /*
     1961 +         * The following check is required for streams processing, below
     1962 +         */
     1963 +
     1964 +        if (!(flags & SMB_CASE_SENSITIVE)) {
     1965 +                if (SMB_TREE_IS_CASEINSENSITIVE(sr))
     1966 +                        flags |= SMB_IGNORE_CASE;
     1967 +        }
     1968 +
     1969 +        od_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
     1970 +
     1971 +        /*
     1972 +         * od_name is the on-disk name of the stream, except
     1973 +         * without the prepended stream prefix (SMB_STREAM_PREFIX)
     1974 +         */
     1975 +
     1976 +        rc = smb_vop_stream_lookup(fnode->vp, sname, &vp, od_name,
     1977 +            &xattrdirvp, flags, root_node->vp, cr);
     1978 +
     1979 +        if (rc != 0) {
     1980 +                kmem_free(od_name, MAXNAMELEN);
     1981 +                return (rc);
     1982 +        }
     1983 +
     1984 +        *ret_snode = smb_stream_node_lookup(sr, cr, fnode, xattrdirvp,
     1985 +            vp, od_name);
     1986 +
     1987 +        kmem_free(od_name, MAXNAMELEN);
     1988 +        VN_RELE(xattrdirvp);
     1989 +        VN_RELE(vp);
     1990 +
     1991 +        if (*ret_snode == NULL)
     1992 +                return (ENOMEM);
     1993 +
1813 1994          return (rc);
1814 1995  }
1815 1996  
1816 1997  /*
1817 1998   * smb_fsop_lookup
1818 1999   *
1819 2000   * All SMB functions should use this smb_vop_lookup wrapper to ensure that
1820 2001   * the smb_vop_lookup is performed with the appropriate credentials and using
1821 2002   * case insensitive compares. Please document any direct call to smb_vop_lookup
1822 2003   * to explain the reason for avoiding this wrapper.
↓ open down ↓ 51 lines elided ↑ open up ↑
1874 2055  
1875 2056          if (!(flags & SMB_CASE_SENSITIVE)) {
1876 2057                  if (SMB_TREE_IS_CASEINSENSITIVE(sr))
1877 2058                          flags |= SMB_IGNORE_CASE;
1878 2059          }
1879 2060          if (SMB_TREE_SUPPORTS_CATIA(sr))
1880 2061                  flags |= SMB_CATIA;
1881 2062          if (SMB_TREE_SUPPORTS_ABE(sr))
1882 2063                  flags |= SMB_ABE;
1883 2064  
1884      -        od_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
     2065 +        /*
     2066 +         * Can have "" or "." when opening named streams on a directory.
     2067 +         */
     2068 +        if (name[0] == '\0' || (name[0] == '.' && name[1] == '\0')) {
     2069 +                smb_node_ref(dnode);
     2070 +                *ret_snode = dnode;
     2071 +                return (0);
     2072 +        }
1885 2073  
     2074 +        od_name = kmem_zalloc(MAXNAMELEN, KM_SLEEP);
     2075 +
1886 2076          rc = smb_vop_lookup(dnode->vp, name, &vp, od_name, flags,
1887 2077              &ret_flags, root_node ? root_node->vp : NULL, &attr, cr);
1888 2078  
1889 2079          if (rc != 0) {
1890 2080                  if (!SMB_TREE_SUPPORTS_SHORTNAMES(sr) ||
1891 2081                      !smb_maybe_mangled(name)) {
1892 2082                          kmem_free(od_name, MAXNAMELEN);
1893 2083                          return (rc);
1894 2084                  }
1895 2085  
↓ open down ↓ 24 lines elided ↑ open up ↑
1920 2110  
1921 2111                  if (rc != 0) {
1922 2112                          kmem_free(od_name, MAXNAMELEN);
1923 2113                          return (rc);
1924 2114                  }
1925 2115          }
1926 2116  
1927 2117          if ((flags & SMB_FOLLOW_LINKS) && (vp->v_type == VLNK) &&
1928 2118              ((attr.sa_dosattr & FILE_ATTRIBUTE_REPARSE_POINT) == 0)) {
1929 2119                  rc = smb_pathname(sr, od_name, FOLLOW, root_node, dnode,
1930      -                    &lnk_dnode, &lnk_target_node, cr);
     2120 +                    &lnk_dnode, &lnk_target_node, cr, NULL);
1931 2121  
1932 2122                  if (rc != 0) {
1933 2123                          /*
1934 2124                           * The link is assumed to be for the last component
1935 2125                           * of a path.  Hence any ENOTDIR error will be returned
1936 2126                           * as ENOENT.
1937 2127                           */
1938 2128                          if (rc == ENOTDIR)
1939 2129                                  rc = ENOENT;
1940 2130  
↓ open down ↓ 88 lines elided ↑ open up ↑
2029 2219   * using smb_fsacl_free() or smb_fssd_term()
2030 2220   */
2031 2221  int
2032 2222  smb_fsop_aclread(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
2033 2223      smb_fssd_t *fs_sd)
2034 2224  {
2035 2225          int error = 0;
2036 2226          int flags = 0;
2037 2227          int access = 0;
2038 2228          acl_t *acl;
2039      -        smb_node_t *unnamed_node;
2040 2229  
2041 2230          ASSERT(cr);
2042 2231  
     2232 +        /* Can't query security on named streams */
     2233 +        if (SMB_IS_STREAM(snode) != NULL)
     2234 +                return (EINVAL);
     2235 +
2043 2236          if (SMB_TREE_HAS_ACCESS(sr, ACE_READ_ACL) == 0)
2044 2237                  return (EACCES);
2045 2238  
2046 2239          if (sr->fid_ofile) {
2047 2240                  if (fs_sd->sd_secinfo & SMB_DACL_SECINFO)
2048 2241                          access = READ_CONTROL;
2049 2242  
2050 2243                  if (fs_sd->sd_secinfo & SMB_SACL_SECINFO)
2051 2244                          access |= ACCESS_SYSTEM_SECURITY;
2052 2245  
2053 2246                  error = smb_ofile_access(sr->fid_ofile, cr, access);
2054 2247                  if (error != NT_STATUS_SUCCESS) {
2055 2248                          return (EACCES);
2056 2249                  }
2057 2250          }
2058 2251  
2059      -        unnamed_node = SMB_IS_STREAM(snode);
2060      -        if (unnamed_node) {
2061      -                ASSERT(unnamed_node->n_magic == SMB_NODE_MAGIC);
2062      -                ASSERT(unnamed_node->n_state != SMB_NODE_STATE_DESTROYING);
2063      -                /*
2064      -                 * Streams don't have ACL, any read ACL attempt on a stream
2065      -                 * should be performed on the unnamed stream.
2066      -                 */
2067      -                snode = unnamed_node;
2068      -        }
2069 2252  
2070 2253          if (smb_tree_has_feature(sr->tid_tree, SMB_TREE_ACEMASKONACCESS))
2071 2254                  flags = ATTR_NOACLCHECK;
2072 2255  
2073 2256          error = smb_vop_acl_read(snode->vp, &acl, flags,
2074 2257              sr->tid_tree->t_acltype, cr);
2075 2258          if (error != 0) {
2076 2259                  return (error);
2077 2260          }
2078 2261  
↓ open down ↓ 16 lines elided ↑ open up ↑
2095 2278   */
2096 2279  int
2097 2280  smb_fsop_aclwrite(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
2098 2281      smb_fssd_t *fs_sd)
2099 2282  {
2100 2283          int target_flavor;
2101 2284          int error = 0;
2102 2285          int flags = 0;
2103 2286          int access = 0;
2104 2287          acl_t *acl, *dacl, *sacl;
2105      -        smb_node_t *unnamed_node;
2106 2288  
2107 2289          ASSERT(cr);
2108 2290  
2109 2291          ASSERT(sr);
2110 2292          ASSERT(sr->tid_tree);
2111 2293          if (SMB_TREE_IS_READONLY(sr))
2112 2294                  return (EROFS);
2113 2295  
     2296 +        /* Can't set security on named streams */
     2297 +        if (SMB_IS_STREAM(snode) != NULL)
     2298 +                return (EINVAL);
     2299 +
2114 2300          if (SMB_TREE_HAS_ACCESS(sr, ACE_WRITE_ACL) == 0)
2115 2301                  return (EACCES);
2116 2302  
2117 2303          if (sr->fid_ofile) {
2118 2304                  if (fs_sd->sd_secinfo & SMB_DACL_SECINFO)
2119 2305                          access = WRITE_DAC;
2120 2306  
2121 2307                  if (fs_sd->sd_secinfo & SMB_SACL_SECINFO)
2122 2308                          access |= ACCESS_SYSTEM_SECURITY;
2123 2309  
↓ open down ↓ 7 lines elided ↑ open up ↑
2131 2317                  target_flavor = _ACL_ACLENT_ENABLED;
2132 2318                  break;
2133 2319  
2134 2320          case ACE_T:
2135 2321                  target_flavor = _ACL_ACE_ENABLED;
2136 2322                  break;
2137 2323          default:
2138 2324                  return (EINVAL);
2139 2325          }
2140 2326  
2141      -        unnamed_node = SMB_IS_STREAM(snode);
2142      -        if (unnamed_node) {
2143      -                ASSERT(unnamed_node->n_magic == SMB_NODE_MAGIC);
2144      -                ASSERT(unnamed_node->n_state != SMB_NODE_STATE_DESTROYING);
2145      -                /*
2146      -                 * Streams don't have ACL, any write ACL attempt on a stream
2147      -                 * should be performed on the unnamed stream.
2148      -                 */
2149      -                snode = unnamed_node;
2150      -        }
2151      -
2152 2327          dacl = fs_sd->sd_zdacl;
2153 2328          sacl = fs_sd->sd_zsacl;
2154 2329  
2155 2330          ASSERT(dacl || sacl);
2156 2331          if ((dacl == NULL) && (sacl == NULL))
2157 2332                  return (EINVAL);
2158 2333  
2159 2334          if (dacl && sacl)
2160 2335                  acl = smb_fsacl_merge(dacl, sacl);
2161 2336          else if (dacl)
↓ open down ↓ 34 lines elided ↑ open up ↑
2196 2371      smb_fssd_t *fs_sd)
2197 2372  {
2198 2373          int error = 0;
2199 2374          int getowner = 0;
2200 2375          cred_t *ga_cred;
2201 2376          smb_attr_t attr;
2202 2377  
2203 2378          ASSERT(cr);
2204 2379          ASSERT(fs_sd);
2205 2380  
     2381 +        /* Can't query security on named streams */
     2382 +        if (SMB_IS_STREAM(snode) != NULL)
     2383 +                return (EINVAL);
     2384 +
2206 2385          /*
2207 2386           * File's uid/gid is fetched in two cases:
2208 2387           *
2209 2388           * 1. it's explicitly requested
2210 2389           *
2211 2390           * 2. target ACL is ACE_T (ZFS ACL). They're needed for
2212 2391           *    owner@/group@ entries. In this case kcred should be used
2213 2392           *    because uid/gid are fetched on behalf of smb server.
2214 2393           */
2215 2394          if (fs_sd->sd_secinfo & (SMB_OWNER_SECINFO | SMB_GROUP_SECINFO)) {
↓ open down ↓ 145 lines elided ↑ open up ↑
2361 2540          int access = 0;
2362 2541  
2363 2542          ASSERT(cr);
2364 2543          ASSERT(fs_sd);
2365 2544  
2366 2545          ASSERT(sr);
2367 2546          ASSERT(sr->tid_tree);
2368 2547          if (SMB_TREE_IS_READONLY(sr))
2369 2548                  return (EROFS);
2370 2549  
     2550 +        /* Can't set security on named streams */
     2551 +        if (SMB_IS_STREAM(snode) != NULL)
     2552 +                return (EINVAL);
     2553 +
2371 2554          bzero(&set_attr, sizeof (smb_attr_t));
2372 2555  
2373 2556          if (fs_sd->sd_secinfo & SMB_OWNER_SECINFO) {
2374 2557                  set_attr.sa_vattr.va_uid = fs_sd->sd_uid;
2375 2558                  set_attr.sa_mask |= SMB_AT_UID;
2376 2559                  access |= WRITE_OWNER;
2377 2560          }
2378 2561  
2379 2562          if (fs_sd->sd_secinfo & SMB_GROUP_SECINFO) {
2380 2563                  set_attr.sa_vattr.va_gid = fs_sd->sd_gid;
↓ open down ↓ 170 lines elided ↑ open up ↑
2551 2734  
2552 2735          if (access & VREAD)
2553 2736                  *eaccess |= FILE_READ_DATA;
2554 2737  
2555 2738          if (access & VEXEC)
2556 2739                  *eaccess |= FILE_EXECUTE;
2557 2740  
2558 2741          if (access & VWRITE)
2559 2742                  *eaccess |= FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES |
2560 2743                      FILE_WRITE_EA | FILE_APPEND_DATA | FILE_DELETE_CHILD;
     2744 +
     2745 +        if (access & (VREAD | VWRITE))
     2746 +                *eaccess |= SYNCHRONIZE;
     2747 +
     2748 +#ifdef  _FAKE_KERNEL
     2749 +        /* Should be: if (we are the owner)... */
     2750 +        if (access & VWRITE)
     2751 +                *eaccess |= DELETE | WRITE_DAC | WRITE_OWNER;
     2752 +#endif
2561 2753  }
2562 2754  
2563 2755  /*
2564 2756   * smb_fsop_shrlock
2565 2757   *
2566 2758   * For the current open request, check file sharing rules
2567 2759   * against existing opens.
2568 2760   *
2569 2761   * Returns NT_STATUS_SHARING_VIOLATION if there is any
2570 2762   * sharing conflict.  Returns NT_STATUS_SUCCESS otherwise.
↓ open down ↓ 60 lines elided ↑ open up ↑
2631 2823           *    file. In the case of Windows a range of zero locks nothing and
2632 2824           *    doesn't conflict with any other lock.
2633 2825           *
2634 2826           * 2) The lock rolls over (start + lenght < start). Solaris will assert
2635 2827           *    if such a request is submitted. This will not create
2636 2828           *    incompatibilities between POSIX and Windows. In the Windows world,
2637 2829           *    if a client submits such a lock, the server will not lock any
2638 2830           *    bytes. Interestingly if the same lock (same offset and length) is
2639 2831           *    resubmitted Windows will consider that there is an overlap and
2640 2832           *    the granting rules will then apply.
     2833 +         *
     2834 +         * 3) The SMB-level process IDs (smb_pid) are not passed down to the
     2835 +         *    POSIX level in l_pid because (a) the rules about lock PIDs are
     2836 +         *    different in SMB, and (b) we're putting our ofile f_uniqid in
     2837 +         *    the POSIX l_pid field to segregate locks per SMB ofile.
     2838 +         *    (We're also using a "remote" system ID in l_sysid.)
     2839 +         *    All SMB locking PIDs are handled at the SMB level and
     2840 +         *    not exposed in POSIX locking.
2641 2841           */
2642 2842          if ((lock->l_length == 0) ||
2643 2843              ((lock->l_start + lock->l_length - 1) < lock->l_start))
2644 2844                  return (0);
2645 2845  
2646 2846          bzero(&bf, sizeof (bf));
2647 2847  
2648 2848          if (unlock) {
2649 2849                  bf.l_type = F_UNLCK;
2650 2850          } else if (lock->l_type == SMB_LOCK_TYPE_READONLY) {
↓ open down ↓ 14 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX