Commit bee57c99 authored by Trond Myklebust's avatar Trond Myklebust

SUNRPC: Ensure xdr_buf_read_netobj() checks for memory overruns

Also clean up the code...
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 4e3e43ad
...@@ -773,44 +773,37 @@ xdr_encode_word(struct xdr_buf *buf, unsigned int base, u32 obj) ...@@ -773,44 +773,37 @@ xdr_encode_word(struct xdr_buf *buf, unsigned int base, u32 obj)
* entirely in the head or the tail, set object to point to it; otherwise * entirely in the head or the tail, set object to point to it; otherwise
* try to find space for it at the end of the tail, copy it there, and * try to find space for it at the end of the tail, copy it there, and
* set obj to point to it. */ * set obj to point to it. */
int int xdr_buf_read_netobj(struct xdr_buf *buf, struct xdr_netobj *obj, unsigned int offset)
xdr_buf_read_netobj(struct xdr_buf *buf, struct xdr_netobj *obj, unsigned int offset)
{ {
unsigned int tail_offset = buf->head[0].iov_len + buf->page_len; struct xdr_buf subbuf;
unsigned int obj_end_offset;
if (xdr_decode_word(buf, offset, &obj->len)) if (xdr_decode_word(buf, offset, &obj->len))
goto out; return -EFAULT;
obj_end_offset = offset + 4 + obj->len; if (xdr_buf_subsegment(buf, &subbuf, offset + 4, obj->len))
return -EFAULT;
if (obj_end_offset <= buf->head[0].iov_len) {
/* The obj is contained entirely in the head: */ /* Is the obj contained entirely in the head? */
obj->data = buf->head[0].iov_base + offset + 4; obj->data = subbuf.head[0].iov_base;
} else if (offset + 4 >= tail_offset) { if (subbuf.head[0].iov_len == obj->len)
if (obj_end_offset - tail_offset return 0;
> buf->tail[0].iov_len) /* ..or is the obj contained entirely in the tail? */
goto out; obj->data = subbuf.tail[0].iov_base;
/* The obj is contained entirely in the tail: */ if (subbuf.tail[0].iov_len == obj->len)
obj->data = buf->tail[0].iov_base return 0;
+ offset - tail_offset + 4;
} else {
/* use end of tail as storage for obj: /* use end of tail as storage for obj:
* (We don't copy to the beginning because then we'd have * (We don't copy to the beginning because then we'd have
* to worry about doing a potentially overlapping copy. * to worry about doing a potentially overlapping copy.
* This assumes the object is at most half the length of the * This assumes the object is at most half the length of the
* tail.) */ * tail.) */
if (obj->len > buf->tail[0].iov_len) if (obj->len > buf->buflen - buf->len)
goto out; return -ENOMEM;
obj->data = buf->tail[0].iov_base + buf->tail[0].iov_len - if (buf->tail[0].iov_len != 0)
obj->len; obj->data = buf->tail[0].iov_base + buf->tail[0].iov_len;
if (read_bytes_from_xdr_buf(buf, offset + 4, else
obj->data, obj->len)) obj->data = buf->head[0].iov_base + buf->head[0].iov_len;
goto out; __read_bytes_from_xdr_buf(&subbuf, obj->data, obj->len);
}
return 0; return 0;
out:
return -1;
} }
/* Returns 0 on success, or else a negative error code. */ /* Returns 0 on success, or else a negative error code. */
......
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