Make sure the NFS readdir client fills in all "struct dirent" data.
The NFS client code (nfsrpc_readdir() and nfsrpc_readdirplus()) wasn't filling in parts of the readdir reply, such as d_pad[01] and the bytes at the end of d_name within d_reclen. As such, data left in a buffer cache block could be leaked to userland in the readdir reply. This patch makes sure all of the data is filled in. Reported by: Thomas Barabosch, Fraunhofer FKIE Reviewed by: kib, markj MFC after: 2 weeks
This commit is contained in:
parent
adce241981
commit
f86bce1770
@ -2959,6 +2959,7 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
|
||||
return (error);
|
||||
nd->nd_mrep = NULL;
|
||||
dp = (struct dirent *)uio_iov_base(uiop);
|
||||
dp->d_pad0 = dp->d_pad1 = 0;
|
||||
dp->d_off = 0;
|
||||
dp->d_type = DT_DIR;
|
||||
dp->d_fileno = dotfileid;
|
||||
@ -2978,6 +2979,7 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
|
||||
uio_iov_base_add(uiop, dp->d_reclen);
|
||||
uio_iov_len_add(uiop, -(dp->d_reclen));
|
||||
dp = (struct dirent *)uio_iov_base(uiop);
|
||||
dp->d_pad0 = dp->d_pad1 = 0;
|
||||
dp->d_off = 0;
|
||||
dp->d_type = DT_DIR;
|
||||
dp->d_fileno = dotdotfileid;
|
||||
@ -3091,6 +3093,7 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
|
||||
tlen += 8; /* To ensure null termination. */
|
||||
left = DIRBLKSIZ - blksiz;
|
||||
if (_GENERIC_DIRLEN(len) + NFSX_HYPER > left) {
|
||||
NFSBZERO(uio_iov_base(uiop), left);
|
||||
dp->d_reclen += left;
|
||||
uio_iov_base_add(uiop, left);
|
||||
uio_iov_len_add(uiop, -(left));
|
||||
@ -3103,6 +3106,7 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
|
||||
bigenough = 0;
|
||||
if (bigenough) {
|
||||
dp = (struct dirent *)uio_iov_base(uiop);
|
||||
dp->d_pad0 = dp->d_pad1 = 0;
|
||||
dp->d_off = 0;
|
||||
dp->d_namlen = len;
|
||||
dp->d_reclen = _GENERIC_DIRLEN(len) +
|
||||
@ -3120,7 +3124,7 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
|
||||
goto nfsmout;
|
||||
cp = uio_iov_base(uiop);
|
||||
tlen -= len;
|
||||
*cp = '\0'; /* null terminate */
|
||||
NFSBZERO(cp, tlen);
|
||||
cp += tlen; /* points to cookie storage */
|
||||
tl2 = (u_int32_t *)cp;
|
||||
uio_iov_base_add(uiop, (tlen + NFSX_HYPER));
|
||||
@ -3208,6 +3212,7 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
|
||||
*/
|
||||
if (blksiz > 0) {
|
||||
left = DIRBLKSIZ - blksiz;
|
||||
NFSBZERO(uio_iov_base(uiop), left);
|
||||
dp->d_reclen += left;
|
||||
uio_iov_base_add(uiop, left);
|
||||
uio_iov_len_add(uiop, -(left));
|
||||
@ -3235,10 +3240,8 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
|
||||
*/
|
||||
while (uio_uio_resid(uiop) > 0 && uio_uio_resid(uiop) != tresid) {
|
||||
dp = (struct dirent *)uio_iov_base(uiop);
|
||||
NFSBZERO(dp, DIRBLKSIZ);
|
||||
dp->d_type = DT_UNKNOWN;
|
||||
dp->d_fileno = 0;
|
||||
dp->d_namlen = 0;
|
||||
dp->d_name[0] = '\0';
|
||||
tl = (u_int32_t *)&dp->d_name[4];
|
||||
*tl++ = cookie.lval[0];
|
||||
*tl = cookie.lval[1];
|
||||
@ -3393,6 +3396,7 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
|
||||
return (error);
|
||||
nd->nd_mrep = NULL;
|
||||
dp = (struct dirent *)uio_iov_base(uiop);
|
||||
dp->d_pad0 = dp->d_pad1 = 0;
|
||||
dp->d_off = 0;
|
||||
dp->d_type = DT_DIR;
|
||||
dp->d_fileno = dotfileid;
|
||||
@ -3412,6 +3416,7 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
|
||||
uio_iov_base_add(uiop, dp->d_reclen);
|
||||
uio_iov_len_add(uiop, -(dp->d_reclen));
|
||||
dp = (struct dirent *)uio_iov_base(uiop);
|
||||
dp->d_pad0 = dp->d_pad1 = 0;
|
||||
dp->d_off = 0;
|
||||
dp->d_type = DT_DIR;
|
||||
dp->d_fileno = dotdotfileid;
|
||||
@ -3506,6 +3511,7 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
|
||||
tlen += 8; /* To ensure null termination. */
|
||||
left = DIRBLKSIZ - blksiz;
|
||||
if (_GENERIC_DIRLEN(len) + NFSX_HYPER > left) {
|
||||
NFSBZERO(uio_iov_base(uiop), left);
|
||||
dp->d_reclen += left;
|
||||
uio_iov_base_add(uiop, left);
|
||||
uio_iov_len_add(uiop, -(left));
|
||||
@ -3518,6 +3524,7 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
|
||||
bigenough = 0;
|
||||
if (bigenough) {
|
||||
dp = (struct dirent *)uio_iov_base(uiop);
|
||||
dp->d_pad0 = dp->d_pad1 = 0;
|
||||
dp->d_off = 0;
|
||||
dp->d_namlen = len;
|
||||
dp->d_reclen = _GENERIC_DIRLEN(len) +
|
||||
@ -3538,7 +3545,7 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
|
||||
goto nfsmout;
|
||||
cp = uio_iov_base(uiop);
|
||||
tlen -= len;
|
||||
*cp = '\0';
|
||||
NFSBZERO(cp, tlen);
|
||||
cp += tlen; /* points to cookie storage */
|
||||
tl2 = (u_int32_t *)cp;
|
||||
if (len == 2 && cnp->cn_nameptr[0] == '.' &&
|
||||
@ -3708,6 +3715,7 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
|
||||
*/
|
||||
if (blksiz > 0) {
|
||||
left = DIRBLKSIZ - blksiz;
|
||||
NFSBZERO(uio_iov_base(uiop), left);
|
||||
dp->d_reclen += left;
|
||||
uio_iov_base_add(uiop, left);
|
||||
uio_iov_len_add(uiop, -(left));
|
||||
@ -3735,10 +3743,8 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
|
||||
*/
|
||||
while (uio_uio_resid(uiop) > 0 && uio_uio_resid(uiop) != tresid) {
|
||||
dp = (struct dirent *)uio_iov_base(uiop);
|
||||
NFSBZERO(dp, DIRBLKSIZ);
|
||||
dp->d_type = DT_UNKNOWN;
|
||||
dp->d_fileno = 0;
|
||||
dp->d_namlen = 0;
|
||||
dp->d_name[0] = '\0';
|
||||
tl = (u_int32_t *)&dp->d_name[4];
|
||||
*tl++ = cookie.lval[0];
|
||||
*tl = cookie.lval[1];
|
||||
|
Loading…
Reference in New Issue
Block a user