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>
*** 26,35 ****
--- 26,36 ----
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/systm.h>
*** 2008,2108 ****
if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
return (FALSE);
return (xdr_u_int(xdrs, &objp->count));
}
- #ifdef nextdp
- #undef nextdp
- #endif
- #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
- #ifdef roundup
- #undef roundup
- #endif
- #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
-
/*
* ENCODE ONLY
*/
static bool_t
xdr_putdirlist(XDR *xdrs, READDIR3resok *objp)
{
- struct dirent64 *dp;
- char *name;
- int size;
- int bufsize;
- uint_t namlen;
bool_t true = TRUE;
bool_t false = FALSE;
! int entrysz;
! int tofit;
! fileid3 fileid;
! cookie3 cookie;
if (xdrs->x_op != XDR_ENCODE)
return (FALSE);
! /*
! * bufsize is used to keep track of the size of the response.
! * It is primed with:
! * 1 for the status +
! * 1 for the dir_attributes.attributes boolean +
! * 2 for the cookie verifier
! * all times BYTES_PER_XDR_UNIT to convert from XDR units
! * to bytes. If there are directory attributes to be
! * returned, then:
! * NFS3_SIZEOF_FATTR3 for the dir_attributes.attr fattr3
! * time BYTES_PER_XDR_UNIT is added to account for them.
! */
! bufsize = (1 + 1 + 2) * BYTES_PER_XDR_UNIT;
! if (objp->dir_attributes.attributes)
! bufsize += NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
! for (size = objp->size, dp = (struct dirent64 *)objp->reply.entries;
! size > 0;
! size -= dp->d_reclen, dp = nextdp(dp)) {
! if (dp->d_reclen == 0)
! return (FALSE);
! if (dp->d_ino == 0)
! continue;
! name = dp->d_name;
! namlen = (uint_t)strlen(dp->d_name);
! /*
! * An entry is composed of:
! * 1 for the true/false list indicator +
! * 2 for the fileid +
! * 1 for the length of the name +
! * 2 for the cookie +
! * all times BYTES_PER_XDR_UNIT to convert from
! * XDR units to bytes, plus the length of the name
! * rounded up to the nearest BYTES_PER_XDR_UNIT.
! */
! entrysz = (1 + 2 + 1 + 2) * BYTES_PER_XDR_UNIT +
! roundup(namlen, BYTES_PER_XDR_UNIT);
! /*
! * We need to check to see if the number of bytes left
! * to go into the buffer will actually fit into the
! * buffer. This is calculated as the size of this
! * entry plus:
! * 1 for the true/false list indicator +
! * 1 for the eof indicator
! * times BYTES_PER_XDR_UNIT to convert from from
! * XDR units to bytes.
! */
! tofit = entrysz + (1 + 1) * BYTES_PER_XDR_UNIT;
! if (bufsize + tofit > objp->count) {
! objp->reply.eof = FALSE;
! break;
! }
! fileid = (fileid3)(dp->d_ino);
! cookie = (cookie3)(dp->d_off);
if (!xdr_bool(xdrs, &true) ||
! !xdr_u_longlong_t(xdrs, &fileid) ||
! !xdr_bytes(xdrs, &name, &namlen, ~0) ||
! !xdr_u_longlong_t(xdrs, &cookie)) {
return (FALSE);
}
- bufsize += entrysz;
}
if (!xdr_bool(xdrs, &false))
return (FALSE);
if (!xdr_bool(xdrs, &objp->reply.eof))
return (FALSE);
return (TRUE);
--- 2009,2041 ----
if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
return (FALSE);
return (xdr_u_int(xdrs, &objp->count));
}
/*
* ENCODE ONLY
*/
static bool_t
xdr_putdirlist(XDR *xdrs, READDIR3resok *objp)
{
bool_t true = TRUE;
bool_t false = FALSE;
! entry3 *entry;
if (xdrs->x_op != XDR_ENCODE)
return (FALSE);
! for (entry = objp->reply.entries; entry != NULL;
! entry = entry->nextentry) {
if (!xdr_bool(xdrs, &true) ||
! !xdr_u_longlong_t(xdrs, &entry->fileid) ||
! !xdr_string(xdrs, &entry->name, MAXPATHLEN) ||
! !xdr_u_longlong_t(xdrs, &entry->cookie)) {
return (FALSE);
}
}
+
if (!xdr_bool(xdrs, &false))
return (FALSE);
if (!xdr_bool(xdrs, &objp->reply.eof))
return (FALSE);
return (TRUE);
*** 2285,2330 ****
* ENCODE ONLY
*/
static bool_t
xdr_putdirpluslist(XDR *xdrs, READDIRPLUS3resok *objp)
{
- struct dirent64 *dp;
- char *name;
- int nents;
bool_t true = TRUE;
bool_t false = FALSE;
! fileid3 fileid;
! cookie3 cookie;
! entryplus3_info *infop;
if (xdrs->x_op != XDR_ENCODE)
return (FALSE);
! dp = (struct dirent64 *)objp->reply.entries;
! nents = objp->size;
! infop = objp->infop;
!
! while (nents > 0) {
! if (dp->d_reclen == 0)
! return (FALSE);
! if (dp->d_ino != 0) {
! name = dp->d_name;
! fileid = (fileid3)(dp->d_ino);
! cookie = (cookie3)(dp->d_off);
if (!xdr_bool(xdrs, &true) ||
! !xdr_u_longlong_t(xdrs, &fileid) ||
! !xdr_bytes(xdrs, &name, &infop->namelen, ~0) ||
! !xdr_u_longlong_t(xdrs, &cookie) ||
! !xdr_post_op_attr(xdrs, &infop->attr) ||
! !xdr_post_op_fh3(xdrs, &infop->fh)) {
return (FALSE);
}
}
- dp = nextdp(dp);
- infop++;
- nents--;
- }
if (!xdr_bool(xdrs, &false))
return (FALSE);
if (!xdr_bool(xdrs, &objp->reply.eof))
return (FALSE);
--- 2218,2245 ----
* ENCODE ONLY
*/
static bool_t
xdr_putdirpluslist(XDR *xdrs, READDIRPLUS3resok *objp)
{
bool_t true = TRUE;
bool_t false = FALSE;
! entryplus3 *entry;
if (xdrs->x_op != XDR_ENCODE)
return (FALSE);
! for (entry = objp->reply.entries; entry != NULL;
! entry = entry->nextentry) {
if (!xdr_bool(xdrs, &true) ||
! !xdr_u_longlong_t(xdrs, &entry->fileid) ||
! !xdr_string(xdrs, &entry->name, MAXPATHLEN) ||
! !xdr_u_longlong_t(xdrs, &entry->cookie) ||
! !xdr_post_op_attr(xdrs, &entry->name_attributes) ||
! !xdr_post_op_fh3(xdrs, &entry->name_handle)) {
return (FALSE);
}
}
if (!xdr_bool(xdrs, &false))
return (FALSE);
if (!xdr_bool(xdrs, &objp->reply.eof))
return (FALSE);