From: "M. Mohan Kumar" <mo...@in.ibm.com> Add validatio check to {un}marshal code.
Signed-off-by: M. Mohan Kumar <mo...@in.ibm.com> --- fsdev/virtio-9p-marshal.c | 97 ++++++++++++------- fsdev/virtio-9p-marshal.h | 8 +- hw/9pfs/virtio-9p.c | 231 +++++++++++++++++++++++++++++++++------------ 3 files changed, 236 insertions(+), 100 deletions(-) diff --git a/fsdev/virtio-9p-marshal.c b/fsdev/virtio-9p-marshal.c index 2da0a34..74161df 100644 --- a/fsdev/virtio-9p-marshal.c +++ b/fsdev/virtio-9p-marshal.c @@ -62,14 +62,14 @@ void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs) } -static size_t v9fs_packunpack(void *addr, struct iovec *sg, int sg_count, - size_t offset, size_t size, int pack) +static ssize_t v9fs_packunpack(void *addr, struct iovec *sg, int sg_count, + ssize_t offset, ssize_t size, int pack) { int i = 0; - size_t copied = 0; + ssize_t copied = 0; for (i = 0; size && i < sg_count; i++) { - size_t len; + ssize_t len; if (offset >= sg[i].iov_len) { /* skip this sg */ offset -= sg[i].iov_len; @@ -91,25 +91,29 @@ static size_t v9fs_packunpack(void *addr, struct iovec *sg, int sg_count, } } + /* could not copy requested 'size' */ + if (copied < 0) { + return -1; + } return copied; } -static size_t v9fs_unpack(void *dst, struct iovec *out_sg, int out_num, - size_t offset, size_t size) +static ssize_t v9fs_unpack(void *dst, struct iovec *out_sg, int out_num, + ssize_t offset, ssize_t size) { return v9fs_packunpack(dst, out_sg, out_num, offset, size, 0); } -size_t v9fs_pack(struct iovec *in_sg, int in_num, size_t offset, - const void *src, size_t size) +ssize_t v9fs_pack(struct iovec *in_sg, int in_num, ssize_t offset, + const void *src, ssize_t size) { return v9fs_packunpack((void *)src, in_sg, in_num, offset, size, 1); } static int v9fs_copy_sg(struct iovec *src_sg, unsigned int num, - size_t offset, struct iovec *sg) + ssize_t offset, struct iovec *sg) { - size_t pos = 0; + ssize_t pos = 0; int i, j; j = 0; @@ -131,10 +135,10 @@ static int v9fs_copy_sg(struct iovec *src_sg, unsigned int num, return j; } -size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset, - int convert, const char *fmt, ...) +ssize_t v9fs_unmarshal(struct iovec *out_sg, + int out_num, ssize_t offset, int convert, const char *fmt, ...) { - size_t old_offset = offset; + ssize_t old_offset = offset, copied; va_list ap; int i; @@ -143,13 +147,13 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset, switch (fmt[i]) { case 'b': { uint8_t *valp = va_arg(ap, uint8_t *); - offset += v9fs_unpack(valp, out_sg, out_num, offset, sizeof(*valp)); + copied = v9fs_unpack(valp, out_sg, out_num, offset, sizeof(*valp)); break; } case 'w': { uint16_t val, *valp; valp = va_arg(ap, uint16_t *); - offset += v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val)); + copied = v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val)); if (convert) { *valp = le16_to_cpu(val); } else { @@ -160,7 +164,7 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset, case 'd': { uint32_t val, *valp; valp = va_arg(ap, uint32_t *); - offset += v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val)); + copied = v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val)); if (convert) { *valp = le32_to_cpu(val); } else { @@ -171,7 +175,7 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset, case 'q': { uint64_t val, *valp; valp = va_arg(ap, uint64_t *); - offset += v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val)); + copied = v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val)); if (convert) { *valp = le64_to_cpu(val); } else { @@ -187,24 +191,31 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset, } case 's': { V9fsString *str = va_arg(ap, V9fsString *); - offset += v9fs_unmarshal(out_sg, out_num, offset, convert, + copied = v9fs_unmarshal(out_sg, out_num, offset, convert, "w", &str->size); - /* FIXME: sanity check str->size */ + if (copied < 0) { + goto out; + } + offset += copied; str->data = g_malloc(str->size + 1); - offset += v9fs_unpack(str->data, out_sg, out_num, offset, + copied = v9fs_unpack(str->data, out_sg, out_num, offset, str->size); + if (copied < 0) { + g_free(str->data); + goto out; + } str->data[str->size] = 0; break; } case 'Q': { V9fsQID *qidp = va_arg(ap, V9fsQID *); - offset += v9fs_unmarshal(out_sg, out_num, offset, convert, "bdq", + copied = v9fs_unmarshal(out_sg, out_num, offset, convert, "bdq", &qidp->type, &qidp->version, &qidp->path); break; } case 'S': { V9fsStat *statp = va_arg(ap, V9fsStat *); - offset += v9fs_unmarshal(out_sg, out_num, offset, convert, + copied = v9fs_unmarshal(out_sg, out_num, offset, convert, "wwdQdddqsssssddd", &statp->size, &statp->type, &statp->dev, &statp->qid, &statp->mode, &statp->atime, @@ -217,7 +228,7 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset, } case 'I': { V9fsIattr *iattr = va_arg(ap, V9fsIattr *); - offset += v9fs_unmarshal(out_sg, out_num, offset, convert, + copied = v9fs_unmarshal(out_sg, out_num, offset, convert, "ddddqqqqq", &iattr->valid, &iattr->mode, &iattr->uid, &iattr->gid, &iattr->size, @@ -228,6 +239,12 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset, default: break; } +out: + if (copied < 0) { + va_end(ap); + return copied; + } + offset += copied; } va_end(ap); @@ -235,10 +252,10 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset, return offset - old_offset; } -size_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset, - int convert, const char *fmt, ...) +ssize_t v9fs_marshal(struct iovec *in_sg, int in_num, + ssize_t offset, int convert, const char *fmt, ...) { - size_t old_offset = offset; + ssize_t old_offset = offset, copied; va_list ap; int i; @@ -247,7 +264,7 @@ size_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset, switch (fmt[i]) { case 'b': { uint8_t val = va_arg(ap, int); - offset += v9fs_pack(in_sg, in_num, offset, &val, sizeof(val)); + copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val)); break; } case 'w': { @@ -257,7 +274,7 @@ size_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset, } else { val = va_arg(ap, int); } - offset += v9fs_pack(in_sg, in_num, offset, &val, sizeof(val)); + copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val)); break; } case 'd': { @@ -267,7 +284,7 @@ size_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset, } else { val = va_arg(ap, uint32_t); } - offset += v9fs_pack(in_sg, in_num, offset, &val, sizeof(val)); + copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val)); break; } case 'q': { @@ -277,7 +294,7 @@ size_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset, } else { val = va_arg(ap, uint64_t); } - offset += v9fs_pack(in_sg, in_num, offset, &val, sizeof(val)); + copied = v9fs_pack(in_sg, in_num, offset, &val, sizeof(val)); break; } case 'v': { @@ -288,20 +305,24 @@ size_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset, } case 's': { V9fsString *str = va_arg(ap, V9fsString *); - offset += v9fs_marshal(in_sg, in_num, offset, convert, + copied = v9fs_marshal(in_sg, in_num, offset, convert, "w", str->size); - offset += v9fs_pack(in_sg, in_num, offset, str->data, str->size); + if (copied < 0) { + goto out; + } + offset += copied; + copied = v9fs_pack(in_sg, in_num, offset, str->data, str->size); break; } case 'Q': { V9fsQID *qidp = va_arg(ap, V9fsQID *); - offset += v9fs_marshal(in_sg, in_num, offset, convert, "bdq", + copied = v9fs_marshal(in_sg, in_num, offset, convert, "bdq", qidp->type, qidp->version, qidp->path); break; } case 'S': { V9fsStat *statp = va_arg(ap, V9fsStat *); - offset += v9fs_marshal(in_sg, in_num, offset, convert, + copied = v9fs_marshal(in_sg, in_num, offset, convert, "wwdQdddqsssssddd", statp->size, statp->type, statp->dev, &statp->qid, statp->mode, statp->atime, @@ -313,7 +334,7 @@ size_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset, } case 'A': { V9fsStatDotl *statp = va_arg(ap, V9fsStatDotl *); - offset += v9fs_marshal(in_sg, in_num, offset, convert, + copied = v9fs_marshal(in_sg, in_num, offset, convert, "qQdddqqqqqqqqqqqqqqq", statp->st_result_mask, &statp->qid, statp->st_mode, @@ -331,6 +352,12 @@ size_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset, default: break; } +out: + if (copied < 0) { + va_end(ap); + return copied; + } + offset += copied; } va_end(ap); diff --git a/fsdev/virtio-9p-marshal.h b/fsdev/virtio-9p-marshal.h index fe2d34b..b268cbf 100644 --- a/fsdev/virtio-9p-marshal.h +++ b/fsdev/virtio-9p-marshal.h @@ -77,11 +77,11 @@ extern void v9fs_string_null(V9fsString *str); extern void v9fs_string_sprintf(V9fsString *str, const char *fmt, ...); extern void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs); -size_t v9fs_pack(struct iovec *in_sg, int in_num, size_t offset, - const void *src, size_t size); -size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset, +ssize_t v9fs_pack(struct iovec *in_sg, int in_num, ssize_t offset, + const void *src, ssize_t size); +ssize_t v9fs_unmarshal(struct iovec *out_sg, int out_num, ssize_t offset, int convert, const char *fmt, ...); -size_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset, +ssize_t v9fs_marshal(struct iovec *in_sg, int in_num, ssize_t offset, int convert, const char *fmt, ...); #endif diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c index 2a8ac56..774e945 100644 --- a/hw/9pfs/virtio-9p.c +++ b/hw/9pfs/virtio-9p.c @@ -897,6 +897,7 @@ static void v9fs_version(void *opaque) V9fsState *s = pdu->s; V9fsString version; size_t offset = 7; + ssize_t copied; pdu_unmarshal(pdu, offset, "ds", &s->msize, &version); trace_v9fs_version(pdu->tag, pdu->id, s->msize, version.data); @@ -909,11 +910,15 @@ static void v9fs_version(void *opaque) v9fs_string_sprintf(&version, "unknown"); } - offset += pdu_marshal(pdu, offset, "ds", s->msize, &version); + copied = pdu_marshal(pdu, offset, "ds", s->msize, &version); + if (copied < 0) { + offset = -EOVERFLOW; + goto out; + } + offset += copied; trace_v9fs_version_return(pdu->tag, pdu->id, s->msize, version.data); - +out: complete_pdu(s, pdu, offset); - v9fs_string_free(&version); return; } @@ -950,8 +955,13 @@ static void v9fs_attach(void *opaque) clunk_fid(s, fid); goto out; } - offset += pdu_marshal(pdu, offset, "Q", &qid); - err = offset; + err = pdu_marshal(pdu, offset, "Q", &qid); + if (err < 0) { + err = -EOVERFLOW; + clunk_fid(s, fid); + goto out; + } + err += offset; trace_v9fs_attach_return(pdu->tag, pdu->id, qid.type, qid.version, qid.path); out: @@ -989,10 +999,15 @@ static void v9fs_stat(void *opaque) if (err < 0) { goto out; } - offset += pdu_marshal(pdu, offset, "wS", 0, &v9stat); - err = offset; + err = pdu_marshal(pdu, offset, "wS", 0, &v9stat); + if (err < 0) { + err = -EOVERFLOW; + v9fs_stat_free(&v9stat); + goto out; + } trace_v9fs_stat_return(pdu->tag, pdu->id, v9stat.mode, v9stat.atime, v9stat.mtime, v9stat.length); + err += offset; v9fs_stat_free(&v9stat); out: put_fid(pdu, fidp); @@ -1038,8 +1053,12 @@ static void v9fs_getattr(void *opaque) } v9stat_dotl.st_result_mask |= P9_STATS_GEN; } - retval = offset; - retval += pdu_marshal(pdu, offset, "A", &v9stat_dotl); + retval = pdu_marshal(pdu, offset, "A", &v9stat_dotl); + if (retval < 0) { + retval = -EOVERFLOW; + goto out; + } + retval += offset; trace_v9fs_getattr_return(pdu->tag, pdu->id, v9stat_dotl.st_result_mask, v9stat_dotl.st_mode, v9stat_dotl.st_uid, v9stat_dotl.st_gid); @@ -1147,9 +1166,18 @@ static int v9fs_walk_marshal(V9fsPDU *pdu, uint16_t nwnames, V9fsQID *qids) { int i; size_t offset = 7; - offset += pdu_marshal(pdu, offset, "w", nwnames); + ssize_t copied; + copied = pdu_marshal(pdu, offset, "w", nwnames); + if (copied < 0) { + return -EOVERFLOW; + } + offset += copied; for (i = 0; i < nwnames; i++) { - offset += pdu_marshal(pdu, offset, "Q", &qids[i]); + copied = pdu_marshal(pdu, offset, "Q", &qids[i]); + if (copied < 0) { + return -EOVERFLOW; + } + offset += copied; } return offset; } @@ -1170,8 +1198,7 @@ static void v9fs_walk(void *opaque) V9fsPDU *pdu = opaque; V9fsState *s = pdu->s; - offset += pdu_unmarshal(pdu, offset, "ddw", &fid, - &newfid, &nwnames); + offset += pdu_unmarshal(pdu, offset, "ddw", &fid, &newfid, &nwnames); trace_v9fs_walk(pdu->tag, pdu->id, fid, newfid, nwnames); @@ -1302,8 +1329,12 @@ static void v9fs_open(void *opaque) goto out; } fidp->fid_type = P9_FID_DIR; - offset += pdu_marshal(pdu, offset, "Qd", &qid, 0); - err = offset; + err = pdu_marshal(pdu, offset, "Qd", &qid, 0); + if (err < 0) { + err = -EOVERFLOW; + goto out; + } + err += offset; } else { if (s->proto_version == V9FS_PROTO_2000L) { flags = get_dotl_openflags(s, mode); @@ -1332,8 +1363,12 @@ static void v9fs_open(void *opaque) fidp->flags |= FID_NON_RECLAIMABLE; } iounit = get_iounit(pdu, &fidp->path); - offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit); - err = offset; + err = pdu_marshal(pdu, offset, "Qd", &qid, iounit); + if (err < 0) { + err = -EOVERFLOW; + goto out; + } + err += offset; } trace_v9fs_open_return(pdu->tag, pdu->id, qid.type, qid.version, qid.path, iounit); @@ -1356,8 +1391,8 @@ static void v9fs_lcreate(void *opaque) int32_t iounit; V9fsPDU *pdu = opaque; - pdu_unmarshal(pdu, offset, "dsddd", &dfid, &name, &flags, - &mode, &gid); + offset += pdu_unmarshal(pdu, offset, "dsddd", &dfid, &name, &flags, + &mode, &gid); trace_v9fs_lcreate(pdu->tag, pdu->id, dfid, flags, mode, gid); fidp = get_fid(pdu, dfid); @@ -1383,8 +1418,12 @@ static void v9fs_lcreate(void *opaque) } iounit = get_iounit(pdu, &fidp->path); stat_to_qid(&stbuf, &qid); - offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit); - err = offset; + err = pdu_marshal(pdu, offset, "Qd", &qid, iounit); + if (err < 0) { + err = -EOVERFLOW; + goto out; + } + err += offset; trace_v9fs_lcreate_return(pdu->tag, pdu->id, qid.type, qid.version, qid.path, iounit); out: @@ -1456,6 +1495,7 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, size_t offset = 7; int read_count; int64_t xattr_len; + ssize_t copied; xattr_len = fidp->fs.xattr.len; read_count = xattr_len - off; @@ -1467,11 +1507,18 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, */ read_count = 0; } - offset += pdu_marshal(pdu, offset, "d", read_count); - offset += v9fs_pack(pdu->elem.in_sg, pdu->elem.in_num, offset, + copied = pdu_marshal(pdu, offset, "d", read_count); + if (copied < 0) { + return -1; + } + offset += copied; + copied = v9fs_pack(pdu->elem.in_sg, pdu->elem.in_num, offset, ((char *)fidp->fs.xattr.value) + off, read_count); - + if (copied < 0) { + return -1; + } + offset += copied; return offset; } @@ -1566,9 +1613,12 @@ static void v9fs_read(void *opaque) err = count; goto out; } - err = offset; - err += pdu_marshal(pdu, offset, "d", count); - err += count; + err = pdu_marshal(pdu, offset, "d", count); + if (err < 0) { + err = -EOVERFLOW; + goto out; + } + err += offset + count; } else if (fidp->fid_type == P9_FID_FILE) { int32_t cnt; int32_t len; @@ -1576,7 +1626,11 @@ static void v9fs_read(void *opaque) struct iovec iov[128]; /* FIXME: bad, bad, bad */ sg = iov; - pdu_marshal(pdu, offset + 4, "v", sg, &cnt); + err = pdu_marshal(pdu, offset + 4, "v", sg, &cnt); + if (err < 0) { + err = -EOVERFLOW; + goto out; + } sg = cap_sg(sg, max_count, &cnt); do { if (0) { @@ -1597,9 +1651,12 @@ static void v9fs_read(void *opaque) } sg = adjust_sg(sg, len, &cnt); } while (count < max_count && len > 0); - err = offset; - err += pdu_marshal(pdu, offset, "d", count); - err += count; + err = pdu_marshal(pdu, offset, "d", count); + if (err < 0) { + err = -EOVERFLOW; + goto out; + } + err += offset + count; } else if (fidp->fid_type == P9_FID_XATTR) { err = v9fs_xattr_read(s, pdu, fidp, off, max_count); } else { @@ -1669,6 +1726,9 @@ static int v9fs_do_readdir(V9fsPDU *pdu, len = pdu_marshal(pdu, 11 + count, "Qqbs", &qid, dent->d_off, dent->d_type, &name); + if (len < 0) { + return -EOVERFLOW; + } count += len; v9fs_string_free(&name); saved_dir_pos = dent->d_off; @@ -1714,9 +1774,12 @@ static void v9fs_readdir(void *opaque) retval = count; goto out; } - retval = offset; - retval += pdu_marshal(pdu, offset, "d", count); - retval += count; + retval = pdu_marshal(pdu, offset, "d", count); + if (retval < 0) { + retval = -EOVERFLOW; + goto out; + } + retval += count + offset; trace_v9fs_readdir_return(pdu->tag, pdu->id, count, retval); out: put_fid(pdu, fidp); @@ -1747,8 +1810,11 @@ static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, err = -ENOSPC; goto out; } - offset += pdu_marshal(pdu, offset, "d", write_count); - err = offset; + err = pdu_marshal(pdu, offset, "d", write_count); + if (err < 0) { + return -EOVERFLOW; + } + err += offset; fidp->fs.xattr.copied_len += write_count; /* * Now copy the content from sg list @@ -1827,8 +1893,12 @@ static void v9fs_write(void *opaque) } sg = adjust_sg(sg, len, &cnt); } while (total < count && len > 0); - offset += pdu_marshal(pdu, offset, "d", total); - err = offset; + err = pdu_marshal(pdu, offset, "d", total); + if (err < 0) { + err = -EOVERFLOW; + goto out; + } + err += offset; trace_v9fs_write_return(pdu->tag, pdu->id, total, err); out: put_fid(pdu, fidp); @@ -1987,8 +2057,12 @@ static void v9fs_create(void *opaque) } iounit = get_iounit(pdu, &fidp->path); stat_to_qid(&stbuf, &qid); - offset += pdu_marshal(pdu, offset, "Qd", &qid, iounit); - err = offset; + err = pdu_marshal(pdu, offset, "Qd", &qid, iounit); + if (err < 0) { + err = -EOVERFLOW; + goto out; + } + err += offset; trace_v9fs_create_return(pdu->tag, pdu->id, qid.type, qid.version, qid.path, iounit); out: @@ -2026,8 +2100,12 @@ static void v9fs_symlink(void *opaque) goto out; } stat_to_qid(&stbuf, &qid); - offset += pdu_marshal(pdu, offset, "Q", &qid); - err = offset; + err = pdu_marshal(pdu, offset, "Q", &qid); + if (err < 0) { + err = -EOVERFLOW; + goto out; + } + err += offset; trace_v9fs_symlink_return(pdu->tag, pdu->id, qid.type, qid.version, qid.path); out: @@ -2535,8 +2613,12 @@ static void v9fs_statfs(void *opaque) if (retval < 0) { goto out; } - retval = offset; - retval += v9fs_fill_statfs(s, pdu, &stbuf); + retval = v9fs_fill_statfs(s, pdu, &stbuf); + if (retval < 0) { + retval = -EOVERFLOW; + goto out; + } + retval += offset; out: put_fid(pdu, fidp); out_nofid: @@ -2575,8 +2657,12 @@ static void v9fs_mknod(void *opaque) goto out; } stat_to_qid(&stbuf, &qid); - err = offset; - err += pdu_marshal(pdu, offset, "Q", &qid); + err = pdu_marshal(pdu, offset, "Q", &qid); + if (err < 0) { + err = -EOVERFLOW; + goto out; + } + err += offset; trace_v9fs_mknod_return(pdu->tag, pdu->id, qid.type, qid.version, qid.path); out: @@ -2633,8 +2719,12 @@ static void v9fs_lock(void *opaque) out: put_fid(pdu, fidp); out_nofid: - err = offset; - err += pdu_marshal(pdu, offset, "b", status); + err = pdu_marshal(pdu, offset, "b", status); + if (err < 0) { + err = -EOVERFLOW; + } else { + err += offset; + } trace_v9fs_lock_return(pdu->tag, pdu->id, status); complete_pdu(s, pdu, err); v9fs_string_free(&flock->client_id); @@ -2673,10 +2763,14 @@ static void v9fs_getlock(void *opaque) goto out; } glock->type = P9_LOCK_TYPE_UNLCK; - offset += pdu_marshal(pdu, offset, "bqqds", glock->type, + err = pdu_marshal(pdu, offset, "bqqds", glock->type, glock->start, glock->length, glock->proc_id, &glock->client_id); - err = offset; + if (err < 0) { + err = -EOVERFLOW; + goto out; + } + err += offset; trace_v9fs_getlock_return(pdu->tag, pdu->id, glock->type, glock->start, glock->length, glock->proc_id); out: @@ -2701,7 +2795,6 @@ static void v9fs_mkdir(void *opaque) int err = 0; pdu_unmarshal(pdu, offset, "dsdd", &fid, &name, &mode, &gid); - trace_v9fs_mkdir(pdu->tag, pdu->id, fid, name.data, mode, gid); fidp = get_fid(pdu, fid); @@ -2714,8 +2807,12 @@ static void v9fs_mkdir(void *opaque) goto out; } stat_to_qid(&stbuf, &qid); - offset += pdu_marshal(pdu, offset, "Q", &qid); - err = offset; + err = pdu_marshal(pdu, offset, "Q", &qid); + if (err < 0) { + err = -EOVERFLOW; + goto out; + } + err += offset; trace_v9fs_mkdir_return(pdu->tag, pdu->id, qid.type, qid.version, qid.path, err); out: @@ -2777,8 +2874,12 @@ static void v9fs_xattrwalk(void *opaque) goto out; } } - offset += pdu_marshal(pdu, offset, "q", size); - err = offset; + err = pdu_marshal(pdu, offset, "q", size); + if (err < 0) { + err = -EOVERFLOW; + goto out; + } + err += offset; } else { /* * specific xattr fid. We check for xattr @@ -2807,8 +2908,12 @@ static void v9fs_xattrwalk(void *opaque) goto out; } } - offset += pdu_marshal(pdu, offset, "q", size); - err = offset; + err = pdu_marshal(pdu, offset, "q", size); + if (err < 0) { + err = -EOVERFLOW; + goto out; + } + err += offset; } trace_v9fs_xattrwalk_return(pdu->tag, pdu->id, size); out: @@ -2834,8 +2939,7 @@ static void v9fs_xattrcreate(void *opaque) V9fsPDU *pdu = opaque; V9fsState *s = pdu->s; - pdu_unmarshal(pdu, offset, "dsqd", - &fid, &name, &size, &flags); + pdu_unmarshal(pdu, offset, "dsqd", &fid, &name, &size, &flags); trace_v9fs_xattrcreate(pdu->tag, pdu->id, fid, name.data, size, flags); file_fidp = get_fid(pdu, fid); @@ -2885,8 +2989,13 @@ static void v9fs_readlink(void *opaque) if (err < 0) { goto out; } - offset += pdu_marshal(pdu, offset, "s", &target); - err = offset; + err = pdu_marshal(pdu, offset, "s", &target); + if (err < 0) { + err = -EOVERFLOW; + v9fs_string_free(&target); + goto out; + } + err += offset; trace_v9fs_readlink_return(pdu->tag, pdu->id, target.data); v9fs_string_free(&target); out: -- 1.7.6