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:
Trond Myklebust 2006-10-09 22:08:22 -04:00
Родитель 4e3e43ad14
Коммит bee57c99c3
1 изменённых файлов: 25 добавлений и 32 удалений

Просмотреть файл

@ -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. */