SUNRPC: Ensure xdr_buf_read_netobj() checks for memory overruns
Also clean up the code... Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
Родитель
4e3e43ad14
Коммит
bee57c99c3
|
@ -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;
|
||||||
|
|
||||||
|
/* Is the obj contained entirely in the head? */
|
||||||
|
obj->data = subbuf.head[0].iov_base;
|
||||||
|
if (subbuf.head[0].iov_len == obj->len)
|
||||||
|
return 0;
|
||||||
|
/* ..or is the obj contained entirely in the tail? */
|
||||||
|
obj->data = subbuf.tail[0].iov_base;
|
||||||
|
if (subbuf.tail[0].iov_len == obj->len)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (obj_end_offset <= buf->head[0].iov_len) {
|
|
||||||
/* The obj is contained entirely in the head: */
|
|
||||||
obj->data = buf->head[0].iov_base + offset + 4;
|
|
||||||
} else if (offset + 4 >= tail_offset) {
|
|
||||||
if (obj_end_offset - tail_offset
|
|
||||||
> buf->tail[0].iov_len)
|
|
||||||
goto out;
|
|
||||||
/* The obj is contained entirely in the tail: */
|
|
||||||
obj->data = buf->tail[0].iov_base
|
|
||||||
+ 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. */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче