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@amazon.com> (earlier version)
Reported by:	Frank van der Linden <fllinder@amazon.com>
This commit is contained in:
rmacklem 2020-04-14 22:57:21 +00:00
parent e0716185e7
commit c017402cfe
4 changed files with 30 additions and 15 deletions

View File

@ -8341,7 +8341,7 @@ nfsrpc_getextattr(vnode_t vp, const char *name, struct uio *uiop, ssize_t *lenp,
} 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;

View File

@ -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)

View File

@ -6159,8 +6159,14 @@ nfsvno_getxattr(struct vnode *vp, char *name, uint32_t maxresp,
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 maxresp,
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 maxresp,
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, struct mbuf *m,
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);

View File

@ -5564,9 +5564,11 @@ nfsrvd_getxattr(struct nfsrv_descript *nd, __unused int isdgram,
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 int isdgram,
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 int isdgram,
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);