aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4xdr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r--fs/nfs/nfs4xdr.c41
1 files changed, 16 insertions, 25 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index ca13483edd60..8dba6bd48557 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -5045,22 +5045,19 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
5045 struct nfs_getaclres *res) 5045 struct nfs_getaclres *res)
5046{ 5046{
5047 unsigned int savep; 5047 unsigned int savep;
5048 __be32 *bm_p;
5049 uint32_t attrlen, 5048 uint32_t attrlen,
5050 bitmap[3] = {0}; 5049 bitmap[3] = {0};
5051 int status; 5050 int status;
5052 size_t page_len = xdr->buf->page_len; 5051 unsigned int pg_offset;
5053 5052
5054 res->acl_len = 0; 5053 res->acl_len = 0;
5055 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) 5054 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
5056 goto out; 5055 goto out;
5057 5056
5058 bm_p = xdr->p; 5057 xdr_enter_page(xdr, xdr->buf->page_len);
5059 res->acl_data_offset = be32_to_cpup(bm_p) + 2; 5058
5060 res->acl_data_offset <<= 2; 5059 /* Calculate the offset of the page data */
5061 /* Check if the acl data starts beyond the allocated buffer */ 5060 pg_offset = xdr->buf->head[0].iov_len;
5062 if (res->acl_data_offset > page_len)
5063 return -ERANGE;
5064 5061
5065 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) 5062 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
5066 goto out; 5063 goto out;
@@ -5074,23 +5071,16 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
5074 /* The bitmap (xdr len + bitmaps) and the attr xdr len words 5071 /* The bitmap (xdr len + bitmaps) and the attr xdr len words
5075 * are stored with the acl data to handle the problem of 5072 * are stored with the acl data to handle the problem of
5076 * variable length bitmaps.*/ 5073 * variable length bitmaps.*/
5077 xdr->p = bm_p; 5074 res->acl_data_offset = xdr_stream_pos(xdr) - pg_offset;
5078
5079 /* We ignore &savep and don't do consistency checks on
5080 * the attr length. Let userspace figure it out.... */
5081 attrlen += res->acl_data_offset;
5082 if (attrlen > page_len) {
5083 if (res->acl_flags & NFS4_ACL_LEN_REQUEST) {
5084 /* getxattr interface called with a NULL buf */
5085 res->acl_len = attrlen;
5086 goto out;
5087 }
5088 dprintk("NFS: acl reply: attrlen %u > page_len %zu\n",
5089 attrlen, page_len);
5090 return -EINVAL;
5091 }
5092 xdr_read_pages(xdr, attrlen);
5093 res->acl_len = attrlen; 5075 res->acl_len = attrlen;
5076
5077 /* Check for receive buffer overflow */
5078 if (res->acl_len > (xdr->nwords << 2) ||
5079 res->acl_len + res->acl_data_offset > xdr->buf->page_len) {
5080 res->acl_flags |= NFS4_ACL_TRUNC;
5081 dprintk("NFS: acl reply: attrlen %u > page_len %u\n",
5082 attrlen, xdr->nwords << 2);
5083 }
5094 } else 5084 } else
5095 status = -EOPNOTSUPP; 5085 status = -EOPNOTSUPP;
5096 5086
@@ -6235,7 +6225,8 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6235 status = decode_open(xdr, res); 6225 status = decode_open(xdr, res);
6236 if (status) 6226 if (status)
6237 goto out; 6227 goto out;
6238 if (decode_getfh(xdr, &res->fh) != 0) 6228 status = decode_getfh(xdr, &res->fh);
6229 if (status)
6239 goto out; 6230 goto out;
6240 decode_getfattr(xdr, res->f_attr, res->server); 6231 decode_getfattr(xdr, res->f_attr, res->server);
6241out: 6232out: