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>


   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 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */



  25 
  26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
  27 /* All Rights Reserved */
  28 
  29 #include <sys/param.h>
  30 #include <sys/types.h>
  31 #include <sys/systm.h>
  32 #include <sys/user.h>
  33 #include <sys/vnode.h>
  34 #include <sys/file.h>
  35 #include <sys/dirent.h>
  36 #include <sys/vfs.h>
  37 #include <sys/stream.h>
  38 #include <sys/strsubr.h>
  39 #include <sys/debug.h>
  40 #include <sys/t_lock.h>
  41 #include <sys/sdt.h>
  42 
  43 #include <rpc/types.h>
  44 #include <rpc/xdr.h>


 754  *              u_int   de_fid;
 755  *              string  de_name<NFS_MAXNAMELEN>;
 756  *      }
 757  */
 758 
 759 #ifdef nextdp
 760 #undef  nextdp
 761 #endif
 762 #define nextdp(dp)      ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
 763 #ifdef roundup
 764 #undef  roundup
 765 #endif
 766 #define roundup(x, y)   ((((x) + ((y) - 1)) / (y)) * (y))
 767 
 768 /*
 769  * ENCODE ONLY
 770  */
 771 bool_t
 772 xdr_putrddirres(XDR *xdrs, struct nfsrddirres *rd)
 773 {
 774         struct dirent64 *dp;
 775         char *name;
 776         int size;
 777         uint_t namlen;
 778         bool_t true = TRUE;
 779         bool_t false = FALSE;
 780         int entrysz;
 781         int tofit;
 782         int bufsize;
 783         uint32_t ino, off;
 784 
 785         if (xdrs->x_op != XDR_ENCODE)
 786                 return (FALSE);
 787         if (!xdr_enum(xdrs, (enum_t *)&rd->rd_status))
 788                 return (FALSE);
 789         if (rd->rd_status != NFS_OK)
 790                 return (TRUE);
 791 
 792         bufsize = 1 * BYTES_PER_XDR_UNIT;
 793         for (size = rd->rd_size, dp = rd->rd_entries;
 794             size > 0;
 795             size -= dp->d_reclen, dp = nextdp(dp)) {
 796                 if (dp->d_reclen == 0 /* || DIRSIZ(dp) > dp->d_reclen */)
 797                         return (FALSE);
 798                 if (dp->d_ino == 0)
 799                         continue;
 800                 ino = (uint32_t)dp->d_ino; /* for LP64 we clip the bits */
 801                 if (dp->d_ino != (ino64_t)ino)       /* and they better be zeros */
 802                         return (FALSE);
 803                 off = (uint32_t)dp->d_off;
 804                 name = dp->d_name;
 805                 namlen = (uint_t)strlen(name);
 806                 entrysz = (1 + 1 + 1 + 1) * BYTES_PER_XDR_UNIT +
 807                     roundup(namlen, BYTES_PER_XDR_UNIT);
 808                 tofit = entrysz + 2 * BYTES_PER_XDR_UNIT;
 809                 if (bufsize + tofit > rd->rd_bufsize) {
 810                         rd->rd_eof = FALSE;
 811                         break;
 812                 }
 813                 if (!xdr_bool(xdrs, &true) ||
 814                     !xdr_u_int(xdrs, &ino) ||
 815                     !xdr_bytes(xdrs, &name, &namlen, NFS_MAXNAMLEN) ||
 816                     !xdr_u_int(xdrs, &off)) {
 817                         return (FALSE);
 818                 }
 819                 bufsize += entrysz;
 820         }
 821         if (!xdr_bool(xdrs, &false))
 822                 return (FALSE);
 823         if (!xdr_bool(xdrs, &rd->rd_eof))
 824                 return (FALSE);
 825         return (TRUE);
 826 }
 827 
 828 /*
 829  * DECODE ONLY
 830  */
 831 bool_t
 832 xdr_getrddirres(XDR *xdrs, struct nfsrddirres *rd)
 833 {
 834         struct dirent64 *dp;
 835         uint_t namlen;
 836         int size;
 837         bool_t valid;
 838         uint32_t offset;
 839         uint_t fileid, this_reclen;
 840 
 841         if (xdrs->x_op != XDR_DECODE)
 842                 return (FALSE);
 843 
 844         if (!xdr_enum(xdrs, (enum_t *)&rd->rd_status))
 845                 return (FALSE);
 846         if (rd->rd_status != NFS_OK)
 847                 return (TRUE);
 848 
 849         size = rd->rd_size;
 850         dp = rd->rd_entries;
 851         offset = rd->rd_offset;
 852         for (;;) {
 853                 if (!xdr_bool(xdrs, &valid))
 854                         return (FALSE);
 855                 if (!valid)
 856                         break;
 857                 if (!xdr_u_int(xdrs, &fileid) ||
 858                     !xdr_u_int(xdrs, &namlen))
 859                         return (FALSE);
 860                 this_reclen = DIRENT64_RECLEN(namlen);
 861                 if (this_reclen > size) {
 862                         rd->rd_eof = FALSE;
 863                         goto bufovflw;
 864                 }
 865                 if (!xdr_opaque(xdrs, dp->d_name, namlen)||
 866                     !xdr_u_int(xdrs, &offset)) {
 867                         return (FALSE);
 868                 }
 869                 bzero(&dp->d_name[namlen],
 870                     DIRENT64_NAMELEN(this_reclen) - namlen);
 871                 dp->d_ino = (ino64_t)fileid;
 872                 dp->d_reclen = this_reclen;
 873                 dp->d_off = (off64_t)offset;
 874                 size -= dp->d_reclen;
 875                 dp = nextdp(dp);
 876         }
 877         if (!xdr_bool(xdrs, &rd->rd_eof))
 878                 return (FALSE);
 879 bufovflw:
 880         rd->rd_size = (uint32_t)((char *)dp - (char *)(rd->rd_entries));
 881         rd->rd_offset = offset;
 882         return (TRUE);
 883 }
 884 
 885 /*
 886  * Arguments for directory operations
 887  */
 888 bool_t
 889 xdr_diropargs(XDR *xdrs, struct nfsdiropargs *da)
 890 {
 891         int32_t *ptr;
 892         int32_t *fhp;
 893         uint32_t size;
 894         uint32_t nodesize;
 895         int i;
 896         int rndup;
 897         char *cptr;
 898 
 899         if (xdrs->x_op == XDR_DECODE) {
 900                 da->da_fhandle = &da->da_fhandle_buf;




   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 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 /*
  26  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  27  */
  28 
  29 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
  30 /* All Rights Reserved */
  31 
  32 #include <sys/param.h>
  33 #include <sys/types.h>
  34 #include <sys/systm.h>
  35 #include <sys/user.h>
  36 #include <sys/vnode.h>
  37 #include <sys/file.h>
  38 #include <sys/dirent.h>
  39 #include <sys/vfs.h>
  40 #include <sys/stream.h>
  41 #include <sys/strsubr.h>
  42 #include <sys/debug.h>
  43 #include <sys/t_lock.h>
  44 #include <sys/sdt.h>
  45 
  46 #include <rpc/types.h>
  47 #include <rpc/xdr.h>


 757  *              u_int   de_fid;
 758  *              string  de_name<NFS_MAXNAMELEN>;
 759  *      }
 760  */
 761 
 762 #ifdef nextdp
 763 #undef  nextdp
 764 #endif
 765 #define nextdp(dp)      ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
 766 #ifdef roundup
 767 #undef  roundup
 768 #endif
 769 #define roundup(x, y)   ((((x) + ((y) - 1)) / (y)) * (y))
 770 
 771 /*
 772  * ENCODE ONLY
 773  */
 774 bool_t
 775 xdr_putrddirres(XDR *xdrs, struct nfsrddirres *rd)
 776 {




 777         bool_t true = TRUE;
 778         bool_t false = FALSE;
 779         struct nfsentry *entry;



 780 
 781         if (xdrs->x_op != XDR_ENCODE)
 782                 return (FALSE);
 783         if (!xdr_enum(xdrs, (enum_t *)&rd->rd_status))
 784                 return (FALSE);
 785         if (rd->rd_status != NFS_OK)
 786                 return (TRUE);
 787 
 788         for (entry = rd->rd_entries; entry != NULL; entry = entry->nextentry) {




















 789                 if (!xdr_bool(xdrs, &true) ||
 790                     !xdr_u_int(xdrs, &entry->fileid) ||
 791                     !xdr_string(xdrs, &entry->name, NFS_MAXNAMLEN) ||
 792                     !xdr_u_int(xdrs, &entry->cookie)) {
 793                         return (FALSE);
 794                 }

 795         }
 796         if (!xdr_bool(xdrs, &false))
 797                 return (FALSE);
 798         if (!xdr_bool(xdrs, &rd->rd_eof))
 799                 return (FALSE);
 800         return (TRUE);
 801 }
 802 
 803 /*
 804  * DECODE ONLY
 805  */
 806 bool_t
 807 xdr_getrddirres(XDR *xdrs, struct nfsrddirres *rd)
 808 {
 809         struct dirent64 *dp;
 810         uint_t namlen;
 811         int size;
 812         bool_t valid;
 813         uint32_t offset;
 814         uint_t fileid, this_reclen;
 815 
 816         if (xdrs->x_op != XDR_DECODE)
 817                 return (FALSE);
 818 
 819         if (!xdr_enum(xdrs, (enum_t *)&rd->rd_status))
 820                 return (FALSE);
 821         if (rd->rd_status != NFS_OK)
 822                 return (TRUE);
 823 
 824         size = rd->rd_size;
 825         dp = rd->rd_dirents;
 826         offset = rd->rd_offset;
 827         for (;;) {
 828                 if (!xdr_bool(xdrs, &valid))
 829                         return (FALSE);
 830                 if (!valid)
 831                         break;
 832                 if (!xdr_u_int(xdrs, &fileid) ||
 833                     !xdr_u_int(xdrs, &namlen))
 834                         return (FALSE);
 835                 this_reclen = DIRENT64_RECLEN(namlen);
 836                 if (this_reclen > size) {
 837                         rd->rd_eof = FALSE;
 838                         goto bufovflw;
 839                 }
 840                 if (!xdr_opaque(xdrs, dp->d_name, namlen)||
 841                     !xdr_u_int(xdrs, &offset)) {
 842                         return (FALSE);
 843                 }
 844                 bzero(&dp->d_name[namlen],
 845                     DIRENT64_NAMELEN(this_reclen) - namlen);
 846                 dp->d_ino = (ino64_t)fileid;
 847                 dp->d_reclen = this_reclen;
 848                 dp->d_off = (off64_t)offset;
 849                 size -= dp->d_reclen;
 850                 dp = nextdp(dp);
 851         }
 852         if (!xdr_bool(xdrs, &rd->rd_eof))
 853                 return (FALSE);
 854 bufovflw:
 855         rd->rd_size = (uint32_t)((char *)dp - (char *)(rd->rd_dirents));
 856         rd->rd_offset = offset;
 857         return (TRUE);
 858 }
 859 
 860 /*
 861  * Arguments for directory operations
 862  */
 863 bool_t
 864 xdr_diropargs(XDR *xdrs, struct nfsdiropargs *da)
 865 {
 866         int32_t *ptr;
 867         int32_t *fhp;
 868         uint32_t size;
 869         uint32_t nodesize;
 870         int i;
 871         int rndup;
 872         char *cptr;
 873 
 874         if (xdrs->x_op == XDR_DECODE) {
 875                 da->da_fhandle = &da->da_fhandle_buf;