Commit a0952771 authored by Trond Myklebust's avatar Trond Myklebust Committed by Linus Torvalds

[PATCH] Fix buffer reservations in nfs4xdr.c

This fixes a couple of incorrect XDR buffer reservations.  The values
passed to RESERVE_SPACE() must reflect precisely the number of bytes
that we wish to send down the wire.
parent 5ab96f44
...@@ -161,9 +161,13 @@ encode_attrs(struct xdr_stream *xdr, struct iattr *iap) ...@@ -161,9 +161,13 @@ encode_attrs(struct xdr_stream *xdr, struct iattr *iap)
* = 36 bytes, plus any contribution from variable-length fields * = 36 bytes, plus any contribution from variable-length fields
* such as owner/group/acl's. * such as owner/group/acl's.
*/ */
len = 36; len = 16;
/* Sigh */ /* Sigh */
if (iap->ia_valid & ATTR_SIZE)
len += 8;
if (iap->ia_valid & ATTR_MODE)
len += 4;
if (iap->ia_valid & ATTR_UID) { if (iap->ia_valid & ATTR_UID) {
status = owner_namelen = encode_uid(owner_name, iap->ia_uid); status = owner_namelen = encode_uid(owner_name, iap->ia_uid);
if (status < 0) { if (status < 0) {
...@@ -171,7 +175,7 @@ encode_attrs(struct xdr_stream *xdr, struct iattr *iap) ...@@ -171,7 +175,7 @@ encode_attrs(struct xdr_stream *xdr, struct iattr *iap)
iap->ia_uid); iap->ia_uid);
goto out; goto out;
} }
len += XDR_QUADLEN(owner_namelen); len += 4 + (XDR_QUADLEN(owner_namelen) << 2);
} }
if (iap->ia_valid & ATTR_GID) { if (iap->ia_valid & ATTR_GID) {
status = owner_grouplen = encode_gid(owner_group, iap->ia_gid); status = owner_grouplen = encode_gid(owner_group, iap->ia_gid);
...@@ -180,8 +184,16 @@ encode_attrs(struct xdr_stream *xdr, struct iattr *iap) ...@@ -180,8 +184,16 @@ encode_attrs(struct xdr_stream *xdr, struct iattr *iap)
iap->ia_gid); iap->ia_gid);
goto out; goto out;
} }
len += XDR_QUADLEN(owner_grouplen); len += 4 + (XDR_QUADLEN(owner_grouplen) << 2);
} }
if (iap->ia_valid & ATTR_ATIME_SET)
len += 16;
else if (iap->ia_valid & ATTR_ATIME)
len += 4;
if (iap->ia_valid & ATTR_MTIME_SET)
len += 16;
else if (iap->ia_valid & ATTR_MTIME)
len += 4;
RESERVE_SPACE(len); RESERVE_SPACE(len);
/* /*
...@@ -204,13 +216,11 @@ encode_attrs(struct xdr_stream *xdr, struct iattr *iap) ...@@ -204,13 +216,11 @@ encode_attrs(struct xdr_stream *xdr, struct iattr *iap)
bmval1 |= FATTR4_WORD1_OWNER; bmval1 |= FATTR4_WORD1_OWNER;
WRITE32(owner_namelen); WRITE32(owner_namelen);
WRITEMEM(owner_name, owner_namelen); WRITEMEM(owner_name, owner_namelen);
p += owner_namelen;
} }
if (iap->ia_valid & ATTR_GID) { if (iap->ia_valid & ATTR_GID) {
bmval1 |= FATTR4_WORD1_OWNER_GROUP; bmval1 |= FATTR4_WORD1_OWNER_GROUP;
WRITE32(owner_grouplen); WRITE32(owner_grouplen);
WRITEMEM(owner_group, owner_grouplen); WRITEMEM(owner_group, owner_grouplen);
p += owner_namelen;
} }
if (iap->ia_valid & ATTR_ATIME_SET) { if (iap->ia_valid & ATTR_ATIME_SET) {
bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET; bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
...@@ -238,6 +248,11 @@ encode_attrs(struct xdr_stream *xdr, struct iattr *iap) ...@@ -238,6 +248,11 @@ encode_attrs(struct xdr_stream *xdr, struct iattr *iap)
/* /*
* Now we backfill the bitmap and the attribute buffer length. * Now we backfill the bitmap and the attribute buffer length.
*/ */
if (len != ((char *)p - (char *)q) + 4) {
printk ("encode_attr: Attr length calculation error! %u != %u\n",
len, ((char *)p - (char *)q) + 4);
BUG();
}
len = (char *)p - (char *)q - 12; len = (char *)p - (char *)q - 12;
*q++ = htonl(bmval0); *q++ = htonl(bmval0);
*q++ = htonl(bmval1); *q++ = htonl(bmval1);
...@@ -265,7 +280,7 @@ encode_close(struct xdr_stream *xdr, struct nfs4_close *close) ...@@ -265,7 +280,7 @@ encode_close(struct xdr_stream *xdr, struct nfs4_close *close)
{ {
uint32_t *p; uint32_t *p;
RESERVE_SPACE(20); RESERVE_SPACE(8+sizeof(nfs4_stateid));
WRITE32(OP_CLOSE); WRITE32(OP_CLOSE);
WRITE32(close->cl_seqid); WRITE32(close->cl_seqid);
WRITEMEM(close->cl_stateid, sizeof(nfs4_stateid)); WRITEMEM(close->cl_stateid, sizeof(nfs4_stateid));
...@@ -380,7 +395,7 @@ encode_open(struct xdr_stream *xdr, struct nfs4_open *open) ...@@ -380,7 +395,7 @@ encode_open(struct xdr_stream *xdr, struct nfs4_open *open)
uint32_t *p; uint32_t *p;
/* seqid, share_access, share_deny, clientid, ownerlen, owner, opentype */ /* seqid, share_access, share_deny, clientid, ownerlen, owner, opentype */
RESERVE_SPACE(52); RESERVE_SPACE(36);
WRITE32(OP_OPEN); WRITE32(OP_OPEN);
WRITE32(0); /* seqid */ WRITE32(0); /* seqid */
WRITE32(open->op_share_access); WRITE32(open->op_share_access);
...@@ -392,7 +407,7 @@ encode_open(struct xdr_stream *xdr, struct nfs4_open *open) ...@@ -392,7 +407,7 @@ encode_open(struct xdr_stream *xdr, struct nfs4_open *open)
if (open->op_opentype == NFS4_OPEN_CREATE) { if (open->op_opentype == NFS4_OPEN_CREATE) {
if (open->op_createmode == NFS4_CREATE_EXCLUSIVE) { if (open->op_createmode == NFS4_CREATE_EXCLUSIVE) {
RESERVE_SPACE(12); RESERVE_SPACE(4+sizeof(nfs4_verifier));
WRITE32(open->op_createmode); WRITE32(open->op_createmode);
WRITEMEM(open->op_verifier, sizeof(nfs4_verifier)); WRITEMEM(open->op_verifier, sizeof(nfs4_verifier));
} }
...@@ -427,7 +442,7 @@ encode_open_confirm(struct xdr_stream *xdr, struct nfs4_open_confirm *open_confi ...@@ -427,7 +442,7 @@ encode_open_confirm(struct xdr_stream *xdr, struct nfs4_open_confirm *open_confi
* Note: In this "stateless" implementation, the OPEN_CONFIRM * Note: In this "stateless" implementation, the OPEN_CONFIRM
* seqid is always equal to 1. * seqid is always equal to 1.
*/ */
RESERVE_SPACE(24); RESERVE_SPACE(8+sizeof(nfs4_stateid));
WRITE32(OP_OPEN_CONFIRM); WRITE32(OP_OPEN_CONFIRM);
WRITEMEM(open_confirm->oc_stateid, sizeof(nfs4_stateid)); WRITEMEM(open_confirm->oc_stateid, sizeof(nfs4_stateid));
WRITE32(1); WRITE32(1);
...@@ -494,7 +509,7 @@ encode_readdir(struct xdr_stream *xdr, struct nfs4_readdir *readdir, struct rpc_ ...@@ -494,7 +509,7 @@ encode_readdir(struct xdr_stream *xdr, struct nfs4_readdir *readdir, struct rpc_
int replen; int replen;
uint32_t *p; uint32_t *p;
RESERVE_SPACE(40); RESERVE_SPACE(32+sizeof(nfs4_verifier));
WRITE32(OP_READDIR); WRITE32(OP_READDIR);
WRITE64(readdir->rd_cookie); WRITE64(readdir->rd_cookie);
WRITEMEM(readdir->rd_req_verifier, sizeof(nfs4_verifier)); WRITEMEM(readdir->rd_req_verifier, sizeof(nfs4_verifier));
...@@ -558,7 +573,7 @@ encode_rename(struct xdr_stream *xdr, struct nfs4_rename *rename) ...@@ -558,7 +573,7 @@ encode_rename(struct xdr_stream *xdr, struct nfs4_rename *rename)
WRITE32(rename->rn_oldnamelen); WRITE32(rename->rn_oldnamelen);
WRITEMEM(rename->rn_oldname, rename->rn_oldnamelen); WRITEMEM(rename->rn_oldname, rename->rn_oldnamelen);
RESERVE_SPACE(8 + rename->rn_newnamelen); RESERVE_SPACE(4 + rename->rn_newnamelen);
WRITE32(rename->rn_newnamelen); WRITE32(rename->rn_newnamelen);
WRITEMEM(rename->rn_newname, rename->rn_newnamelen); WRITEMEM(rename->rn_newname, rename->rn_newnamelen);
...@@ -605,7 +620,7 @@ encode_setattr(struct xdr_stream *xdr, struct nfs4_setattr *setattr) ...@@ -605,7 +620,7 @@ encode_setattr(struct xdr_stream *xdr, struct nfs4_setattr *setattr)
int status; int status;
uint32_t *p; uint32_t *p;
RESERVE_SPACE(20); RESERVE_SPACE(4+sizeof(nfs4_stateid));
WRITE32(OP_SETATTR); WRITE32(OP_SETATTR);
WRITEMEM(setattr->st_stateid, sizeof(nfs4_stateid)); WRITEMEM(setattr->st_stateid, sizeof(nfs4_stateid));
...@@ -626,7 +641,7 @@ encode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid *setclientid) ...@@ -626,7 +641,7 @@ encode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid *setclientid)
len2 = strlen(setclientid->sc_netid); len2 = strlen(setclientid->sc_netid);
len3 = strlen(setclientid->sc_uaddr); len3 = strlen(setclientid->sc_uaddr);
total_len = XDR_QUADLEN(len1) + XDR_QUADLEN(len2) + XDR_QUADLEN(len3); total_len = XDR_QUADLEN(len1) + XDR_QUADLEN(len2) + XDR_QUADLEN(len3);
total_len = (total_len << 2) + 32; total_len = (total_len << 2) + 24 + sizeof(nfs4_verifier);
RESERVE_SPACE(total_len); RESERVE_SPACE(total_len);
WRITE32(OP_SETCLIENTID); WRITE32(OP_SETCLIENTID);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment