Loading net/sunrpc/xdr.c +26 −33 Original line number Diff line number Diff line Loading @@ -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 * try to find space for it at the end of the tail, copy it there, and * set obj to point to it. */ int xdr_buf_read_netobj(struct xdr_buf *buf, struct xdr_netobj *obj, unsigned int offset) int 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; unsigned int obj_end_offset; struct xdr_buf subbuf; if (xdr_decode_word(buf, offset, &obj->len)) goto out; obj_end_offset = offset + 4 + obj->len; 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 { return -EFAULT; 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; /* use end of tail as storage for obj: * (We don't copy to the beginning because then we'd have * to worry about doing a potentially overlapping copy. * This assumes the object is at most half the length of the * tail.) */ if (obj->len > buf->tail[0].iov_len) goto out; obj->data = buf->tail[0].iov_base + buf->tail[0].iov_len - obj->len; if (read_bytes_from_xdr_buf(buf, offset + 4, obj->data, obj->len)) goto out; } if (obj->len > buf->buflen - buf->len) return -ENOMEM; if (buf->tail[0].iov_len != 0) obj->data = buf->tail[0].iov_base + buf->tail[0].iov_len; else obj->data = buf->head[0].iov_base + buf->head[0].iov_len; __read_bytes_from_xdr_buf(&subbuf, obj->data, obj->len); return 0; out: return -1; } /* Returns 0 on success, or else a negative error code. */ Loading Loading
net/sunrpc/xdr.c +26 −33 Original line number Diff line number Diff line Loading @@ -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 * try to find space for it at the end of the tail, copy it there, and * set obj to point to it. */ int xdr_buf_read_netobj(struct xdr_buf *buf, struct xdr_netobj *obj, unsigned int offset) int 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; unsigned int obj_end_offset; struct xdr_buf subbuf; if (xdr_decode_word(buf, offset, &obj->len)) goto out; obj_end_offset = offset + 4 + obj->len; 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 { return -EFAULT; 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; /* use end of tail as storage for obj: * (We don't copy to the beginning because then we'd have * to worry about doing a potentially overlapping copy. * This assumes the object is at most half the length of the * tail.) */ if (obj->len > buf->tail[0].iov_len) goto out; obj->data = buf->tail[0].iov_base + buf->tail[0].iov_len - obj->len; if (read_bytes_from_xdr_buf(buf, offset + 4, obj->data, obj->len)) goto out; } if (obj->len > buf->buflen - buf->len) return -ENOMEM; if (buf->tail[0].iov_len != 0) obj->data = buf->tail[0].iov_base + buf->tail[0].iov_len; else obj->data = buf->head[0].iov_base + buf->head[0].iov_len; __read_bytes_from_xdr_buf(&subbuf, obj->data, obj->len); return 0; out: return -1; } /* Returns 0 on success, or else a negative error code. */ Loading