Print this page
NEX-14666 Need to provide SMB 2.1 Client
NEX-17187 panic in smbfs_acl_store
NEX-17231 smbfs create xattr files finds wrong file
NEX-17224 smbfs lookup EINVAL should be ENOENT
NEX-17260 SMB1 client fails to list directory after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
and: (cleanup)
NEX-15578 SMB2 durable handle redesign
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-15578 SMB2 durable handle redesign
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-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-4538 SMB1 create file should support extended_response format (2)
NEX-6116 Failures in smbtorture raw.open
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Include this commit if upstreaming/backporting any of:
NEX-4540 SMB server declines EA support incorrectly
NEX-4239 smbtorture create failures re. allocation size
(illumos) 6398 SMB should support path names longer than 1024
NEX-4538 SMB1 create file should support extended_response format
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
NEX-2522 svcadm disable network/smb/server may hang
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-3662 Backport illumos 1501: taskq_create_proc ... TQ_DYNAMIC puts tasks in p0 (take 2)
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Dan McDonald <danmcd@omniti.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Marcel Telka <marcel.telka@nexenta.com>
NEX-3576 RPC error when displaying open files via Windows MMC
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-2188 Browsing top level share produces RPC error 1728
SMB-119 Text file contains garbage when re-opened
SMB-120 Share enumeration fails with Windows 8
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-39 Use AF_UNIX pipes for RPC
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 (data structure changes)
Many things move to the smb_server_t object, and
many functions gain an sv arg (which server).
SMB-65 SMB server in non-global zones (kmem_caches)
common kmem_cache instances across zones
separate GZ-only init from NGZ init
SMB-63 taskq_create_proc ... TQ_DYNAMIC puts tasks in p0
re #11974 CIFS Share - Tree connect fails from Windows 7 Clients
re #6812 rb1753 backport illumos 1604 smbd print_enable doesn't really work

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/smbsrv/smb_opipe.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb_opipe.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  /*
  27   27   * This module provides the interface to NDR RPC.
  28   28   */
  29   29  
  30   30  #include <sys/stat.h>
  31   31  #include <sys/uio.h>
  32   32  #include <sys/ksynch.h>
  33   33  #include <sys/stropts.h>
  34   34  #include <sys/socket.h>
  35   35  #include <sys/filio.h>
  36   36  #include <smbsrv/smb_kproto.h>
  37   37  #include <smbsrv/smb_xdr.h>
  38      -#include <smbsrv/winioctl.h>
       38 +#include <smb/winioctl.h>
  39   39  
  40      -static uint32_t smb_opipe_transceive(smb_request_t *, smb_fsctl_t *);
  41      -
  42   40  /*
  43   41   * Allocate a new opipe and return it, or NULL, in which case
  44   42   * the caller will report "internal error".
  45   43   */
  46   44  static smb_opipe_t *
  47   45  smb_opipe_alloc(smb_request_t *sr)
  48   46  {
  49   47          smb_server_t    *sv = sr->sr_server;
  50   48          smb_opipe_t     *opipe;
  51   49          ksocket_t       sock;
↓ open down ↓ 38 lines elided ↑ open up ↑
  90   88                  (void) ksocket_close(opipe->p_socket, zone_kcred());
  91   89  
  92   90          opipe->p_magic = (uint32_t)~SMB_OPIPE_MAGIC;
  93   91          cv_destroy(&opipe->p_cv);
  94   92          mutex_destroy(&opipe->p_mutex);
  95   93  
  96   94          kmem_cache_free(smb_cache_opipe, opipe);
  97   95  }
  98   96  
  99   97  /*
       98 + * Unblock a request that might be blocked reading some
       99 + * pipe (AF_UNIX socket).  We don't have an easy way to
      100 + * interrupt just the thread servicing this request, so
      101 + * we shutdown(3socket) the socket, waking all readers.
      102 + * That's a bit heavy-handed, making the socket unusable
      103 + * after this, so we do this only when disconnecting a
      104 + * session (i.e. stopping the SMB service), and not when
      105 + * handling an SMB2_cancel or SMB_nt_cancel request.
      106 + */
      107 +static void
      108 +smb_opipe_cancel(smb_request_t *sr)
      109 +{
      110 +        ksocket_t so;
      111 +
      112 +        switch (sr->session->s_state) {
      113 +        case SMB_SESSION_STATE_DISCONNECTED:
      114 +        case SMB_SESSION_STATE_TERMINATED:
      115 +                if ((so = sr->cancel_arg2) != NULL)
      116 +                        (void) ksocket_shutdown(so, SHUT_RDWR, sr->user_cr);
      117 +                break;
      118 +        }
      119 +}
      120 +
      121 +/*
 100  122   * Helper for open: build pipe name and connect.
 101  123   */
 102  124  static int
 103  125  smb_opipe_connect(smb_request_t *sr, smb_opipe_t *opipe)
 104  126  {
 105  127          struct sockaddr_un saddr;
 106  128          smb_arg_open_t  *op = &sr->sr_open;
 107  129          const char *name;
 108  130          int rc;
 109  131  
↓ open down ↓ 50 lines elided ↑ open up ↑
 160  182  
 161  183          buflen = sizeof (phdr) + phdr.ph_uilen;
 162  184          buf = kmem_alloc(buflen, KM_SLEEP);
 163  185  
 164  186          bcopy(&phdr, buf, sizeof (phdr));
 165  187          xdrmem_create(&xdrs, buf + sizeof (phdr),
 166  188              buflen - (sizeof (phdr)), XDR_ENCODE);
 167  189          if (!smb_netuserinfo_xdr(&xdrs, &nui))
 168  190                  goto out;
 169  191  
 170      -        /*
 171      -         * If we fail sending the netuserinfo or recv'ing the
 172      -         * status reponse, we have probably run into the limit
 173      -         * on the number of open pipes.  That's this status:
 174      -         */
 175      -        errp->status = NT_STATUS_PIPE_NOT_AVAILABLE;
      192 +        mutex_enter(&sr->sr_mutex);
      193 +        if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
      194 +                mutex_exit(&sr->sr_mutex);
      195 +                errp->status = NT_STATUS_CANCELLED;
      196 +                goto out;
      197 +        }
      198 +        sr->sr_state = SMB_REQ_STATE_WAITING_PIPE;
      199 +        sr->cancel_method = smb_opipe_cancel;
      200 +        sr->cancel_arg2 = opipe->p_socket;
      201 +        mutex_exit(&sr->sr_mutex);
 176  202  
 177  203          rc = ksocket_send(opipe->p_socket, buf, buflen, 0,
 178  204              &iocnt, sr->user_cr);
 179  205          if (rc == 0 && iocnt != buflen)
 180  206                  rc = EIO;
 181      -        if (rc != 0)
 182      -                goto out;
      207 +        if (rc == 0)
      208 +                rc = ksocket_recv(opipe->p_socket, &status, sizeof (status),
      209 +                    0, &iocnt, sr->user_cr);
      210 +        if (rc == 0 && iocnt != sizeof (status))
      211 +                rc = EIO;
 183  212  
 184      -        rc = ksocket_recv(opipe->p_socket, &status, sizeof (status), 0,
 185      -            &iocnt, sr->user_cr);
 186      -        if (rc != 0 || iocnt != sizeof (status))
 187      -                goto out;
      213 +        mutex_enter(&sr->sr_mutex);
      214 +        sr->cancel_method = NULL;
      215 +        sr->cancel_arg2 = NULL;
      216 +        switch (sr->sr_state) {
      217 +        case SMB_REQ_STATE_WAITING_PIPE:
      218 +                sr->sr_state = SMB_REQ_STATE_ACTIVE;
      219 +                break;
      220 +        case SMB_REQ_STATE_CANCEL_PENDING:
      221 +                sr->sr_state = SMB_REQ_STATE_CANCELLED;
      222 +                rc = EINTR;
      223 +                break;
      224 +        default:
      225 +                /* keep rc from above */
      226 +                break;
      227 +        }
      228 +        mutex_exit(&sr->sr_mutex);
 188  229  
      230 +
 189  231          /*
 190  232           * Return the status we read from the pipe service,
 191  233           * normally NT_STATUS_SUCCESS, but could be something
 192  234           * else like NT_STATUS_ACCESS_DENIED.
 193  235           */
 194      -        errp->status = status;
      236 +        switch (rc) {
      237 +        case 0:
      238 +                errp->status = status;
      239 +                break;
      240 +        case EINTR:
      241 +                errp->status = NT_STATUS_CANCELLED;
      242 +                break;
      243 +        /*
      244 +         * If we fail sending the netuserinfo or recv'ing the
      245 +         * status reponse, we have probably run into the limit
      246 +         * on the number of open pipes.  That's this status:
      247 +         */
      248 +        default:
      249 +                errp->status = NT_STATUS_PIPE_NOT_AVAILABLE;
      250 +                break;
      251 +        }
 195  252  
 196  253  out:
 197  254          xdr_destroy(&xdrs);
 198  255          kmem_free(buf, buflen);
 199  256          smb_user_netinfo_fini(&nui);
 200  257  }
 201  258  
 202  259  /*
 203  260   * smb_opipe_open
 204  261   *
 205  262   * Open an RPC named pipe. This routine should be called if
 206  263   * a file open is requested on a share of type STYPE_IPC.
 207  264   * If we recognize the pipe, we setup a new ofile.
 208  265   *
 209  266   * Returns 0 on success, Otherwise an NT status code.
 210  267   */
 211  268  int
 212      -smb_opipe_open(smb_request_t *sr, uint32_t uniqid)
      269 +smb_opipe_open(smb_request_t *sr, smb_ofile_t *ofile)
 213  270  {
 214  271          smb_arg_open_t  *op = &sr->sr_open;
 215      -        smb_ofile_t *ofile;
      272 +        smb_attr_t *ap = &op->fqi.fq_fattr;
 216  273          smb_opipe_t *opipe;
 217  274          smb_error_t err;
 218  275  
 219  276          opipe = smb_opipe_alloc(sr);
 220  277          if (opipe == NULL)
 221  278                  return (NT_STATUS_INTERNAL_ERROR);
 222  279  
 223  280          if (smb_opipe_connect(sr, opipe) != 0) {
 224  281                  smb_opipe_dealloc(opipe);
 225  282                  return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
 226  283          }
 227  284  
 228  285          smb_opipe_send_userinfo(sr, opipe, &err);
 229  286          if (err.status != 0) {
 230  287                  smb_opipe_dealloc(opipe);
 231  288                  return (err.status);
 232  289          }
 233  290  
 234  291          /*
 235      -         * Note: If smb_ofile_open succeeds, the new ofile is
 236      -         * in the FID lists can can be used by I/O requests.
      292 +         * We might have blocked in smb_opipe_connect long enough so
      293 +         * a tree disconnect might have happened.  In that case, we
      294 +         * would be adding an ofile to a tree that's disconnecting,
      295 +         * which would interfere with tear-down.
 237  296           */
 238      -        op->create_options = 0;
 239      -        op->pipe = opipe;
 240      -        ofile = smb_ofile_open(sr, NULL, op,
 241      -            SMB_FTYPE_MESG_PIPE, uniqid, &err);
 242      -        op->pipe = NULL;
 243      -        if (ofile == NULL) {
      297 +        if (!smb_tree_is_connected(sr->tid_tree)) {
 244  298                  smb_opipe_dealloc(opipe);
 245      -                return (err.status);
      299 +                return (NT_STATUS_NETWORK_NAME_DELETED);
 246  300          }
 247  301  
      302 +        /*
      303 +         * Note: The new opipe is given to smb_ofile_open
      304 +         * via op->pipe
      305 +         */
      306 +        op->pipe = opipe;
      307 +        smb_ofile_open(sr, op, ofile);
      308 +        op->pipe = NULL;
      309 +
 248  310          /* An "up" pointer, for debug. */
 249  311          opipe->p_ofile = ofile;
 250  312  
 251      -        op->dsize = 0x01000;
 252      -        op->dattr = FILE_ATTRIBUTE_NORMAL;
      313 +        /*
      314 +         * Caller expects attributes in op->fqi
      315 +         */
      316 +        (void) smb_opipe_getattr(ofile, &op->fqi.fq_fattr);
      317 +
      318 +        op->dsize = 0;
      319 +        op->dattr = ap->sa_dosattr;
      320 +        op->fileid = ap->sa_vattr.va_nodeid;
 253  321          op->ftype = SMB_FTYPE_MESG_PIPE;
 254      -        op->action_taken = SMB_OACT_LOCK | SMB_OACT_OPENED; /* 0x8001 */
      322 +        op->action_taken = SMB_OACT_OPLOCK | SMB_OACT_OPENED;
 255  323          op->devstate = SMB_PIPE_READMODE_MESSAGE
 256  324              | SMB_PIPE_TYPE_MESSAGE
 257  325              | SMB_PIPE_UNLIMITED_INSTANCES; /* 0x05ff */
 258      -        op->fileid = ofile->f_fid;
 259  326  
 260  327          sr->smb_fid = ofile->f_fid;
 261  328          sr->fid_ofile = ofile;
 262  329  
 263  330          return (NT_STATUS_SUCCESS);
 264  331  }
 265  332  
 266  333  /*
 267  334   * smb_opipe_close
 268  335   *
↓ open down ↓ 96 lines elided ↑ open up ↑
 365  432          SMB_OPIPE_VALID(opipe);
 366  433  
 367  434          mutex_enter(&opipe->p_mutex);
 368  435          sock = opipe->p_socket;
 369  436          if (sock != NULL)
 370  437                  ksocket_hold(sock);
 371  438          mutex_exit(&opipe->p_mutex);
 372  439          if (sock == NULL)
 373  440                  return (EBADF);
 374  441  
 375      -        bzero(&msghdr, sizeof (msghdr));
 376      -        msghdr.msg_iov = uio->uio_iov;
 377      -        msghdr.msg_iovlen = uio->uio_iovcnt;
      442 +        mutex_enter(&sr->sr_mutex);
      443 +        if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
      444 +                mutex_exit(&sr->sr_mutex);
      445 +                rc = EINTR;
      446 +                goto out;
      447 +        }
      448 +        sr->sr_state = SMB_REQ_STATE_WAITING_PIPE;
      449 +        sr->cancel_method = smb_opipe_cancel;
      450 +        sr->cancel_arg2 = sock;
      451 +        mutex_exit(&sr->sr_mutex);
 378  452  
 379  453          /*
 380  454           * This should block only if there's no data.
 381  455           * A single call to recvmsg does just that.
 382  456           * (Intentionaly no recv loop here.)
 383  457           */
      458 +        bzero(&msghdr, sizeof (msghdr));
      459 +        msghdr.msg_iov = uio->uio_iov;
      460 +        msghdr.msg_iovlen = uio->uio_iovcnt;
 384  461          rc = ksocket_recvmsg(sock, &msghdr, 0,
 385  462              &recvcnt, ofile->f_cr);
      463 +
      464 +        mutex_enter(&sr->sr_mutex);
      465 +        sr->cancel_method = NULL;
      466 +        sr->cancel_arg2 = NULL;
      467 +        switch (sr->sr_state) {
      468 +        case SMB_REQ_STATE_WAITING_PIPE:
      469 +                sr->sr_state = SMB_REQ_STATE_ACTIVE;
      470 +                break;
      471 +        case SMB_REQ_STATE_CANCEL_PENDING:
      472 +                sr->sr_state = SMB_REQ_STATE_CANCELLED;
      473 +                rc = EINTR;
      474 +                break;
      475 +        default:
      476 +                /* keep rc from above */
      477 +                break;
      478 +        }
      479 +        mutex_exit(&sr->sr_mutex);
      480 +
 386  481          if (rc != 0)
 387  482                  goto out;
 388  483  
 389  484          if (recvcnt == 0) {
 390  485                  /* Other side closed. */
 391  486                  rc = EPIPE;
 392  487                  goto out;
 393  488          }
 394  489          uio->uio_resid -= recvcnt;
 395  490  
↓ open down ↓ 37 lines elided ↑ open up ↑
 433  528   */
 434  529  int
 435  530  smb_opipe_getattr(smb_ofile_t *of, smb_attr_t *ap)
 436  531  {
 437  532  
 438  533          if (of->f_pipe == NULL)
 439  534                  return (EINVAL);
 440  535  
 441  536          ap->sa_vattr.va_type = VFIFO;
 442  537          ap->sa_vattr.va_nlink = 1;
      538 +        ap->sa_vattr.va_nodeid = (uintptr_t)of->f_pipe;
 443  539          ap->sa_dosattr = FILE_ATTRIBUTE_NORMAL;
 444      -        ap->sa_allocsz = 0x1000LL;
      540 +        ap->sa_allocsz = SMB_PIPE_MAX_MSGSIZE;
 445  541  
 446  542          return (0);
 447  543  }
 448  544  
 449  545  int
 450  546  smb_opipe_getname(smb_ofile_t *of, char *buf, size_t buflen)
 451  547  {
 452  548          smb_opipe_t *opipe;
 453  549  
 454  550          if ((opipe = of->f_pipe) == NULL)
 455  551                  return (EINVAL);
 456  552  
 457  553          (void) snprintf(buf, buflen, "\\%s", opipe->p_name);
 458  554          return (0);
 459  555  }
 460  556  
 461  557  /*
 462      - * Handler for smb2_ioctl
      558 + * Handle device type FILE_DEVICE_NAMED_PIPE
      559 + * for smb2_ioctl
 463  560   */
 464  561  /* ARGSUSED */
 465  562  uint32_t
 466  563  smb_opipe_fsctl(smb_request_t *sr, smb_fsctl_t *fsctl)
 467  564  {
 468  565          uint32_t status;
 469  566  
      567 +        if (!STYPE_ISIPC(sr->tid_tree->t_res_type))
      568 +                return (NT_STATUS_INVALID_DEVICE_REQUEST);
      569 +
 470  570          switch (fsctl->CtlCode) {
 471  571          case FSCTL_PIPE_TRANSCEIVE:
 472  572                  status = smb_opipe_transceive(sr, fsctl);
 473  573                  break;
 474  574  
 475  575          case FSCTL_PIPE_PEEK:
 476  576          case FSCTL_PIPE_WAIT:
 477  577                  /* XXX todo */
 478  578                  status = NT_STATUS_NOT_SUPPORTED;
 479  579                  break;
 480  580  
 481  581          default:
 482  582                  ASSERT(!"CtlCode");
 483  583                  status = NT_STATUS_INTERNAL_ERROR;
 484  584                  break;
 485  585          }
 486  586  
 487  587          return (status);
 488  588  }
 489  589  
 490      -static uint32_t
      590 +uint32_t
 491  591  smb_opipe_transceive(smb_request_t *sr, smb_fsctl_t *fsctl)
 492  592  {
 493  593          smb_vdb_t       vdb;
 494  594          smb_ofile_t     *ofile;
 495  595          struct mbuf     *mb;
 496  596          uint32_t        status;
 497  597          int             len, rc;
 498  598  
 499  599          /*
 500  600           * Caller checked that this is the IPC$ share,
↓ open down ↓ 57 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX