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 <fllin...@amazon.com> (earlier version)
  Reported by:  Frank van der Linden <fllin...@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);
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to