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>


  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 /*
  23  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 /*
  27  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  28  * Use is subject to license terms.
  29  */



  30 
  31 #include <sys/param.h>
  32 #include <sys/types.h>
  33 #include <sys/systm.h>
  34 #include <sys/cred.h>
  35 #include <sys/buf.h>
  36 #include <sys/vfs.h>
  37 #include <sys/vnode.h>
  38 #include <sys/uio.h>
  39 #include <sys/errno.h>
  40 #include <sys/sysmacros.h>
  41 #include <sys/statvfs.h>
  42 #include <sys/kmem.h>
  43 #include <sys/dirent.h>
  44 #include <rpc/types.h>
  45 #include <rpc/auth.h>
  46 #include <rpc/rpcsec_gss.h>
  47 #include <rpc/svc.h>
  48 #include <sys/strsubr.h>
  49 #include <sys/strsun.h>


 757                                             FATTR4_FILES_AVAIL_MASK |
 758                                             FATTR4_FILES_FREE_MASK |
 759                                             FATTR4_FILES_TOTAL_MASK);
 760                                         rddirattr_error = error;
 761                                 }
 762                         }
 763                         if (ar & (FATTR4_MAXFILESIZE_MASK |
 764                             FATTR4_MAXLINK_MASK |
 765                             FATTR4_MAXNAME_MASK)) {
 766                                 if (error = rfs4_get_pc_encode(cs->vp,
 767                                     &pce, ar, cs->cr)) {
 768                                         ar &= ~(FATTR4_MAXFILESIZE_MASK |
 769                                             FATTR4_MAXLINK_MASK |
 770                                             FATTR4_MAXNAME_MASK);
 771                                         rddirattr_error = error;
 772                                 }
 773                         }
 774                 }
 775 
 776 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                 name = nfscmd_convname(ca, cs->exi, dp->d_name,
 783                     NFSCMD_CONV_OUTBOUND, MAXPATHLEN + 1);
 784 
 785                 if (name == NULL) {
 786                         rddir_next_offset = dp->d_off;
 787                         continue;
 788                 }
 789                 /* Calculate the dirent name length */
 790                 namelen = strlen(name);
 791 
 792                 rndup = RNDUP(namelen) / BYTES_PER_XDR_UNIT;
 793 
 794                 /* room for LENGTH + string ? */
 795                 if ((ptr + (1 + rndup)) > ptr_redzone) {
 796                         no_space = TRUE;


 797                         continue;
 798                 }
 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                 /*
 813                  * Keep checking on the dircount to see if we have
 814                  * reached the limit; from the RFC, dircount is to be
 815                  * the XDR encoded limit of the cookie plus name.
 816                  * So the count is the name, XDR_UNIT of length for
 817                  * that name and 2 * XDR_UNIT bytes of cookie;
 818                  * However, use the regular DIRENT64 to match most
 819                  * client's APIs.
 820                  */
 821                 dircount -= DIRENT64_RECLEN(namelen);
 822                 if (nents != 0 && dircount < 0) {
 823                         no_space = TRUE;


 824                         continue;
 825                 }
 826 

















 827                 /*
 828                  * Attributes requested?
 829                  * Gather up the attribute info and the previous VOP_LOOKUP()
 830                  * succeeded; if an error occurs on the VOP_GETATTR() then
 831                  * return just the error (again if it is requested).
 832                  * Note that the previous VOP_LOOKUP() could have failed
 833                  * itself which leaves this code without anything for
 834                  * a VOP_GETATTR().
 835                  * Also note that the readdir_attr_error is left in the
 836                  * encoding mask if requested and so is the mounted_on_fileid.
 837                  */
 838                 if (ae != 0) {
 839                         if (!vp) {
 840                                 ae = ar & (FATTR4_RDATTR_ERROR_MASK |
 841                                     FATTR4_MOUNTED_ON_FILEID_MASK);
 842                         } else {
 843                                 va.va_mask = AT_ALL;
 844                                 rddirattr_error =
 845                                     VOP_GETATTR(vp, &va, 0, cs->cr, NULL);
 846                                 if (rddirattr_error) {




  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 /*
  23  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 /*
  27  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  28  * Use is subject to license terms.
  29  */
  30 /*
  31  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  32  */
  33 
  34 #include <sys/param.h>
  35 #include <sys/types.h>
  36 #include <sys/systm.h>
  37 #include <sys/cred.h>
  38 #include <sys/buf.h>
  39 #include <sys/vfs.h>
  40 #include <sys/vnode.h>
  41 #include <sys/uio.h>
  42 #include <sys/errno.h>
  43 #include <sys/sysmacros.h>
  44 #include <sys/statvfs.h>
  45 #include <sys/kmem.h>
  46 #include <sys/dirent.h>
  47 #include <rpc/types.h>
  48 #include <rpc/auth.h>
  49 #include <rpc/rpcsec_gss.h>
  50 #include <rpc/svc.h>
  51 #include <sys/strsubr.h>
  52 #include <sys/strsun.h>


 760                                             FATTR4_FILES_AVAIL_MASK |
 761                                             FATTR4_FILES_FREE_MASK |
 762                                             FATTR4_FILES_TOTAL_MASK);
 763                                         rddirattr_error = error;
 764                                 }
 765                         }
 766                         if (ar & (FATTR4_MAXFILESIZE_MASK |
 767                             FATTR4_MAXLINK_MASK |
 768                             FATTR4_MAXNAME_MASK)) {
 769                                 if (error = rfs4_get_pc_encode(cs->vp,
 770                                     &pce, ar, cs->cr)) {
 771                                         ar &= ~(FATTR4_MAXFILESIZE_MASK |
 772                                             FATTR4_MAXLINK_MASK |
 773                                             FATTR4_MAXNAME_MASK);
 774                                         rddirattr_error = error;
 775                                 }
 776                         }
 777                 }
 778 
 779 reencode_attrs:





 780                 name = nfscmd_convname(ca, cs->exi, dp->d_name,
 781                     NFSCMD_CONV_OUTBOUND, MAXPATHLEN + 1);
 782 
 783                 if (name == NULL) {
 784                         rddir_next_offset = dp->d_off;
 785                         continue;
 786                 }
 787                 /* Calculate the dirent name length */
 788                 namelen = strlen(name);
 789 
 790                 rndup = RNDUP(namelen) / BYTES_PER_XDR_UNIT;
 791 
 792                 /* room for LENGTH + string ? */
 793                 if ((ptr + (1 + rndup)) > ptr_redzone) {
 794                         no_space = TRUE;
 795                         if (name != dp->d_name)
 796                                 kmem_free(name, MAXPATHLEN + 1);
 797                         continue;
 798                 }
 799 












 800                 /*
 801                  * Keep checking on the dircount to see if we have
 802                  * reached the limit; from the RFC, dircount is to be
 803                  * the XDR encoded limit of the cookie plus name.
 804                  * So the count is the name, XDR_UNIT of length for
 805                  * that name and 2 * XDR_UNIT bytes of cookie;
 806                  * However, use the regular DIRENT64 to match most
 807                  * client's APIs.
 808                  */
 809                 dircount -= DIRENT64_RECLEN(namelen);
 810                 if (nents != 0 && dircount < 0) {
 811                         no_space = TRUE;
 812                         if (name != dp->d_name)
 813                                 kmem_free(name, MAXPATHLEN + 1);
 814                         continue;
 815                 }
 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 
 834                 /*
 835                  * Attributes requested?
 836                  * Gather up the attribute info and the previous VOP_LOOKUP()
 837                  * succeeded; if an error occurs on the VOP_GETATTR() then
 838                  * return just the error (again if it is requested).
 839                  * Note that the previous VOP_LOOKUP() could have failed
 840                  * itself which leaves this code without anything for
 841                  * a VOP_GETATTR().
 842                  * Also note that the readdir_attr_error is left in the
 843                  * encoding mask if requested and so is the mounted_on_fileid.
 844                  */
 845                 if (ae != 0) {
 846                         if (!vp) {
 847                                 ae = ar & (FATTR4_RDATTR_ERROR_MASK |
 848                                     FATTR4_MOUNTED_ON_FILEID_MASK);
 849                         } else {
 850                                 va.va_mask = AT_ALL;
 851                                 rddirattr_error =
 852                                     VOP_GETATTR(vp, &va, 0, cs->cr, NULL);
 853                                 if (rddirattr_error) {