svn commit: r359941 - in head/sys/fs: nfsclient nfsserver

Rick Macklem rmacklem at FreeBSD.org
Tue Apr 14 22:57:22 UTC 2020


Author: rmacklem
Date: Tue Apr 14 22:57:21 2020
New Revision: 359941
URL: https://svnweb.freebsd.org/changeset/base/359941

Log:
  Fix the NFSv2 extended attribute support to handle 0 length attributes.
  
  I did not realize that zero length attributes are allowed, but they are.
  This patch fixes the NFSv4.2 client and server to handle zero length
  extended attributes correctly.
  
  Submitted by:	Frank van der Linden <fllinden at amazon.com> (earlier version)
  Reported by:	Frank van der Linden <fllinder at amazon.com>

Modified:
  head/sys/fs/nfsclient/nfs_clrpcops.c
  head/sys/fs/nfsclient/nfs_clvnops.c
  head/sys/fs/nfsserver/nfs_nfsdport.c
  head/sys/fs/nfsserver/nfs_nfsdserv.c

Modified: head/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- head/sys/fs/nfsclient/nfs_clrpcops.c	Tue Apr 14 22:48:33 2020	(r359940)
+++ head/sys/fs/nfsclient/nfs_clrpcops.c	Tue Apr 14 22:57:21 2020	(r359941)
@@ -8341,7 +8341,7 @@ nfsrpc_getextattr(vnode_t vp, const char *name, struct
 		} else if (uiop == NULL && len > 0) {
 			/* Just wants the length and not the data. */
 			error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
-		} else
+		} else if (len > 0)
 			error = ENOATTR;
 		if (error != 0)
 			goto nfsmout;

Modified: head/sys/fs/nfsclient/nfs_clvnops.c
==============================================================================
--- head/sys/fs/nfsclient/nfs_clvnops.c	Tue Apr 14 22:48:33 2020	(r359940)
+++ head/sys/fs/nfsclient/nfs_clvnops.c	Tue Apr 14 22:57:21 2020	(r359941)
@@ -3982,7 +3982,7 @@ nfs_setextattr(struct vop_setextattr_args *ap)
 	}
 	mtx_unlock(&nmp->nm_mtx);
 
-	if (ap->a_uio->uio_resid <= 0)
+	if (ap->a_uio->uio_resid < 0)
 		return (EINVAL);
 	cred = ap->a_cred;
 	if (cred == NULL)

Modified: head/sys/fs/nfsserver/nfs_nfsdport.c
==============================================================================
--- head/sys/fs/nfsserver/nfs_nfsdport.c	Tue Apr 14 22:48:33 2020	(r359940)
+++ head/sys/fs/nfsserver/nfs_nfsdport.c	Tue Apr 14 22:57:21 2020	(r359941)
@@ -6159,8 +6159,14 @@ nfsvno_getxattr(struct vnode *vp, char *name, uint32_t
 		return (NFSERR_XATTR2BIG);
 	len = siz;
 	tlen = NFSM_RNDUP(len);
-	uiop->uio_iovcnt = nfsrv_createiovec(tlen, &m, &m2, &iv);
-	uiop->uio_iov = iv;
+	if (tlen > 0) {
+		uiop->uio_iovcnt = nfsrv_createiovec(tlen, &m, &m2, &iv);
+		uiop->uio_iov = iv;
+	} else {
+		uiop->uio_iovcnt = 0;
+		uiop->uio_iov = iv = NULL;
+		m = m2 = NULL;
+	}
 	uiop->uio_offset = 0;
 	uiop->uio_resid = tlen;
 	uiop->uio_rw = UIO_READ;
@@ -6173,8 +6179,9 @@ nfsvno_getxattr(struct vnode *vp, char *name, uint32_t
 		goto out;
 #endif
 
-	error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, uiop, NULL,
-	    cred, p);
+	if (tlen > 0)
+		error = VOP_GETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, uiop,
+		    NULL, cred, p);
 	if (error != 0)
 		goto out;
 	if (uiop->uio_resid > 0) {
@@ -6191,7 +6198,8 @@ nfsvno_getxattr(struct vnode *vp, char *name, uint32_t
 
 out:
 	if (error != 0) {
-		m_freem(m);
+		if (m != NULL)
+			m_freem(m);
 		*lenp = 0;
 	}
 	free(iv, M_TEMP);
@@ -6223,9 +6231,14 @@ nfsvno_setxattr(struct vnode *vp, char *name, int len,
 	uiop->uio_td = p;
 	uiop->uio_offset = 0;
 	uiop->uio_resid = len;
-	error = nfsrv_createiovecw(len, m, cp, &iv, &cnt);
-	uiop->uio_iov = iv;
-	uiop->uio_iovcnt = cnt;
+	if (len > 0) {
+		error = nfsrv_createiovecw(len, m, cp, &iv, &cnt);
+		uiop->uio_iov = iv;
+		uiop->uio_iovcnt = cnt;
+	} else {
+		uiop->uio_iov = iv = NULL;
+		uiop->uio_iovcnt = 0;
+	}
 	if (error == 0) {
 		error = VOP_SETEXTATTR(vp, EXTATTR_NAMESPACE_USER, name, uiop,
 		    cred, p);

Modified: head/sys/fs/nfsserver/nfs_nfsdserv.c
==============================================================================
--- head/sys/fs/nfsserver/nfs_nfsdserv.c	Tue Apr 14 22:48:33 2020	(r359940)
+++ head/sys/fs/nfsserver/nfs_nfsdserv.c	Tue Apr 14 22:57:21 2020	(r359941)
@@ -5564,9 +5564,11 @@ nfsrvd_getxattr(struct nfsrv_descript *nd, __unused in
 	if (nd->nd_repstat == 0) {
 		NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
 		*tl = txdr_unsigned(len);
-		nd->nd_mb->m_next = mp;
-		nd->nd_mb = mpend;
-		nd->nd_bpos = mtod(mpend, caddr_t) + mpend->m_len;
+		if (len > 0) {
+			nd->nd_mb->m_next = mp;
+			nd->nd_mb = mpend;
+			nd->nd_bpos = mtod(mpend, caddr_t) + mpend->m_len;
+		}
 	}
 	free(name, M_TEMP);
 
@@ -5616,7 +5618,7 @@ nfsrvd_setxattr(struct nfsrv_descript *nd, __unused in
 		goto nfsmout;
 	NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 	len = fxdr_unsigned(int, *tl);
-	if (len <= 0 || len > IOSIZE_MAX) {
+	if (len < 0 || len > IOSIZE_MAX) {
 		nd->nd_repstat = NFSERR_XATTR2BIG;
 		goto nfsmout;
 	}
@@ -5652,7 +5654,7 @@ nfsrvd_setxattr(struct nfsrv_descript *nd, __unused in
 		if (nd->nd_repstat == ENXIO)
 			nd->nd_repstat = NFSERR_XATTR2BIG;
 	}
-	if (nd->nd_repstat == 0)
+	if (nd->nd_repstat == 0 && len > 0)
 		nd->nd_repstat = nfsm_advance(nd, NFSM_RNDUP(len), -1);
 	if (nd->nd_repstat == 0)
 		nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1, &attrbits);


More information about the svn-src-head mailing list