Print this page
OS-20 share_nfs(1m) charset handling is unreliable
OS-22 Page fault at nfscmd_dropped_entrysize+0x1e()
OS-23 NFSv2/3/4: READDIR responses are inconsistent when charset conversion fails
OS-24 rfs3_readdir(): Issues related to nfscmd_convdirent()
Reviewed by: Jan Kryl <jan.kryl@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/nfs/nfs4_srv_readdir.c
          +++ new/usr/src/uts/common/fs/nfs/nfs4_srv_readdir.c
↓ open down ↓ 19 lines elided ↑ open up ↑
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  24   24   */
  25   25  
  26   26  /*
  27   27   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  28   28   * Use is subject to license terms.
  29   29   */
       30 +/*
       31 + * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
       32 + */
  30   33  
  31   34  #include <sys/param.h>
  32   35  #include <sys/types.h>
  33   36  #include <sys/systm.h>
  34   37  #include <sys/cred.h>
  35   38  #include <sys/buf.h>
  36   39  #include <sys/vfs.h>
  37   40  #include <sys/vnode.h>
  38   41  #include <sys/uio.h>
  39   42  #include <sys/errno.h>
↓ open down ↓ 727 lines elided ↑ open up ↑
 767  770                                      &pce, ar, cs->cr)) {
 768  771                                          ar &= ~(FATTR4_MAXFILESIZE_MASK |
 769  772                                              FATTR4_MAXLINK_MASK |
 770  773                                              FATTR4_MAXNAME_MASK);
 771  774                                          rddirattr_error = error;
 772  775                                  }
 773  776                          }
 774  777                  }
 775  778  
 776  779  reencode_attrs:
 777      -                /* encode the BOOLEAN for the existence of the next entry */
 778      -                IXDR_PUT_U_INT32(ptr, true);
 779      -                /* encode the COOKIE for the entry */
 780      -                IXDR_PUT_U_HYPER(ptr, dp->d_off);
 781      -
 782  780                  name = nfscmd_convname(ca, cs->exi, dp->d_name,
 783  781                      NFSCMD_CONV_OUTBOUND, MAXPATHLEN + 1);
 784  782  
 785  783                  if (name == NULL) {
 786  784                          rddir_next_offset = dp->d_off;
 787  785                          continue;
 788  786                  }
 789  787                  /* Calculate the dirent name length */
 790  788                  namelen = strlen(name);
 791  789  
 792  790                  rndup = RNDUP(namelen) / BYTES_PER_XDR_UNIT;
 793  791  
 794  792                  /* room for LENGTH + string ? */
 795  793                  if ((ptr + (1 + rndup)) > ptr_redzone) {
 796  794                          no_space = TRUE;
      795 +                        if (name != dp->d_name)
      796 +                                kmem_free(name, MAXPATHLEN + 1);
 797  797                          continue;
 798  798                  }
 799  799  
 800      -                /* encode the LENGTH of the name */
 801      -                IXDR_PUT_U_INT32(ptr, namelen);
 802      -                /* encode the RNDUP FILL first */
 803      -                ptr[rndup - 1] = 0;
 804      -                /* encode the NAME of the entry */
 805      -                bcopy(name, (char *)ptr, namelen);
 806      -                /* now bump the ptr after... */
 807      -                ptr += rndup;
 808      -
 809      -                if (name != dp->d_name)
 810      -                        kmem_free(name, MAXPATHLEN + 1);
 811      -
 812  800                  /*
 813  801                   * Keep checking on the dircount to see if we have
 814  802                   * reached the limit; from the RFC, dircount is to be
 815  803                   * the XDR encoded limit of the cookie plus name.
 816  804                   * So the count is the name, XDR_UNIT of length for
 817  805                   * that name and 2 * XDR_UNIT bytes of cookie;
 818  806                   * However, use the regular DIRENT64 to match most
 819  807                   * client's APIs.
 820  808                   */
 821  809                  dircount -= DIRENT64_RECLEN(namelen);
 822  810                  if (nents != 0 && dircount < 0) {
 823  811                          no_space = TRUE;
      812 +                        if (name != dp->d_name)
      813 +                                kmem_free(name, MAXPATHLEN + 1);
 824  814                          continue;
 825  815                  }
 826  816  
      817 +                /* encode the BOOLEAN for the existence of the next entry */
      818 +                IXDR_PUT_U_INT32(ptr, true);
      819 +                /* encode the COOKIE for the entry */
      820 +                IXDR_PUT_U_HYPER(ptr, dp->d_off);
      821 +
      822 +                /* encode the LENGTH of the name */
      823 +                IXDR_PUT_U_INT32(ptr, namelen);
      824 +                /* encode the RNDUP FILL first */
      825 +                ptr[rndup - 1] = 0;
      826 +                /* encode the NAME of the entry */
      827 +                bcopy(name, (char *)ptr, namelen);
      828 +                /* now bump the ptr after... */
      829 +                ptr += rndup;
      830 +
      831 +                if (name != dp->d_name)
      832 +                        kmem_free(name, MAXPATHLEN + 1);
      833 +
 827  834                  /*
 828  835                   * Attributes requested?
 829  836                   * Gather up the attribute info and the previous VOP_LOOKUP()
 830  837                   * succeeded; if an error occurs on the VOP_GETATTR() then
 831  838                   * return just the error (again if it is requested).
 832  839                   * Note that the previous VOP_LOOKUP() could have failed
 833  840                   * itself which leaves this code without anything for
 834  841                   * a VOP_GETATTR().
 835  842                   * Also note that the readdir_attr_error is left in the
 836  843                   * encoding mask if requested and so is the mounted_on_fileid.
↓ open down ↓ 718 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX