svn commit: r340787 - head/sys/fs/nfsclient

Rick Macklem rmacklem at FreeBSD.org
Fri Nov 23 00:17:48 UTC 2018


Author: rmacklem
Date: Fri Nov 23 00:17:47 2018
New Revision: 340787
URL: https://svnweb.freebsd.org/changeset/base/340787

Log:
  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

Modified:
  head/sys/fs/nfsclient/nfs_clrpcops.c

Modified: head/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- head/sys/fs/nfsclient/nfs_clrpcops.c	Thu Nov 22 21:38:24 2018	(r340786)
+++ head/sys/fs/nfsclient/nfs_clrpcops.c	Fri Nov 23 00:17:47 2018	(r340787)
@@ -2959,6 +2959,7 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64
 			    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
 			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
 				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
 				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
 					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
 	 */
 	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
 	 */
 	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, nfsui
 			    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, nfsui
 			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, nfsui
 				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, nfsui
 				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, nfsui
 					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, nfsui
 	 */
 	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, nfsui
 	 */
 	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];


More information about the svn-src-all mailing list