Print this page
NEX-15580 SMB tree connect leaks memory
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15580 SMB tree connect leaks memory
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-1643 dtrace provider for smbsrv
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-4473 SMB1 tree connect missing some features
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-63 taskq_create_proc ... TQ_DYNAMIC puts tasks in p0
re #11974 CIFS Share - Tree connect fails from Windows 7 Clients


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
  24  */
  25 
  26 #include <smbsrv/smb_kproto.h>
  27 #include <smbsrv/smb_share.h>
  28 
  29 static void
  30 smb_tcon_puterror(smb_request_t *sr, uint32_t status)
  31 {
  32 
  33         switch (status) {
  34 
  35         case NT_STATUS_BAD_NETWORK_NAME:
  36                 /* Intentional status=0 */
  37                 smbsr_error(sr, 0, ERRSRV, ERRinvnetname);
  38                 break;
  39 
  40         case NT_STATUS_ACCESS_DENIED:
  41                 smbsr_error(sr, status, ERRSRV, ERRaccess);
  42                 break;
  43 


  83  * message that the server can handle.  The client should not generate
  84  * messages, nor expect to receive responses, larger than this.  This
  85  * must be constant for a given server. For newer dialects, this field
  86  * is ignored.
  87  */
  88 smb_sdrc_t
  89 smb_pre_tree_connect(smb_request_t *sr)
  90 {
  91         smb_arg_tcon_t  *tcon = &sr->sr_tcon;
  92         int             rc;
  93 
  94         /*
  95          * Perhaps this should be "%A.sA" now that unicode is enabled.
  96          */
  97         rc = smbsr_decode_data(sr, "%AAA", sr, &tcon->path,
  98             &tcon->password, &tcon->service);
  99 
 100         tcon->flags = 0;
 101         tcon->optional_support = 0;
 102 
 103         DTRACE_SMB_2(op__TreeConnect__start, smb_request_t *, sr,
 104             smb_arg_tcon_t *, tcon);
 105 
 106         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 107 }
 108 
 109 void
 110 smb_post_tree_connect(smb_request_t *sr)
 111 {
 112         DTRACE_SMB_1(op__TreeConnect__done, smb_request_t *, sr);
 113 }
 114 
 115 smb_sdrc_t
 116 smb_com_tree_connect(smb_request_t *sr)
 117 {
 118         uint32_t status;
 119         int rc;
 120 
 121         status = smb_tree_connect(sr);
 122         if (status) {
 123                 smb_tcon_puterror(sr, status);
 124                 return (SDRC_ERROR);
 125         }
 126 
 127         rc = smbsr_encode_result(sr, 2, 0, "bwww",
 128             2,                          /* wct */
 129             (WORD)smb_maxbufsize,       /* MaxBufferSize */
 130             sr->smb_tid,             /* TID */
 131             0);                         /* bcc */
 132 


 274         smb_arg_tcon_t  *tcon = &sr->sr_tcon;
 275         uint8_t         *pwbuf = NULL;
 276         uint16_t        pwlen = 0;
 277         int             rc;
 278 
 279         rc = smbsr_decode_vwv(sr, "b.www", &sr->andx_com, &sr->andx_off,
 280             &tcon->flags, &pwlen);
 281         if (rc == 0) {
 282                 if (pwlen != 0)
 283                         pwbuf = smb_srm_zalloc(sr, pwlen);
 284 
 285                 rc = smbsr_decode_data(sr, "%#cus", sr, pwlen, pwbuf,
 286                     &tcon->path, &tcon->service);
 287 
 288                 tcon->pwdlen = pwlen;
 289                 tcon->password = (char *)pwbuf;
 290         }
 291 
 292         tcon->optional_support = 0;
 293 
 294         DTRACE_SMB_2(op__TreeConnectX__start, smb_request_t *, sr,
 295             smb_arg_tcon_t *, tcon);
 296 
 297         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 298 }
 299 
 300 void
 301 smb_post_tree_connect_andx(smb_request_t *sr)
 302 {
 303         DTRACE_SMB_1(op__TreeConnectX__done, smb_request_t *, sr);
 304 }
 305 
 306 smb_sdrc_t
 307 smb_com_tree_connect_andx(smb_request_t *sr)
 308 {
 309         smb_arg_tcon_t  *tcon = &sr->sr_tcon;

 310         char            *service;
 311         uint32_t        status;
 312         int             rc;
 313 








 314         status = smb_tree_connect(sr);
 315         if (status) {
 316                 smb_tcon_puterror(sr, status);
 317                 return (SDRC_ERROR);
 318         }

 319 
 320         switch (sr->tid_tree->t_res_type & STYPE_MASK) {
 321         case STYPE_IPC:
 322                 service = "IPC";
 323                 break;
 324         case STYPE_PRINTQ:
 325                 service = "LPT1:";
 326                 break;
 327         case STYPE_DISKTREE:
 328         default:
 329                 service = "A:";
 330         }
 331 
 332         if (sr->session->dialect < NT_LM_0_12) {
 333                 rc = smbsr_encode_result(sr, 2, VAR_BCC, "bb.wwss",
 334                     (char)2,            /* wct */
 335                     sr->andx_com,
 336                     VAR_BCC,
 337                     VAR_BCC,

 338                     service,
 339                     sr->tid_tree->t_typename);
 340         } else {
 341                 rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.wwws%u",
 342                     (char)3,            /* wct */
 343                     sr->andx_com,
 344                     (short)64,
 345                     tcon->optional_support,
 346                     VAR_BCC,
 347                     service,
 348                     sr,
 349                     sr->tid_tree->t_typename);














 350         }
 351 
 352         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 353 }
 354 
 355 /*
 356  * SmbTreeDisconnect: Disconnect a tree.
 357  *
 358  * Note: SDDF_SUPPRESS_UID is set for this operation, which means the sr
 359  * uid_user field will not be valid on entry to these functions.  Do not
 360  * use it until it is set up in smb_com_tree_disconnect() or the system
 361  * will panic.
 362  *
 363  * Note: there are scenarios in which the client does not send a tree
 364  * disconnect request, for example, when ERRbaduid is returned from
 365  * SmbReadX after a user has logged off.  Any open files will remain
 366  * around until the session is destroyed.
 367  *
 368  * Client Request                     Description
 369  * ================================== =================================


 375  * logically disconnected from the server. Tid is invalidated; it will not
 376  * be recognized if used by the client for subsequent requests. All locks,
 377  * open files, etc. created on behalf of Tid are released.
 378  *
 379  * Server Response                    Description
 380  * ================================== =================================
 381  *
 382  * UCHAR WordCount;                   Count of parameter words = 0
 383  * USHORT ByteCount;                  Count of data bytes = 0
 384  *
 385  * Errors:
 386  * ERRSRV/ERRinvnid
 387  * ERRSRV/ERRbaduid
 388  */
 389 smb_sdrc_t
 390 smb_pre_tree_disconnect(smb_request_t *sr)
 391 {
 392         sr->uid_user = smb_session_lookup_uid(sr->session, sr->smb_uid);
 393         sr->tid_tree = smb_session_lookup_tree(sr->session, sr->smb_tid);
 394 
 395         DTRACE_SMB_1(op__TreeDisconnect__start, smb_request_t *, sr);
 396         return (SDRC_SUCCESS);
 397 }
 398 
 399 void
 400 smb_post_tree_disconnect(smb_request_t *sr)
 401 {
 402         DTRACE_SMB_1(op__TreeDisconnect__done, smb_request_t *, sr);
 403 }
 404 
 405 /*
 406  * SmbTreeDisconnect requires a valid UID as well as a valid TID.  Some
 407  * clients logoff a user and then try to disconnect the trees connected
 408  * by the user who has just been logged off, which would normally fail
 409  * in the dispatch code with ERRbaduid but, unfortunately, ERRbaduid
 410  * causes a problem for some of those clients.  Windows returns ERRinvnid.
 411  *
 412  * To prevent ERRbaduid being returned, the UID and TID are looked up here
 413  * rather than prior to dispatching SmbTreeDisconnect requests.  If either
 414  * the UID or the TID is invalid, ERRinvnid is returned.
 415  */
 416 smb_sdrc_t
 417 smb_com_tree_disconnect(smb_request_t *sr)
 418 {
 419         if (sr->uid_user == NULL || sr->tid_tree == NULL) {
 420                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRinvnid);
 421                 return (SDRC_ERROR);
 422         }
 423 
 424         sr->user_cr = smb_user_getcred(sr->uid_user);
 425 
 426         smb_session_cancel_requests(sr->session, sr->tid_tree, sr);
 427         smb_tree_disconnect(sr->tid_tree, B_TRUE);

 428 
 429         if (smbsr_encode_empty_result(sr))
 430                 return (SDRC_ERROR);
 431 
 432         return (SDRC_SUCCESS);
 433 }


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
  24  */
  25 
  26 #include <smbsrv/smb_kproto.h>
  27 #include <smbsrv/smb_share.h>
  28 
  29 static void
  30 smb_tcon_puterror(smb_request_t *sr, uint32_t status)
  31 {
  32 
  33         switch (status) {
  34 
  35         case NT_STATUS_BAD_NETWORK_NAME:
  36                 /* Intentional status=0 */
  37                 smbsr_error(sr, 0, ERRSRV, ERRinvnetname);
  38                 break;
  39 
  40         case NT_STATUS_ACCESS_DENIED:
  41                 smbsr_error(sr, status, ERRSRV, ERRaccess);
  42                 break;
  43 


  83  * message that the server can handle.  The client should not generate
  84  * messages, nor expect to receive responses, larger than this.  This
  85  * must be constant for a given server. For newer dialects, this field
  86  * is ignored.
  87  */
  88 smb_sdrc_t
  89 smb_pre_tree_connect(smb_request_t *sr)
  90 {
  91         smb_arg_tcon_t  *tcon = &sr->sr_tcon;
  92         int             rc;
  93 
  94         /*
  95          * Perhaps this should be "%A.sA" now that unicode is enabled.
  96          */
  97         rc = smbsr_decode_data(sr, "%AAA", sr, &tcon->path,
  98             &tcon->password, &tcon->service);
  99 
 100         tcon->flags = 0;
 101         tcon->optional_support = 0;
 102 
 103         DTRACE_SMB_START(op__TreeConnect, smb_request_t *, sr);

 104 
 105         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 106 }
 107 
 108 void
 109 smb_post_tree_connect(smb_request_t *sr)
 110 {
 111         DTRACE_SMB_DONE(op__TreeConnect, smb_request_t *, sr);
 112 }
 113 
 114 smb_sdrc_t
 115 smb_com_tree_connect(smb_request_t *sr)
 116 {
 117         uint32_t status;
 118         int rc;
 119 
 120         status = smb_tree_connect(sr);
 121         if (status) {
 122                 smb_tcon_puterror(sr, status);
 123                 return (SDRC_ERROR);
 124         }
 125 
 126         rc = smbsr_encode_result(sr, 2, 0, "bwww",
 127             2,                          /* wct */
 128             (WORD)smb_maxbufsize,       /* MaxBufferSize */
 129             sr->smb_tid,             /* TID */
 130             0);                         /* bcc */
 131 


 273         smb_arg_tcon_t  *tcon = &sr->sr_tcon;
 274         uint8_t         *pwbuf = NULL;
 275         uint16_t        pwlen = 0;
 276         int             rc;
 277 
 278         rc = smbsr_decode_vwv(sr, "b.www", &sr->andx_com, &sr->andx_off,
 279             &tcon->flags, &pwlen);
 280         if (rc == 0) {
 281                 if (pwlen != 0)
 282                         pwbuf = smb_srm_zalloc(sr, pwlen);
 283 
 284                 rc = smbsr_decode_data(sr, "%#cus", sr, pwlen, pwbuf,
 285                     &tcon->path, &tcon->service);
 286 
 287                 tcon->pwdlen = pwlen;
 288                 tcon->password = (char *)pwbuf;
 289         }
 290 
 291         tcon->optional_support = 0;
 292 
 293         DTRACE_SMB_START(op__TreeConnectX, smb_request_t *, sr);

 294 
 295         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 296 }
 297 
 298 void
 299 smb_post_tree_connect_andx(smb_request_t *sr)
 300 {
 301         DTRACE_SMB_DONE(op__TreeConnectX, smb_request_t *, sr);
 302 }
 303 
 304 smb_sdrc_t
 305 smb_com_tree_connect_andx(smb_request_t *sr)
 306 {
 307         smb_arg_tcon_t  *tcon = &sr->sr_tcon;
 308         smb_tree_t      *tree;
 309         char            *service;
 310         uint32_t        status;
 311         int             rc;
 312 
 313         if (tcon->flags & SMB_TCONX_DISCONECT_TID) {
 314                 tree = smb_session_lookup_tree(sr->session, sr->smb_tid);
 315                 if (tree != NULL) {
 316                         smb_tree_disconnect(tree, B_TRUE);
 317                         smb_session_cancel_requests(sr->session, tree, sr);
 318                 }
 319         }
 320 
 321         status = smb_tree_connect(sr);
 322         if (status) {
 323                 smb_tcon_puterror(sr, status);
 324                 return (SDRC_ERROR);
 325         }
 326         tree = sr->tid_tree;
 327 
 328         switch (tree->t_res_type & STYPE_MASK) {
 329         case STYPE_IPC:
 330                 service = "IPC";
 331                 break;
 332         case STYPE_PRINTQ:
 333                 service = "LPT1:";
 334                 break;
 335         case STYPE_DISKTREE:
 336         default:
 337                 service = "A:";
 338         }
 339 
 340         if (sr->session->dialect < NT_LM_0_12) {
 341                 rc = smbsr_encode_result(sr, 2, VAR_BCC, "bb.ww%ss",
 342                     (char)2,            /* wct */
 343                     sr->andx_com,
 344                     VAR_BCC,
 345                     VAR_BCC,
 346                     sr,
 347                     service,
 348                     tree->t_typename);
 349         } else if ((tcon->flags & SMB_TCONX_EXTENDED_RESPONSE) == 0) {
 350                 rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.www%su",
 351                     (char)3,            /* wct */
 352                     sr->andx_com,
 353                     (short)64,
 354                     tcon->optional_support,
 355                     VAR_BCC,

 356                     sr,
 357                     service,
 358                     tree->t_typename);
 359 
 360         } else {
 361                 rc = smbsr_encode_result(sr, 7, VAR_BCC, "bb.wwllw%su",
 362                     (char)7,            /* wct (b) */
 363                     sr->andx_com,    /* AndXcmd (b) */
 364                     (short)72,          /* AndXoff (w) */
 365                     tcon->optional_support,  /* (w) */
 366                     tree->t_access,          /* (l) */
 367                     0,          /*    guest_access (l) */
 368                     VAR_BCC,            /* (w) */
 369                     sr,                 /* (%) */
 370                     service,            /* (s) */
 371                     tree->t_typename);       /* (u) */
 372         }
 373 
 374         return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
 375 }
 376 
 377 /*
 378  * SmbTreeDisconnect: Disconnect a tree.
 379  *
 380  * Note: SDDF_SUPPRESS_UID is set for this operation, which means the sr
 381  * uid_user field will not be valid on entry to these functions.  Do not
 382  * use it until it is set up in smb_com_tree_disconnect() or the system
 383  * will panic.
 384  *
 385  * Note: there are scenarios in which the client does not send a tree
 386  * disconnect request, for example, when ERRbaduid is returned from
 387  * SmbReadX after a user has logged off.  Any open files will remain
 388  * around until the session is destroyed.
 389  *
 390  * Client Request                     Description
 391  * ================================== =================================


 397  * logically disconnected from the server. Tid is invalidated; it will not
 398  * be recognized if used by the client for subsequent requests. All locks,
 399  * open files, etc. created on behalf of Tid are released.
 400  *
 401  * Server Response                    Description
 402  * ================================== =================================
 403  *
 404  * UCHAR WordCount;                   Count of parameter words = 0
 405  * USHORT ByteCount;                  Count of data bytes = 0
 406  *
 407  * Errors:
 408  * ERRSRV/ERRinvnid
 409  * ERRSRV/ERRbaduid
 410  */
 411 smb_sdrc_t
 412 smb_pre_tree_disconnect(smb_request_t *sr)
 413 {
 414         sr->uid_user = smb_session_lookup_uid(sr->session, sr->smb_uid);
 415         sr->tid_tree = smb_session_lookup_tree(sr->session, sr->smb_tid);
 416 
 417         DTRACE_SMB_START(op__TreeDisconnect, smb_request_t *, sr);
 418         return (SDRC_SUCCESS);
 419 }
 420 
 421 void
 422 smb_post_tree_disconnect(smb_request_t *sr)
 423 {
 424         DTRACE_SMB_DONE(op__TreeDisconnect, smb_request_t *, sr);
 425 }
 426 
 427 /*
 428  * SmbTreeDisconnect requires a valid UID as well as a valid TID.  Some
 429  * clients logoff a user and then try to disconnect the trees connected
 430  * by the user who has just been logged off, which would normally fail
 431  * in the dispatch code with ERRbaduid but, unfortunately, ERRbaduid
 432  * causes a problem for some of those clients.  Windows returns ERRinvnid.
 433  *
 434  * To prevent ERRbaduid being returned, the UID and TID are looked up here
 435  * rather than prior to dispatching SmbTreeDisconnect requests.  If either
 436  * the UID or the TID is invalid, ERRinvnid is returned.
 437  */
 438 smb_sdrc_t
 439 smb_com_tree_disconnect(smb_request_t *sr)
 440 {
 441         if (sr->uid_user == NULL || sr->tid_tree == NULL) {
 442                 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRinvnid);
 443                 return (SDRC_ERROR);
 444         }
 445 
 446         sr->user_cr = smb_user_getcred(sr->uid_user);
 447 

 448         smb_tree_disconnect(sr->tid_tree, B_TRUE);
 449         smb_session_cancel_requests(sr->session, sr->tid_tree, sr);
 450 
 451         if (smbsr_encode_empty_result(sr))
 452                 return (SDRC_ERROR);
 453 
 454         return (SDRC_SUCCESS);
 455 }