Print this page
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-15069 smtorture smb2.create.blob is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-4083 Upstream changes from illumos 5917 and 5995
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
SMB-50 User-mode SMB server
 Includes work by these authors:
 Thomas Keiser <thomas.keiser@nexenta.com>
 Albert Lee <trisk@nexenta.com>
SMB-65 SMB server in non-global zones (use zone_kcred())
SMB-65 SMB server in non-global zones (data structure changes)
Many things move to the smb_server_t object, and
many functions gain an sv arg (which server).

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/smbsrv/smb_mangle_name.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb_mangle_name.c
↓ open down ↓ 12 lines elided ↑ open up ↑
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23      - * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
       23 + * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
  24   24   */
  25   25  
  26   26  #include <sys/types.h>
  27   27  #include <sys/param.h>
  28   28  #include <sys/sunddi.h>
  29   29  #include <sys/errno.h>
  30   30  #include <sys/extdirent.h>
  31   31  #include <smbsrv/string.h>
  32   32  #include <smbsrv/smb_vops.h>
  33   33  #include <smbsrv/smb_kproto.h>
↓ open down ↓ 310 lines elided ↑ open up ↑
 344  344  
 345  345  /*
 346  346   * smb_unmangle
 347  347   *
 348  348   * Given a mangled name, try to find the real file name as it appears
 349  349   * in the directory entry.
 350  350   *
 351  351   * smb_unmangle should only be called on names for which
 352  352   * smb_maybe_mangled() is true
 353  353   *
 354      - * File systems which support VFSFT_EDIRENT_FLAGS will return the
 355      - * directory entries as a buffer of edirent_t structure. Others will
 356      - * return a buffer of dirent64_t structures. A union is used for the
 357      - * the pointer into the buffer (bufptr, edp and dp).
 358      - * The ed_name/d_name is NULL terminated by the file system.
      354 + * The flags arg is no longer used, but retained just to avoid
      355 + * changing the many callers of this function.
 359  356   *
 360  357   * Returns:
 361  358   *   0       - SUCCESS. Unmangled name is returned in namebuf.
 362  359   *   EINVAL  - a parameter was invalid.
 363  360   *   ENOTDIR - dnode is not a directory node.
 364  361   *   ENOENT  - an unmangled name could not be found.
 365  362   */
 366  363  #define SMB_UNMANGLE_BUFSIZE    (4 * 1024)
 367  364  int
 368  365  smb_unmangle(smb_node_t *dnode, char *name, char *namebuf,
 369  366      int buflen, uint32_t flags)
 370  367  {
 371      -        int             err, eof, bufsize, reclen;
      368 +        _NOTE(ARGUNUSED(flags)) // avoid changing all callers
      369 +        int             err, eof, bufsize;
 372  370          uint64_t        offset;
 373  371          ino64_t         ino;
 374      -        boolean_t       is_edp;
 375  372          char            *namep, *buf;
 376  373          char            shortname[SMB_SHORTNAMELEN];
 377  374          vnode_t         *vp;
 378      -        union {
 379      -                char            *u_bufptr;
 380      -                edirent_t       *u_edp;
 381      -                dirent64_t      *u_dp;
 382      -        } u;
 383      -#define bufptr          u.u_bufptr
 384      -#define edp             u.u_edp
 385      -#define dp              u.u_dp
      375 +        char            *bufptr;
      376 +        dirent64_t      *dp;
      377 +        cred_t          *cr = zone_kcred();
      378 +        int             rc = ENOENT;
 386  379  
 387  380          if (dnode == NULL || name == NULL || namebuf == NULL || buflen == 0)
 388  381                  return (EINVAL);
 389  382  
 390  383          ASSERT(smb_maybe_mangled(name) == B_TRUE);
 391  384  
 392  385          if (!smb_node_is_dir(dnode))
 393  386                  return (ENOTDIR);
 394  387  
 395  388          vp = dnode->vp;
 396  389          *namebuf = '\0';
 397      -        is_edp = vfs_has_feature(vp->v_vfsp, VFSFT_DIRENTFLAGS);
 398  390  
 399  391          buf = kmem_alloc(SMB_UNMANGLE_BUFSIZE, KM_SLEEP);
 400      -        bufsize = SMB_UNMANGLE_BUFSIZE;
 401      -        offset = 0;
      392 +        bufptr = buf;
      393 +        bufsize = 0;
      394 +        offset = 0;     // next entry offset
      395 +        eof = B_FALSE;
 402  396  
 403      -        while ((err = smb_vop_readdir(vp, offset, buf, &bufsize,
 404      -            &eof, flags, zone_kcred())) == 0) {
 405      -                if (bufsize == 0) {
 406      -                        err = ENOENT;
 407      -                        break;
      397 +        for (;;) {
      398 +                /*
      399 +                 * Read some entries, if buffer empty or
      400 +                 * we've scanned all of it.  Flags zero
      401 +                 * (no edirent, no ABE wanted here)
      402 +                 */
      403 +                if (bufsize <= 0) {
      404 +                        bufsize = SMB_UNMANGLE_BUFSIZE;
      405 +                        rc = smb_vop_readdir(vp, offset, buf,
      406 +                            &bufsize, &eof, 0, cr);
      407 +                        if (rc != 0)
      408 +                                break; /* error */
      409 +                        if (bufsize == 0) {
      410 +                                eof = B_TRUE;
      411 +                                rc = ENOENT;
      412 +                                break;
      413 +                        }
      414 +                        bufptr = buf;
 408  415                  }
      416 +                /* LINTED pointer alignment */
      417 +                dp = (dirent64_t *)bufptr;
 409  418  
 410      -                bufptr = buf;
 411      -                reclen = 0;
      419 +                /*
      420 +                 * Partial records are not supposed to happen,
      421 +                 * but let's be defensive. If this happens,
      422 +                 * restart at the current offset.
      423 +                 */
      424 +                bufptr += dp->d_reclen;
      425 +                bufsize -= dp->d_reclen;
      426 +                if (bufsize < 0)
      427 +                        continue;
 412  428  
 413      -                while ((bufptr += reclen) < buf + bufsize) {
 414      -                        if (is_edp) {
 415      -                                reclen = edp->ed_reclen;
 416      -                                offset = edp->ed_off;
 417      -                                ino = edp->ed_ino;
 418      -                                namep = edp->ed_name;
 419      -                        } else {
 420      -                                reclen = dp->d_reclen;
 421      -                                offset = dp->d_off;
 422      -                                ino = dp->d_ino;
 423      -                                namep = dp->d_name;
 424      -                        }
      429 +                offset = dp->d_off;
      430 +                ino = dp->d_ino;
      431 +                namep = dp->d_name;
 425  432  
 426      -                        /* skip non utf8 filename */
 427      -                        if (u8_validate(namep, strlen(namep), NULL,
 428      -                            U8_VALIDATE_ENTIRE, &err) < 0)
 429      -                                continue;
      433 +                /* skip non utf8 filename */
      434 +                if (u8_validate(namep, strlen(namep), NULL,
      435 +                    U8_VALIDATE_ENTIRE, &err) < 0)
      436 +                        continue;
 430  437  
 431      -                        smb_mangle(namep, ino, shortname, SMB_SHORTNAMELEN);
 432      -
 433      -                        if (smb_strcasecmp(name, shortname, 0) == 0) {
 434      -                                (void) strlcpy(namebuf, namep, buflen);
 435      -                                kmem_free(buf, SMB_UNMANGLE_BUFSIZE);
 436      -                                return (0);
 437      -                        }
 438      -                }
 439      -
 440      -                if (eof) {
 441      -                        err = ENOENT;
      438 +                smb_mangle(namep, ino, shortname, SMB_SHORTNAMELEN);
      439 +                if (smb_strcasecmp(name, shortname, 0) == 0) {
      440 +                        (void) strlcpy(namebuf, namep, buflen);
      441 +                        rc = 0;
 442  442                          break;
 443  443                  }
 444      -
 445      -                bufsize = SMB_UNMANGLE_BUFSIZE;
 446  444          }
 447  445  
 448  446          kmem_free(buf, SMB_UNMANGLE_BUFSIZE);
 449      -        return (err);
      447 +        return (rc);
 450  448  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX