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>


  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 2010 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 /*
  30  * Copyright (c) 2013 by Delphix. All rights reserved.

  31  */
  32 
  33 #include <sys/param.h>
  34 #include <sys/types.h>
  35 #include <sys/systm.h>
  36 #include <sys/user.h>
  37 #include <sys/vnode.h>
  38 #include <sys/file.h>
  39 #include <sys/dirent.h>
  40 #include <sys/vfs.h>
  41 #include <sys/stream.h>
  42 #include <sys/strsubr.h>
  43 #include <sys/debug.h>
  44 #include <sys/t_lock.h>
  45 #include <sys/cmn_err.h>
  46 #include <sys/dnlc.h>
  47 #include <sys/cred.h>
  48 #include <sys/time.h>
  49 #include <sys/sdt.h>
  50 


1993         if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
1994             xdrs->x_op == XDR_ENCODE) {
1995                 rci.rci_type = RCI_REPLY_CHUNK;
1996                 rci.rci_len = objp->count;
1997                 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
1998         }
1999 
2000         if (!xdr_u_longlong_t(xdrs, &objp->cookie))
2001                 return (FALSE);
2002         /*
2003          * cookieverf is really an opaque 8 byte
2004          * quantity, but we will treat it as a
2005          * hyper for efficiency, the cost of
2006          * a byteswap here saves bcopys elsewhere
2007          */
2008         if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
2009                 return (FALSE);
2010         return (xdr_u_int(xdrs, &objp->count));
2011 }
2012 
2013 #ifdef  nextdp
2014 #undef  nextdp
2015 #endif
2016 #define nextdp(dp)      ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
2017 #ifdef  roundup
2018 #undef  roundup
2019 #endif
2020 #define roundup(x, y)   ((((x) + ((y) - 1)) / (y)) * (y))
2021 
2022 /*
2023  * ENCODE ONLY
2024  */
2025 static bool_t
2026 xdr_putdirlist(XDR *xdrs, READDIR3resok *objp)
2027 {
2028         struct dirent64 *dp;
2029         char *name;
2030         int size;
2031         int bufsize;
2032         uint_t namlen;
2033         bool_t true = TRUE;
2034         bool_t false = FALSE;
2035         int entrysz;
2036         int tofit;
2037         fileid3 fileid;
2038         cookie3 cookie;
2039 
2040         if (xdrs->x_op != XDR_ENCODE)
2041                 return (FALSE);
2042 
2043         /*
2044          * bufsize is used to keep track of the size of the response.
2045          * It is primed with:
2046          *      1 for the status +
2047          *      1 for the dir_attributes.attributes boolean +
2048          *      2 for the cookie verifier
2049          * all times BYTES_PER_XDR_UNIT to convert from XDR units
2050          * to bytes.  If there are directory attributes to be
2051          * returned, then:
2052          *      NFS3_SIZEOF_FATTR3 for the dir_attributes.attr fattr3
2053          * time BYTES_PER_XDR_UNIT is added to account for them.
2054          */
2055         bufsize = (1 + 1 + 2) * BYTES_PER_XDR_UNIT;
2056         if (objp->dir_attributes.attributes)
2057                 bufsize += NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
2058         for (size = objp->size, dp = (struct dirent64 *)objp->reply.entries;
2059             size > 0;
2060             size -= dp->d_reclen, dp = nextdp(dp)) {
2061                 if (dp->d_reclen == 0)
2062                         return (FALSE);
2063                 if (dp->d_ino == 0)
2064                         continue;
2065                 name = dp->d_name;
2066                 namlen = (uint_t)strlen(dp->d_name);
2067                 /*
2068                  * An entry is composed of:
2069                  *      1 for the true/false list indicator +
2070                  *      2 for the fileid +
2071                  *      1 for the length of the name +
2072                  *      2 for the cookie +
2073                  * all times BYTES_PER_XDR_UNIT to convert from
2074                  * XDR units to bytes, plus the length of the name
2075                  * rounded up to the nearest BYTES_PER_XDR_UNIT.
2076                  */
2077                 entrysz = (1 + 2 + 1 + 2) * BYTES_PER_XDR_UNIT +
2078                     roundup(namlen, BYTES_PER_XDR_UNIT);
2079                 /*
2080                  * We need to check to see if the number of bytes left
2081                  * to go into the buffer will actually fit into the
2082                  * buffer.  This is calculated as the size of this
2083                  * entry plus:
2084                  *      1 for the true/false list indicator +
2085                  *      1 for the eof indicator
2086                  * times BYTES_PER_XDR_UNIT to convert from from
2087                  * XDR units to bytes.
2088                  */
2089                 tofit = entrysz + (1 + 1) * BYTES_PER_XDR_UNIT;
2090                 if (bufsize + tofit > objp->count) {
2091                         objp->reply.eof = FALSE;
2092                         break;
2093                 }
2094                 fileid = (fileid3)(dp->d_ino);
2095                 cookie = (cookie3)(dp->d_off);
2096                 if (!xdr_bool(xdrs, &true) ||
2097                     !xdr_u_longlong_t(xdrs, &fileid) ||
2098                     !xdr_bytes(xdrs, &name, &namlen, ~0) ||
2099                     !xdr_u_longlong_t(xdrs, &cookie)) {
2100                         return (FALSE);
2101                 }
2102                 bufsize += entrysz;
2103         }

2104         if (!xdr_bool(xdrs, &false))
2105                 return (FALSE);
2106         if (!xdr_bool(xdrs, &objp->reply.eof))
2107                 return (FALSE);
2108         return (TRUE);
2109 }
2110 
2111 bool_t
2112 xdr_READDIR3res(XDR *xdrs, READDIR3res *objp)
2113 {
2114         READDIR3resok *resokp;
2115 
2116         /*
2117          * ENCODE or FREE only
2118          */
2119         if (xdrs->x_op == XDR_DECODE)
2120                 return (FALSE);
2121 
2122         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2123                 return (FALSE);


2270                 return (FALSE);
2271         /*
2272          * cookieverf is really an opaque 8 byte
2273          * quantity, but we will treat it as a
2274          * hyper for efficiency, the cost of
2275          * a byteswap here saves bcopys elsewhere
2276          */
2277         if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
2278                 return (FALSE);
2279         if (!xdr_u_int(xdrs, &objp->dircount))
2280                 return (FALSE);
2281         return (xdr_u_int(xdrs, &objp->maxcount));
2282 }
2283 
2284 /*
2285  * ENCODE ONLY
2286  */
2287 static bool_t
2288 xdr_putdirpluslist(XDR *xdrs, READDIRPLUS3resok *objp)
2289 {
2290         struct dirent64 *dp;
2291         char *name;
2292         int nents;
2293         bool_t true = TRUE;
2294         bool_t false = FALSE;
2295         fileid3 fileid;
2296         cookie3 cookie;
2297         entryplus3_info *infop;
2298 
2299         if (xdrs->x_op != XDR_ENCODE)
2300                 return (FALSE);
2301 
2302         dp = (struct dirent64 *)objp->reply.entries;
2303         nents = objp->size;
2304         infop = objp->infop;
2305 
2306         while (nents > 0) {
2307                 if (dp->d_reclen == 0)
2308                         return (FALSE);
2309                 if (dp->d_ino != 0) {
2310                         name = dp->d_name;
2311                         fileid = (fileid3)(dp->d_ino);
2312                         cookie = (cookie3)(dp->d_off);
2313                         if (!xdr_bool(xdrs, &true) ||
2314                             !xdr_u_longlong_t(xdrs, &fileid) ||
2315                             !xdr_bytes(xdrs, &name, &infop->namelen, ~0) ||
2316                             !xdr_u_longlong_t(xdrs, &cookie) ||
2317                             !xdr_post_op_attr(xdrs, &infop->attr) ||
2318                             !xdr_post_op_fh3(xdrs, &infop->fh)) {
2319                                 return (FALSE);
2320                         }
2321                 }
2322                 dp = nextdp(dp);
2323                 infop++;
2324                 nents--;
2325         }
2326 
2327         if (!xdr_bool(xdrs, &false))
2328                 return (FALSE);
2329         if (!xdr_bool(xdrs, &objp->reply.eof))
2330                 return (FALSE);
2331         return (TRUE);
2332 }
2333 
2334 bool_t
2335 xdr_READDIRPLUS3res(XDR *xdrs, READDIRPLUS3res *objp)
2336 {
2337         READDIRPLUS3resok *resokp;
2338 
2339         /*
2340          * ENCODE or FREE only
2341          */
2342         if (xdrs->x_op == XDR_DECODE)
2343                 return (FALSE);
2344 
2345         if (!xdr_enum(xdrs, (enum_t *)&objp->status))




  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 2010 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 /*
  30  * Copyright (c) 2013 by Delphix. All rights reserved.
  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/user.h>
  38 #include <sys/vnode.h>
  39 #include <sys/file.h>
  40 #include <sys/dirent.h>
  41 #include <sys/vfs.h>
  42 #include <sys/stream.h>
  43 #include <sys/strsubr.h>
  44 #include <sys/debug.h>
  45 #include <sys/t_lock.h>
  46 #include <sys/cmn_err.h>
  47 #include <sys/dnlc.h>
  48 #include <sys/cred.h>
  49 #include <sys/time.h>
  50 #include <sys/sdt.h>
  51 


1994         if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
1995             xdrs->x_op == XDR_ENCODE) {
1996                 rci.rci_type = RCI_REPLY_CHUNK;
1997                 rci.rci_len = objp->count;
1998                 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
1999         }
2000 
2001         if (!xdr_u_longlong_t(xdrs, &objp->cookie))
2002                 return (FALSE);
2003         /*
2004          * cookieverf is really an opaque 8 byte
2005          * quantity, but we will treat it as a
2006          * hyper for efficiency, the cost of
2007          * a byteswap here saves bcopys elsewhere
2008          */
2009         if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
2010                 return (FALSE);
2011         return (xdr_u_int(xdrs, &objp->count));
2012 }
2013 









2014 /*
2015  * ENCODE ONLY
2016  */
2017 static bool_t
2018 xdr_putdirlist(XDR *xdrs, READDIR3resok *objp)
2019 {





2020         bool_t true = TRUE;
2021         bool_t false = FALSE;
2022         entry3 *entry;



2023 
2024         if (xdrs->x_op != XDR_ENCODE)
2025                 return (FALSE);
2026 
2027         for (entry = objp->reply.entries; entry != NULL;
2028             entry = entry->nextentry) {



















































2029                 if (!xdr_bool(xdrs, &true) ||
2030                     !xdr_u_longlong_t(xdrs, &entry->fileid) ||
2031                     !xdr_string(xdrs, &entry->name, MAXPATHLEN) ||
2032                     !xdr_u_longlong_t(xdrs, &entry->cookie)) {
2033                         return (FALSE);
2034                 }

2035         }
2036 
2037         if (!xdr_bool(xdrs, &false))
2038                 return (FALSE);
2039         if (!xdr_bool(xdrs, &objp->reply.eof))
2040                 return (FALSE);
2041         return (TRUE);
2042 }
2043 
2044 bool_t
2045 xdr_READDIR3res(XDR *xdrs, READDIR3res *objp)
2046 {
2047         READDIR3resok *resokp;
2048 
2049         /*
2050          * ENCODE or FREE only
2051          */
2052         if (xdrs->x_op == XDR_DECODE)
2053                 return (FALSE);
2054 
2055         if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2056                 return (FALSE);


2203                 return (FALSE);
2204         /*
2205          * cookieverf is really an opaque 8 byte
2206          * quantity, but we will treat it as a
2207          * hyper for efficiency, the cost of
2208          * a byteswap here saves bcopys elsewhere
2209          */
2210         if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
2211                 return (FALSE);
2212         if (!xdr_u_int(xdrs, &objp->dircount))
2213                 return (FALSE);
2214         return (xdr_u_int(xdrs, &objp->maxcount));
2215 }
2216 
2217 /*
2218  * ENCODE ONLY
2219  */
2220 static bool_t
2221 xdr_putdirpluslist(XDR *xdrs, READDIRPLUS3resok *objp)
2222 {



2223         bool_t true = TRUE;
2224         bool_t false = FALSE;
2225         entryplus3 *entry;


2226 
2227         if (xdrs->x_op != XDR_ENCODE)
2228                 return (FALSE);
2229 
2230         for (entry = objp->reply.entries; entry != NULL;
2231             entry = entry->nextentry) {









2232                 if (!xdr_bool(xdrs, &true) ||
2233                     !xdr_u_longlong_t(xdrs, &entry->fileid) ||
2234                     !xdr_string(xdrs, &entry->name, MAXPATHLEN) ||
2235                     !xdr_u_longlong_t(xdrs, &entry->cookie) ||
2236                     !xdr_post_op_attr(xdrs, &entry->name_attributes) ||
2237                     !xdr_post_op_fh3(xdrs, &entry->name_handle)) {
2238                         return (FALSE);
2239                 }
2240         }




2241 
2242         if (!xdr_bool(xdrs, &false))
2243                 return (FALSE);
2244         if (!xdr_bool(xdrs, &objp->reply.eof))
2245                 return (FALSE);
2246         return (TRUE);
2247 }
2248 
2249 bool_t
2250 xdr_READDIRPLUS3res(XDR *xdrs, READDIRPLUS3res *objp)
2251 {
2252         READDIRPLUS3resok *resokp;
2253 
2254         /*
2255          * ENCODE or FREE only
2256          */
2257         if (xdrs->x_op == XDR_DECODE)
2258                 return (FALSE);
2259 
2260         if (!xdr_enum(xdrs, (enum_t *)&objp->status))