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-16818 Add fksmbcl development tool
NEX-17264 SMB client test tp_smbutil_013 fails after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
and: (fix ref leaks)

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_xattr.c
          +++ new/usr/src/uts/common/fs/smbclnt/smbfs/smbfs_xattr.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  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  /*
  23   23   * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
       24 + * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  24   25   */
  25   26  
  26   27  /*
  27   28   * Functions supporting Solaris Extended Attributes,
  28   29   * used to provide access to CIFS "named streams".
  29   30   */
  30   31  
  31   32  #include <sys/systm.h>
       33 +#include <sys/inttypes.h>
  32   34  #include <sys/cred.h>
  33   35  #include <sys/vnode.h>
  34   36  #include <sys/vfs.h>
  35   37  #include <sys/filio.h>
  36   38  #include <sys/uio.h>
  37   39  #include <sys/dirent.h>
  38   40  #include <sys/errno.h>
  39   41  #include <sys/sysmacros.h>
  40   42  #include <sys/kmem.h>
  41   43  #include <sys/stat.h>
  42   44  #include <sys/cmn_err.h>
  43   45  #include <sys/u8_textprep.h>
  44   46  
  45   47  #include <netsmb/smb_osdep.h>
       48 +
  46   49  #include <netsmb/smb.h>
       50 +#include <netsmb/smb2.h>
  47   51  #include <netsmb/smb_conn.h>
  48   52  #include <netsmb/smb_subr.h>
  49   53  #include <netsmb/smb_rq.h>
  50   54  
  51   55  #include <smbfs/smbfs.h>
  52   56  #include <smbfs/smbfs_node.h>
  53   57  #include <smbfs/smbfs_subr.h>
  54   58  
  55   59  #include <fs/fs_subr.h>
  56   60  
