diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2016-11-01 12:48:07 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2016-11-01 12:48:07 +0000 |
commit | 39542105bbb19c690219d2f22844d8dfbd9bba05 (patch) | |
tree | ea9be2b3d2c88e60342c3b4993b4031dab68e430 | |
parent | 38ab359644e7f26b1d77842ab29c4d425e5e540c (diff) | |
parent | 79decce35b4d769fa878b048ab1a7b3e9045c9c6 (diff) |
Merge remote-tracking branch 'remotes/gkurz/tags/for-upstream' into staging
This pull request mostly contains some more fixes to prevent buggy guests from
breaking QEMU.
# gpg: Signature made Tue 01 Nov 2016 11:26:42 GMT
# gpg: using DSA key 0x02FC3AEB0101DBC2
# gpg: Good signature from "Greg Kurz <groug@kaod.org>"
# gpg: aka "Greg Kurz <groug@free.fr>"
# gpg: aka "Greg Kurz <gkurz@fr.ibm.com>"
# gpg: aka "Greg Kurz <gkurz@linux.vnet.ibm.com>"
# gpg: aka "Gregory Kurz (Groug) <groug@free.fr>"
# gpg: aka "Gregory Kurz (Cimai Technology) <gkurz@cimai.com>"
# gpg: aka "Gregory Kurz (Meiosys Technology) <gkurz@meiosys.com>"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg: There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 2BD4 3B44 535E C0A7 9894 DBA2 02FC 3AEB 0101 DBC2
* remotes/gkurz/tags/for-upstream:
9pfs: drop excessive error message from virtfs_reset()
9pfs: don't BUG_ON() if fid is already opened
9pfs: xattrcreate requires non-opened fids
9pfs: limit xattr size in xattrcreate
9pfs: fix integer overflow issue in xattr read/write
9pfs: convert 'len/copied_len' field in V9fsXattr to the type of uint64_t
9pfs: add xattrwalk_fid field in V9fsXattr struct
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | hw/9pfs/9p.c | 80 | ||||
-rw-r--r-- | hw/9pfs/9p.h | 5 | ||||
-rw-r--r-- | hw/9pfs/trace-events | 2 |
3 files changed, 49 insertions, 38 deletions
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index e88cf257a2..aea7e9d392 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -325,7 +325,7 @@ static int coroutine_fn v9fs_xattr_fid_clunk(V9fsPDU *pdu, V9fsFidState *fidp) { int retval = 0; - if (fidp->fs.xattr.copied_len == -1) { + if (fidp->fs.xattr.xattrwalk_fid) { /* getxattr/listxattr fid */ goto free_value; } @@ -535,7 +535,7 @@ static int coroutine_fn v9fs_mark_fids_unreclaim(V9fsPDU *pdu, V9fsPath *path) static void coroutine_fn virtfs_reset(V9fsPDU *pdu) { V9fsState *s = pdu->s; - V9fsFidState *fidp = NULL; + V9fsFidState *fidp; /* Free all fids */ while (s->fid_list) { @@ -548,11 +548,6 @@ static void coroutine_fn virtfs_reset(V9fsPDU *pdu) free_fid(pdu, fidp); } } - if (fidp) { - /* One or more unclunked fids found... */ - error_report("9pfs:%s: One or more uncluncked fids " - "found during reset", __func__); - } } #define P9_QID_TYPE_DIR 0x80 @@ -1361,7 +1356,10 @@ static void coroutine_fn v9fs_walk(void *opaque) memcpy(&qids[name_idx], &qid, sizeof(qid)); } if (fid == newfid) { - BUG_ON(fidp->fid_type != P9_FID_NONE); + if (fidp->fid_type != P9_FID_NONE) { + err = -EINVAL; + goto out; + } v9fs_path_copy(&fidp->path, &path); } else { newfidp = alloc_fid(s, newfid); @@ -1443,7 +1441,10 @@ static void coroutine_fn v9fs_open(void *opaque) err = -ENOENT; goto out_nofid; } - BUG_ON(fidp->fid_type != P9_FID_NONE); + if (fidp->fid_type != P9_FID_NONE) { + err = -EINVAL; + goto out; + } err = v9fs_co_lstat(pdu, &fidp->path, &stbuf); if (err < 0) { @@ -1637,20 +1638,17 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, { ssize_t err; size_t offset = 7; - int read_count; - int64_t xattr_len; + uint64_t read_count; V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); VirtQueueElement *elem = v->elems[pdu->idx]; - xattr_len = fidp->fs.xattr.len; - read_count = xattr_len - off; + if (fidp->fs.xattr.len < off) { + read_count = 0; + } else { + read_count = fidp->fs.xattr.len - off; + } if (read_count > max_count) { read_count = max_count; - } else if (read_count < 0) { - /* - * read beyond XATTR value - */ - read_count = 0; } err = pdu_marshal(pdu, offset, "d", read_count); if (err < 0) { @@ -1979,23 +1977,18 @@ static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, { int i, to_copy; ssize_t err = 0; - int write_count; - int64_t xattr_len; + uint64_t write_count; size_t offset = 7; - xattr_len = fidp->fs.xattr.len; - write_count = xattr_len - off; - if (write_count > count) { - write_count = count; - } else if (write_count < 0) { - /* - * write beyond XATTR value len specified in - * xattrcreate - */ + if (fidp->fs.xattr.len < off) { err = -ENOSPC; goto out; } + write_count = fidp->fs.xattr.len - off; + if (write_count > count) { + write_count = count; + } err = pdu_marshal(pdu, offset, "d", write_count); if (err < 0) { return err; @@ -2548,7 +2541,10 @@ static int coroutine_fn v9fs_complete_rename(V9fsPDU *pdu, V9fsFidState *fidp, err = -ENOENT; goto out_nofid; } - BUG_ON(dirfidp->fid_type != P9_FID_NONE); + if (fidp->fid_type != P9_FID_NONE) { + err = -EINVAL; + goto out; + } v9fs_co_name_to_path(pdu, &dirfidp->path, name->data, &new_path); } else { old_name = fidp->path.data; @@ -2620,7 +2616,10 @@ static void coroutine_fn v9fs_rename(void *opaque) err = -ENOENT; goto out_nofid; } - BUG_ON(fidp->fid_type != P9_FID_NONE); + if (fidp->fid_type != P9_FID_NONE) { + err = -EINVAL; + goto out; + } /* if fs driver is not path based, return EOPNOTSUPP */ if (!(pdu->s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT)) { err = -EOPNOTSUPP; @@ -3190,7 +3189,7 @@ static void coroutine_fn v9fs_xattrwalk(void *opaque) */ xattr_fidp->fs.xattr.len = size; xattr_fidp->fid_type = P9_FID_XATTR; - xattr_fidp->fs.xattr.copied_len = -1; + xattr_fidp->fs.xattr.xattrwalk_fid = true; if (size) { xattr_fidp->fs.xattr.value = g_malloc(size); err = v9fs_co_llistxattr(pdu, &xattr_fidp->path, @@ -3223,7 +3222,7 @@ static void coroutine_fn v9fs_xattrwalk(void *opaque) */ xattr_fidp->fs.xattr.len = size; xattr_fidp->fid_type = P9_FID_XATTR; - xattr_fidp->fs.xattr.copied_len = -1; + xattr_fidp->fs.xattr.xattrwalk_fid = true; if (size) { xattr_fidp->fs.xattr.value = g_malloc(size); err = v9fs_co_lgetxattr(pdu, &xattr_fidp->path, @@ -3255,7 +3254,7 @@ static void coroutine_fn v9fs_xattrcreate(void *opaque) { int flags; int32_t fid; - int64_t size; + uint64_t size; ssize_t err = 0; V9fsString name; size_t offset = 7; @@ -3270,22 +3269,33 @@ static void coroutine_fn v9fs_xattrcreate(void *opaque) } trace_v9fs_xattrcreate(pdu->tag, pdu->id, fid, name.data, size, flags); + if (size > XATTR_SIZE_MAX) { + err = -E2BIG; + goto out_nofid; + } + file_fidp = get_fid(pdu, fid); if (file_fidp == NULL) { err = -EINVAL; goto out_nofid; } + if (file_fidp->fid_type != P9_FID_NONE) { + err = -EINVAL; + goto out_put_fid; + } + /* Make the file fid point to xattr */ xattr_fidp = file_fidp; xattr_fidp->fid_type = P9_FID_XATTR; xattr_fidp->fs.xattr.copied_len = 0; + xattr_fidp->fs.xattr.xattrwalk_fid = false; xattr_fidp->fs.xattr.len = size; xattr_fidp->fs.xattr.flags = flags; v9fs_string_init(&xattr_fidp->fs.xattr.name); v9fs_string_copy(&xattr_fidp->fs.xattr.name, &name); - g_free(xattr_fidp->fs.xattr.value); xattr_fidp->fs.xattr.value = g_malloc0(size); err = offset; +out_put_fid: put_fid(pdu, file_fidp); out_nofid: pdu_complete(pdu, err); diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h index 2523a445f8..3976b7fe3d 100644 --- a/hw/9pfs/9p.h +++ b/hw/9pfs/9p.h @@ -159,11 +159,12 @@ typedef struct V9fsConf typedef struct V9fsXattr { - int64_t copied_len; - int64_t len; + uint64_t copied_len; + uint64_t len; void *value; V9fsString name; int flags; + bool xattrwalk_fid; } V9fsXattr; typedef struct V9fsDir { diff --git a/hw/9pfs/trace-events b/hw/9pfs/trace-events index 48d3d8abed..fb4de3d465 100644 --- a/hw/9pfs/trace-events +++ b/hw/9pfs/trace-events @@ -42,6 +42,6 @@ v9fs_mkdir(uint16_t tag, uint8_t id, int32_t fid, char* name, int mode, uint32_t v9fs_mkdir_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int err) "tag %u id %u qid={type %d version %d path %"PRId64"} err %d" v9fs_xattrwalk(uint16_t tag, uint8_t id, int32_t fid, int32_t newfid, char* name) "tag %d id %d fid %d newfid %d name %s" v9fs_xattrwalk_return(uint16_t tag, uint8_t id, int64_t size) "tag %d id %d size %"PRId64 -v9fs_xattrcreate(uint16_t tag, uint8_t id, int32_t fid, char* name, int64_t size, int flags) "tag %d id %d fid %d name %s size %"PRId64" flags %d" +v9fs_xattrcreate(uint16_t tag, uint8_t id, int32_t fid, char* name, uint64_t size, int flags) "tag %d id %d fid %d name %s size %"PRIu64" flags %d" v9fs_readlink(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d" v9fs_readlink_return(uint16_t tag, uint8_t id, char* target) "tag %d id %d name %s" |