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:
parent
e0716185e7
commit
c017402cfe
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user