↓ open down ↓ 225 lines elided ↑ open up ↑
 282  286          error = smbfs_smb_lookup(pnp, &name, &nlen, fap, scrp);
 283  287          if (error == 0 && name != sname)
 284  288                  smbfs_name_free(name, nlen);
 285  289  
 286  290          VN_RELE(pvp);
 287  291  
 288  292          return (error);
 289  293  }
 290  294  
 291  295  /*
 292      - * Fetch the entire attribute list here in findopen.
 293      - * Will parse the results in findnext.
      296 + * Actually go OtW to get the list of "streams".
 294  297   *
 295  298   * This is called on the XATTR directory, so we
 296  299   * have to get the (real) parent object first.
 297  300   */
 298      -/* ARGSUSED */
 299      -int
 300      -smbfs_xa_findopen(struct smbfs_fctx *ctx, struct smbnode *dnp,
 301      -        const char *wildcard, int wclen)
      301 +static int
      302 +smbfs_xa_get_streaminfo(struct smbfs_fctx *ctx)
 302  303  {
 303  304          vnode_t *pvp;   /* parent */
 304  305          smbnode_t *pnp;
 305      -        struct smb_t2rq *t2p;
 306      -        struct smb_vc *vcp = SSTOVC(ctx->f_ssp);
 307      -        struct mbchain *mbp;
      306 +        smbnode_t *dnp = ctx->f_dnp;
      307 +        struct mdchain *mdp;
 308  308          int error;
 309  309  
 310      -        ASSERT(dnp->n_flag & N_XATTR);
 311      -
 312      -        ctx->f_type = ft_XA;
 313      -        ctx->f_namesz = SMB_MAXFNAMELEN + 1;
 314      -        if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp)))
 315      -                ctx->f_namesz *= 2;
 316      -        ctx->f_name = kmem_alloc(ctx->f_namesz, KM_SLEEP);
 317      -
 318  310          error = smbfs_xa_parent(SMBTOV(dnp), &pvp);
 319  311          if (error)
 320  312                  return (error);
 321  313          ASSERT(pvp);
 322  314          /* Note: pvp has a VN_HOLD */
 323  315          pnp = VTOSMB(pvp);
 324  316  
 325      -        if (ctx->f_t2) {
 326      -                smb_t2_done(ctx->f_t2);
 327      -                ctx->f_t2 = NULL;
 328      -        }
      317 +        /*
      318 +         * Get stream info into f_mdchain
      319 +         */
      320 +        mdp = &ctx->f_mdchain;
      321 +        md_done(mdp);
 329  322  
 330      -        error = smb_t2_alloc(SSTOCP(ctx->f_ssp),
 331      -            SMB_TRANS2_QUERY_PATH_INFORMATION,
 332      -            ctx->f_scred, &t2p);
      323 +        if (SSTOVC(ctx->f_ssp)->vc_flags & SMBV_SMB2) {
      324 +                error = smbfs_smb2_get_streaminfo(pnp, mdp, ctx->f_scred);
      325 +        } else {
      326 +                error = smbfs_smb1_get_streaminfo(pnp, mdp, ctx->f_scred);
      327 +        }
 333  328          if (error)
 334  329                  goto out;
 335      -        ctx->f_t2 = t2p;
 336  330  
 337      -        mbp = &t2p->t2_tparam;
 338      -        (void) mb_init(mbp);
 339      -        (void) mb_put_uint16le(mbp, SMB_QFILEINFO_STREAM_INFO);
 340      -        (void) mb_put_uint32le(mbp, 0);
 341      -        error = smbfs_fullpath(mbp, vcp, pnp, NULL, NULL, 0);
 342      -        if (error)
 343      -                goto out;
 344      -        t2p->t2_maxpcount = 2;
 345      -        t2p->t2_maxdcount = INT16_MAX;
 346      -        error = smb_t2_request(t2p);
 347      -        if (error) {
 348      -                if (t2p->t2_sr_error == NT_STATUS_INVALID_PARAMETER)
 349      -                        error = ENOTSUP;
 350      -        }
 351  331          /*
 352      -         * No returned parameters to parse.
 353      -         * Returned data are in t2_rdata,
 354      -         * which we'll parse in _findnext.
 355      -         * However, save the wildcard.
      332 +         * Have stream info in ctx->f_mdchain
      333 +         * Initialize buffer length, position.
 356  334           */
 357      -        ctx->f_wildcard = wildcard;
 358      -        ctx->f_wclen = wclen;
      335 +        ctx->f_left = m_fixhdr(mdp->md_top);
      336 +        ctx->f_eofs = 0;
 359  337  
      338 +        /*
      339 +         * After one successful call, we're at EOF.
      340 +         */
      341 +        ctx->f_flags |= SMBFS_RDD_EOF;
      342 +
 360  343  out:
 361  344          VN_RELE(pvp);
 362  345          return (error);
 363  346  }
 364  347  
 365  348  /*
 366      - * Get the next name in an XATTR directory into f_name
      349 + * Get a buffer of directory entries (if we don't already have
      350 + * some remaining in the current buffer) then decode one.
 367  351   */
 368      -/* ARGSUSED */
 369  352  int
 370      -smbfs_xa_findnext(struct smbfs_fctx *ctx, uint16_t limit)
      353 +smbfs_xa_findopen(struct smbfs_fctx *ctx, struct smbnode *dnp,
      354 +        const char *wildcard, int wclen)
 371  355  {
 372      -        struct mdchain *mdp;
 373      -        struct smb_t2rq *t2p;
 374      -        uint32_t size, next;
 375      -        uint64_t llongint;
 376      -        int error, skip, used, nmlen;
 377  356  
 378      -        t2p = ctx->f_t2;
 379      -        mdp = &t2p->t2_rdata;
      357 +        ASSERT(dnp->n_flag & N_XATTR);
 380  358  
 381      -        if (ctx->f_flags & SMBFS_RDD_FINDSINGLE) {
 382      -                ASSERT(ctx->f_wildcard);
 383      -                SMBVDEBUG("wildcard: %s\n", ctx->f_wildcard);
 384      -        }
      359 +        ctx->f_type = ft_XA;
      360 +        ctx->f_namesz = SMB_MAXFNAMELEN + 1;
      361 +        ctx->f_name = kmem_alloc(ctx->f_namesz, KM_SLEEP);
      362 +        ctx->f_infolevel = FileStreamInformation;
      363 +        ctx->f_wildcard = wildcard;
      364 +        ctx->f_wclen = wclen;
 385  365  
 386      -again:
 387      -        if (ctx->f_flags & SMBFS_RDD_EOF)
 388      -                return (ENOENT);
      366 +        return (0);
      367 +}
 389  368  
 390      -        /* Parse FILE_STREAM_INFORMATION */
 391      -        if ((error = md_get_uint32le(mdp, &next)) != 0) /* offset to */
 392      -                return (ENOENT);
 393      -        if ((error = md_get_uint32le(mdp, &size)) != 0) /* name len */
 394      -                return (ENOENT);
 395      -        (void) md_get_uint64le(mdp, &llongint); /* file size */
 396      -        ctx->f_attr.fa_size = llongint;
 397      -        (void) md_get_uint64le(mdp, NULL);      /* alloc. size */
 398      -        used = 4 + 4 + 8 + 8;   /* how much we consumed */
 399  369  
      370 +/*
      371 + * Get the next name in an XATTR directory
      372 + */
      373 +/* ARGSUSED */
      374 +int
      375 +smbfs_xa_findnext(struct smbfs_fctx *ctx, uint16_t limit)
      376 +{
      377 +        int error;
      378 +
 400  379          /*
 401      -         * Copy the string, but skip the first char (":")
 402      -         * Watch out for zero-length strings here.
      380 +         * If we've scanned to the end of the current buffer
      381 +         * try to read anohther buffer of dir entries.
      382 +         * Treat anything less than 8 bytes as an "empty"
      383 +         * buffer to ensure we can read something.
      384 +         * (There may be up to 8 bytes of padding.)
 403  385           */
 404      -        if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp))) {
 405      -                if (size >= 2) {
 406      -                        size -= 2; used += 2;
 407      -                        (void) md_get_uint16le(mdp, NULL);
 408      -                }
 409      -                nmlen = min(size, SMB_MAXFNAMELEN * 2);
 410      -        } else {
 411      -                if (size >= 1) {
 412      -                        size -= 1; used += 1;
 413      -                        (void) md_get_uint8(mdp, NULL);
 414      -                }
 415      -                nmlen = min(size, SMB_MAXFNAMELEN);
      386 +again:
      387 +        if ((ctx->f_eofs + 8) > ctx->f_left) {
      388 +                /* Scanned the whole buffer. */
      389 +                if (ctx->f_flags & SMBFS_RDD_EOF)
      390 +                        return (ENOENT);
      391 +                ctx->f_limit = limit;
      392 +                error = smbfs_xa_get_streaminfo(ctx);
      393 +                if (error)
      394 +                        return (error);
      395 +                ctx->f_otws++;
 416  396          }
 417  397  
 418      -        ASSERT(nmlen < ctx->f_namesz);
 419      -        ctx->f_nmlen = nmlen;
 420      -        error = md_get_mem(mdp, ctx->f_name, nmlen, MB_MSYSTEM);
      398 +        /*
      399 +         * Decode one entry, advance f_eofs
      400 +         */
      401 +        error = smbfs_decode_dirent(ctx);
 421  402          if (error)
 422  403                  return (error);
 423      -        used += nmlen;
      404 +        SMBVDEBUG("name: %s\n", ctx->f_name);
 424  405  
 425  406          /*
 426      -         * Convert UCS-2 to UTF-8
 427      -         */
 428      -        smbfs_fname_tolocal(ctx);
 429      -        if (nmlen)
 430      -                SMBVDEBUG("name: %s\n", ctx->f_name);
 431      -        else
 432      -                SMBVDEBUG("null name!\n");
 433      -
 434      -        /*
 435      -         * Skip padding until next offset
 436      -         */
 437      -        if (next > used) {
 438      -                skip = next - used;
 439      -                (void) md_get_mem(mdp, NULL, skip, MB_MSYSTEM);
 440      -        }
 441      -        if (next == 0)
 442      -                ctx->f_flags |= SMBFS_RDD_EOF;
 443      -
 444      -        /*
 445  407           * Chop off the trailing ":$DATA"
 446  408           * The 6 here is strlen(":$DATA")
 447  409           */
 448  410          if (ctx->f_nmlen >= 6) {
 449  411                  char *p = ctx->f_name + ctx->f_nmlen - 6;
 450  412                  if (strncmp(p, ":$DATA", 6) == 0) {
 451  413                          *p = '\0'; /* Chop! */
 452  414                          ctx->f_nmlen -= 6;
 453  415                  }
 454  416          }
 455  417  
 456  418          /*
 457  419           * The Chop above will typically leave
 458  420           * an empty name in the first slot,
 459  421           * which we will skip here.
 460  422           */
 461  423          if (ctx->f_nmlen == 0)
 462  424                  goto again;
 463  425  
 464  426          /*
 465      -         * If this is a lookup of a specific name,
 466      -         * skip past any non-matching names.
      427 +         * When called by lookup, we'll have the "single" flag,
      428 +         * and a name with no wildcards.  We need to filter here
      429 +         * because smbfs_xa_get_streaminfo() gets ALL the names
      430 +         * (not just those matching our pattern).
 467  431           */
 468  432          if (ctx->f_flags & SMBFS_RDD_FINDSINGLE) {
 469  433                  if (ctx->f_wclen != ctx->f_nmlen)
 470  434                          goto again;
 471  435                  if (u8_strcmp(ctx->f_wildcard, ctx->f_name,
 472  436                      ctx->f_nmlen, U8_STRCMP_CI_LOWER,
 473  437                      U8_UNICODE_LATEST, &error) || error)
 474  438                          goto again;
 475  439          }
 476  440  
↓ open down ↓ 4 lines elided ↑ open up ↑
 481  445   * Find first/next/close for XATTR directories.
 482  446   * NB: also used by smbfs_smb_lookup
 483  447   */
 484  448  
 485  449  int
 486  450  smbfs_xa_findclose(struct smbfs_fctx *ctx)
 487  451  {
 488  452  
 489  453          if (ctx->f_name)
 490  454                  kmem_free(ctx->f_name, ctx->f_namesz);
 491      -        if (ctx->f_t2)
 492      -                smb_t2_done(ctx->f_t2);
 493  455  
 494  456          return (0);
 495  457  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX