From e5f1c19665b3cf7ff33431c1c8c898177504dcd5 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 8 Feb 2011 15:12:38 +0100 Subject: blockdev: Plug memory leak in drive_uninit() Started leaking in commit 1dae12e6. Signed-off-by: Markus Armbruster --- blockdev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/blockdev.c b/blockdev.c index ecfadc138..24d765806 100644 --- a/blockdev.c +++ b/blockdev.c @@ -182,6 +182,7 @@ static void drive_uninit(DriveInfo *dinfo) { qemu_opts_del(dinfo->opts); bdrv_delete(dinfo->bdrv); + qemu_free(dinfo->id); QTAILQ_REMOVE(&drives, dinfo, next); qemu_free(dinfo); } -- cgit v1.2.3 From 0893194783a006380b8b7cf0c0d79041bd4da93f Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 8 Feb 2011 15:12:39 +0100 Subject: blockdev: Plug memory leak in drive_init() error paths Should have spotted this when doing commit 319ae529. Signed-off-by: Markus Armbruster --- blockdev.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/blockdev.c b/blockdev.c index 24d765806..0690cc8be 100644 --- a/blockdev.c +++ b/blockdev.c @@ -526,7 +526,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) } else if (ro == 1) { if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) { error_report("readonly not supported by this bus type"); - return NULL; + goto err; } } @@ -536,12 +536,19 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) if (ret < 0) { error_report("could not open disk image %s: %s", file, strerror(-ret)); - return NULL; + goto err; } if (bdrv_key_required(dinfo->bdrv)) autostart = 0; return dinfo; + +err: + bdrv_delete(dinfo->bdrv); + qemu_free(dinfo->id); + QTAILQ_REMOVE(&drives, dinfo, next); + qemu_free(dinfo); + return NULL; } void do_commit(Monitor *mon, const QDict *qdict) -- cgit v1.2.3 From 28637533d655b1427d3ebfc1dc3ac4f1b16dfa86 Mon Sep 17 00:00:00 2001 From: Martin Mohring Date: Tue, 8 Feb 2011 14:48:56 +0200 Subject: linux-user: fix for loopmount ioctl In case a chrooted build uses XEN or KVM, a looped mount needs to be done to setup the chroot. The ioctl for loop mount works correctly for arm, mips, ppc32 and sh4, so its now activated. Signed-off-by: Riku Voipio --- linux-user/ioctls.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index acff78108..526aaa2a7 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -312,10 +312,8 @@ IOCTL(LOOP_CLR_FD, 0, TYPE_INT) IOCTL(LOOP_SET_STATUS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info))) IOCTL(LOOP_GET_STATUS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info))) -#if 0 /* These have some problems - not fully tested */ IOCTL(LOOP_SET_STATUS64, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info64))) IOCTL(LOOP_GET_STATUS64, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info64))) -#endif IOCTL(LOOP_CHANGE_FD, 0, TYPE_INT) IOCTL(MTIOCTOP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_mtop))) -- cgit v1.2.3 From eee37d310c1e53698e317e76db53c63f6bf62af0 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Mon, 17 Jan 2011 21:36:06 +0100 Subject: linux-user: Fix possible realloc memory leak Extract from "man realloc": "If realloc() fails the original block is left untouched; it is not freed or moved." Fix a possible memory leak (reported by cppcheck). Cc: Riku Voipio Signed-off-by: Stefan Weil Signed-off-by: Riku Voipio --- linux-user/elfload.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 33d776de4..08c44d893 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1481,7 +1481,7 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias) struct elf_shdr *shdr; char *strings; struct syminfo *s; - struct elf_sym *syms; + struct elf_sym *syms, *new_syms; shnum = hdr->e_shnum; i = shnum * sizeof(struct elf_shdr); @@ -1550,12 +1550,14 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias) that we threw away. Whether or not this has any effect on the memory allocation depends on the malloc implementation and how many symbols we managed to discard. */ - syms = realloc(syms, nsyms * sizeof(*syms)); - if (syms == NULL) { + new_syms = realloc(syms, nsyms * sizeof(*syms)); + if (new_syms == NULL) { free(s); + free(syms); free(strings); return; } + syms = new_syms; qsort(syms, nsyms, sizeof(*syms), symcmp); -- cgit v1.2.3 From b03088c32f8a88e4674f6cdab47da79ef4188d88 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Mon, 17 Jan 2011 21:36:06 +0100 Subject: linux-user: Fix possible realloc memory leak Extract from "man realloc": "If realloc() fails the original block is left untouched; it is not freed or moved." Fix a possible memory leak (reported by cppcheck). Cc: Riku Voipio Signed-off-by: Stefan Weil Signed-off-by: Riku Voipio (cherry picked from commit 8d79de6e42947a4a11ad7c7bb87e8f745a4f8321) --- linux-user/elfload.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 33d776de4..08c44d893 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1481,7 +1481,7 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias) struct elf_shdr *shdr; char *strings; struct syminfo *s; - struct elf_sym *syms; + struct elf_sym *syms, *new_syms; shnum = hdr->e_shnum; i = shnum * sizeof(struct elf_shdr); @@ -1550,12 +1550,14 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias) that we threw away. Whether or not this has any effect on the memory allocation depends on the malloc implementation and how many symbols we managed to discard. */ - syms = realloc(syms, nsyms * sizeof(*syms)); - if (syms == NULL) { + new_syms = realloc(syms, nsyms * sizeof(*syms)); + if (new_syms == NULL) { free(s); + free(syms); free(strings); return; } + syms = new_syms; qsort(syms, nsyms, sizeof(*syms), symcmp); -- cgit v1.2.3 From ac12a5af0bb48e2cee46232480dc5f6d8d8241b9 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Fri, 4 Feb 2011 09:22:14 +0100 Subject: Change snapshot_blkdev hmp to use correct argument type for device Pointed out by Markus Signed-off-by: Jes Sorensen Signed-off-by: Kevin Wolf (cherry picked from commit 982aa95532a3a7b549695d5b3e18442975eecfb5) --- hmp-commands.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index 38e1eb7eb..372bef429 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -822,7 +822,7 @@ ETEXI { .name = "snapshot_blkdev", - .args_type = "device:s,snapshot_file:s?,format:s?", + .args_type = "device:B,snapshot_file:s?,format:s?", .params = "device [new-image-file] [format]", .help = "initiates a live snapshot\n\t\t\t" "of device. If a new image file is specified, the\n\t\t\t" -- cgit v1.2.3 From 607a375709625a439c5bbdbfb62f8052276d33ad Mon Sep 17 00:00:00 2001 From: Chunqiang Tang Date: Thu, 3 Feb 2011 10:12:49 -0500 Subject: QCOW2: bug fix - read base image beyond its size This patch fixes the following bug in QCOW2. For a QCOW2 image that is larger than its base image, when handling a read request straddling over the end of the base image, the QCOW2 driver attempts to read beyond the end of the base image and the request would fail. This bug was found by Fast Virtual Disk (FVD)'s fully automated testing tool. The following test triggered the bug. dd if=/dev/zero of=/var/ramdisk/truth.raw count=0 bs=1 seek=1098561536 dd if=/dev/zero of=/var/ramdisk/zero-500M.raw count=0 bs=1 seek=593099264 ./qemu-img create -f qcow2 -ocluster_size=65536,backing_fmt=blksim -b /var/ramdisk/zero-500M.raw /var/ramdisk/test.qcow2 1098561536 ./qemu-io --auto --seed=30477694 --truth=/var/ramdisk/truth.raw --format=qcow2 --test=blksim:/var/ramdisk/test.qcow2 --verify_write=true --compare_before=false --compare_after=true --round=100000 --parallel=100 --io_size=10485760 --fail_prob=0 --cancel_prob=0 --instant_qemubh=true Signed-off-by: Chunqiang Tang Signed-off-by: Kevin Wolf (cherry picked from commit e0d9c6f93729c9bfc98fcafcd73098bb8e131aeb) --- block/qcow2.c | 5 ++--- cutils.c | 31 +++++++++++++++++++++++++++++++ qemu-common.h | 2 ++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index a1773e479..28338bf9d 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -355,7 +355,7 @@ int qcow2_backing_read1(BlockDriverState *bs, QEMUIOVector *qiov, else n1 = bs->total_sectors - sector_num; - qemu_iovec_memset(qiov, 0, 512 * (nb_sectors - n1)); + qemu_iovec_memset_skip(qiov, 0, 512 * (nb_sectors - n1), 512 * n1); return n1; } @@ -478,8 +478,7 @@ static void qcow2_aio_read_cb(void *opaque, int ret) if (n1 > 0) { BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO); acb->hd_aiocb = bdrv_aio_readv(bs->backing_hd, acb->sector_num, - &acb->hd_qiov, acb->cur_nr_sectors, - qcow2_aio_read_cb, acb); + &acb->hd_qiov, n1, qcow2_aio_read_cb, acb); if (acb->hd_aiocb == NULL) goto done; } else { diff --git a/cutils.c b/cutils.c index 8d562b28a..f9a7e3689 100644 --- a/cutils.c +++ b/cutils.c @@ -267,6 +267,37 @@ void qemu_iovec_memset(QEMUIOVector *qiov, int c, size_t count) } } +void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count, + size_t skip) +{ + int i; + size_t done; + void *iov_base; + uint64_t iov_len; + + done = 0; + for (i = 0; (i < qiov->niov) && (done != count); i++) { + if (skip >= qiov->iov[i].iov_len) { + /* Skip the whole iov */ + skip -= qiov->iov[i].iov_len; + continue; + } else { + /* Skip only part (or nothing) of the iov */ + iov_base = (uint8_t*) qiov->iov[i].iov_base + skip; + iov_len = qiov->iov[i].iov_len - skip; + skip = 0; + } + + if (done + iov_len > count) { + memset(iov_base, c, count - done); + break; + } else { + memset(iov_base, c, iov_len); + } + done += iov_len; + } +} + #ifndef _WIN32 /* Sets a specific flag */ int fcntl_setfl(int fd, int flag) diff --git a/qemu-common.h b/qemu-common.h index c7ff280b9..cb4b7e0d3 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -322,6 +322,8 @@ void qemu_iovec_reset(QEMUIOVector *qiov); void qemu_iovec_to_buffer(QEMUIOVector *qiov, void *buf); void qemu_iovec_from_buffer(QEMUIOVector *qiov, const void *buf, size_t count); void qemu_iovec_memset(QEMUIOVector *qiov, int c, size_t count); +void qemu_iovec_memset_skip(QEMUIOVector *qiov, int c, size_t count, + size_t skip); struct Monitor; typedef struct Monitor Monitor; -- cgit v1.2.3 From 16e07bc282c3c2d560ae9c4e9db76106975495eb Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Tue, 8 Feb 2011 18:12:35 +0100 Subject: qcow2: Fix error handling for immediate backing file read failure Requests could return success even though they failed when bdrv_aio_readv returned NULL for a backing file read. Reported-by: Chunqiang Tang Signed-off-by: Kevin Wolf (cherry picked from commit 3ab4c7e92d39d40e6dc0bdb1c2320889543691cb) --- block/qcow2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/block/qcow2.c b/block/qcow2.c index 28338bf9d..647c2a4bc 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -479,8 +479,10 @@ static void qcow2_aio_read_cb(void *opaque, int ret) BLKDBG_EVENT(bs->file, BLKDBG_READ_BACKING_AIO); acb->hd_aiocb = bdrv_aio_readv(bs->backing_hd, acb->sector_num, &acb->hd_qiov, n1, qcow2_aio_read_cb, acb); - if (acb->hd_aiocb == NULL) + if (acb->hd_aiocb == NULL) { + ret = -EIO; goto done; + } } else { ret = qcow2_schedule_bh(qcow2_aio_read_bh, acb); if (ret < 0) -- cgit v1.2.3 From 5c9596112cbc959a0bbb458540a620ac05ece1a7 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 9 Feb 2011 10:26:06 +0100 Subject: qcow2: Fix error handling for reading compressed clusters When reading a compressed cluster failed, qcow2 falsely returned success. Signed-off-by: Kevin Wolf Reviewed-by: Markus Armbruster (cherry picked from commit 8af364884355b3f0c5d60a2d2f427927739658ea) --- block/qcow2-cluster.c | 4 ++-- block/qcow2.c | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 5fb8c6695..437aaa817 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -878,11 +878,11 @@ int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset) BLKDBG_EVENT(bs->file, BLKDBG_READ_COMPRESSED); ret = bdrv_read(bs->file, coffset >> 9, s->cluster_data, nb_csectors); if (ret < 0) { - return -1; + return ret; } if (decompress_buffer(s->cluster_cache, s->cluster_size, s->cluster_data + sector_offset, csize) < 0) { - return -1; + return -EIO; } s->cluster_cache_offset = coffset; } diff --git a/block/qcow2.c b/block/qcow2.c index 647c2a4bc..551b3c2f8 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -497,8 +497,10 @@ static void qcow2_aio_read_cb(void *opaque, int ret) } } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) { /* add AIO support for compressed blocks ? */ - if (qcow2_decompress_cluster(bs, acb->cluster_offset) < 0) + ret = qcow2_decompress_cluster(bs, acb->cluster_offset); + if (ret < 0) { goto done; + } qemu_iovec_from_buffer(&acb->hd_qiov, s->cluster_cache + index_in_cluster * 512, -- cgit v1.2.3 From e37dcdfb8dc328471c98dc22444be98455e5f0f7 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 9 Feb 2011 11:09:38 +0100 Subject: qerror: Add QERR_UNKNOWN_BLOCK_FORMAT_FEATURE Signed-off-by: Kevin Wolf Reviewed-by: Anthony Liguori (cherry picked from commit f54e3641122e51c6343d587805422642f307462e) --- qerror.c | 5 +++++ qerror.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/qerror.c b/qerror.c index 9d0cdeb45..485560418 100644 --- a/qerror.c +++ b/qerror.c @@ -200,6 +200,11 @@ static const QErrorStringTable qerror_table[] = { .error_fmt = QERR_UNDEFINED_ERROR, .desc = "An undefined error has ocurred", }, + { + .error_fmt = QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, + .desc = "'%(device)' uses a %(format) feature which is not " + "supported by this qemu version: %(feature)", + }, { .error_fmt = QERR_VNC_SERVER_FAILED, .desc = "Could not start VNC server on %(target)", diff --git a/qerror.h b/qerror.h index b0f69dabe..f732d45e8 100644 --- a/qerror.h +++ b/qerror.h @@ -165,6 +165,9 @@ QError *qobject_to_qerror(const QObject *obj); #define QERR_UNDEFINED_ERROR \ "{ 'class': 'UndefinedError', 'data': {} }" +#define QERR_UNKNOWN_BLOCK_FORMAT_FEATURE \ + "{ 'class': 'UnknownBlockFormatFeature', 'data': { 'device': %s, 'format': %s, 'feature': %s } }" + #define QERR_VNC_SERVER_FAILED \ "{ 'class': 'VNCServerFailed', 'data': { 'target': %s } }" -- cgit v1.2.3 From 12597b06082b5880789a8e738b25a2659a58f64f Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 9 Feb 2011 11:11:07 +0100 Subject: qcow2: Report error for version > 2 The qcow2 driver is now declared responsible for any QCOW image that has version 2 or greater (before this, version 3 would be detected as raw). For everything newer than version 2, an error is reported. Signed-off-by: Kevin Wolf Reviewed-by: Anthony Liguori (cherry picked from commit e8cdcec123facf0ed273d941caeeeb9b08f14955) --- block/qcow2.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index 551b3c2f8..75b8becc0 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -28,6 +28,7 @@ #include "aes.h" #include "block/qcow2.h" #include "qemu-error.h" +#include "qerror.h" /* Differences with QCOW: @@ -59,7 +60,7 @@ static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filename) if (buf_size >= sizeof(QCowHeader) && be32_to_cpu(cow_header->magic) == QCOW_MAGIC && - be32_to_cpu(cow_header->version) == QCOW_VERSION) + be32_to_cpu(cow_header->version) >= QCOW_VERSION) return 100; else return 0; @@ -163,10 +164,18 @@ static int qcow2_open(BlockDriverState *bs, int flags) be64_to_cpus(&header.snapshots_offset); be32_to_cpus(&header.nb_snapshots); - if (header.magic != QCOW_MAGIC || header.version != QCOW_VERSION) { + if (header.magic != QCOW_MAGIC) { ret = -EINVAL; goto fail; } + if (header.version != QCOW_VERSION) { + char version[64]; + snprintf(version, sizeof(version), "QCOW version %d", header.version); + qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, + bs->device_name, "qcow2", version); + ret = -ENOTSUP; + goto fail; + } if (header.cluster_bits < MIN_CLUSTER_BITS || header.cluster_bits > MAX_CLUSTER_BITS) { ret = -EINVAL; -- cgit v1.2.3 From 64a216f58edc1c6d34b728c618342aae2493241a Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 9 Feb 2011 11:13:26 +0100 Subject: qed: Report error for unsupported features Instead of just returning -ENOTSUP, generate a more detailed error. Unfortunately we don't have a helpful text for features that we don't know yet, so just print the feature mask. It might be useful at least if someone asks for help. Signed-off-by: Kevin Wolf Reviewed-by: Anthony Liguori Acked-by: Stefan Hajnoczi (cherry picked from commit 10b758e85c9b38b4b370cff81435f6ed26024a26) --- block/qed.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/block/qed.c b/block/qed.c index 32734486c..75ae2440e 100644 --- a/block/qed.c +++ b/block/qed.c @@ -14,6 +14,7 @@ #include "trace.h" #include "qed.h" +#include "qerror.h" static void qed_aio_cancel(BlockDriverAIOCB *blockacb) { @@ -311,7 +312,13 @@ static int bdrv_qed_open(BlockDriverState *bs, int flags) return -EINVAL; } if (s->header.features & ~QED_FEATURE_MASK) { - return -ENOTSUP; /* image uses unsupported feature bits */ + /* image uses unsupported feature bits */ + char buf[64]; + snprintf(buf, sizeof(buf), "%" PRIx64, + s->header.features & ~QED_FEATURE_MASK); + qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE, + bs->device_name, "QED", buf); + return -ENOTSUP; } if (!qed_is_cluster_size_valid(s->header.cluster_size)) { return -EINVAL; -- cgit v1.2.3 From 038a866f8153c45499b80162f8e1b7188620bd8a Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 9 Feb 2011 11:25:53 +0100 Subject: qemu-img: Improve error messages for failed bdrv_open Output the error message string of the bdrv_open return code. Also set a non-empty device name for the images because the unknown feature error message includes it. Signed-off-by: Kevin Wolf Reviewed-by: Anthony Liguori (cherry picked from commit b9eaf9ecb15a9c69a592f386159163d5efc3b919) --- qemu-img.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/qemu-img.c b/qemu-img.c index 4a3735811..7e3cc4cbd 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -213,8 +213,9 @@ static BlockDriverState *bdrv_new_open(const char *filename, BlockDriverState *bs; BlockDriver *drv; char password[256]; + int ret; - bs = bdrv_new(""); + bs = bdrv_new("image"); if (fmt) { drv = bdrv_find_format(fmt); @@ -225,10 +226,13 @@ static BlockDriverState *bdrv_new_open(const char *filename, } else { drv = NULL; } - if (bdrv_open(bs, filename, flags, drv) < 0) { - error_report("Could not open '%s'", filename); + + ret = bdrv_open(bs, filename, flags, drv); + if (ret < 0) { + error_report("Could not open '%s': %s", filename, strerror(-ret)); goto fail; } + if (bdrv_is_encrypted(bs)) { printf("Disk image '%s' is encrypted.\n", filename); if (read_password(password, sizeof(password)) < 0) { -- cgit v1.2.3 From c7e9df3bc6bf0cad74081c7492b5aab753bf9cc9 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 9 Feb 2011 17:36:19 +0100 Subject: qcow2: Fix order in L2 table COW When copying L2 tables (this happens only with internal snapshots), the order wasn't completely safe, so that after a crash you could end up with a L2 table that has too low refcount, possibly leading to corruption in the long run. This patch puts the operations in the right order: First allocate the new L2 table and replace the reference, and only then decrease the refcount of the old table. Signed-off-by: Kevin Wolf (cherry picked from commit 16fde5f2c2788232b16c06d34d0459a5c1ec1f6c) --- block/qcow2-cluster.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index 437aaa817..750abe37d 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -515,13 +515,16 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset, return ret; } } else { - /* FIXME Order */ - if (l2_offset) - qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t)); + /* First allocate a new L2 table (and do COW if needed) */ ret = l2_allocate(bs, l1_index, &l2_table); if (ret < 0) { return ret; } + + /* Then decrease the refcount of the old table */ + if (l2_offset) { + qcow2_free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t)); + } l2_offset = s->l1_table[l1_index] & ~QCOW_OFLAG_COPIED; } -- cgit v1.2.3 From 7083b66b45571c610cc0a9dedff761da8ebe013f Mon Sep 17 00:00:00 2001 From: Gleb Natapov Date: Mon, 7 Feb 2011 16:14:44 +0200 Subject: correctly check ppr priority during interrupt injection] TPR blocks all interrupts in a priority class, so simple "less or equal" check is not enough. Signed-off-by: Gleb Natapov Reviewed-by: Jan Kiszka Signed-off-by: Anthony Liguori --- hw/apic.c | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/hw/apic.c b/hw/apic.c index 2f8376a30..218d1bb6d 100644 --- a/hw/apic.c +++ b/hw/apic.c @@ -372,19 +372,36 @@ static int apic_get_arb_pri(APICState *s) return 0; } -/* signal the CPU if an irq is pending */ -static void apic_update_irq(APICState *s) + +/* + * <0 - low prio interrupt, + * 0 - no interrupt, + * >0 - interrupt number + */ +static int apic_irq_pending(APICState *s) { int irrv, ppr; - if (!(s->spurious_vec & APIC_SV_ENABLE)) - return; irrv = get_highest_priority_int(s->irr); - if (irrv < 0) - return; + if (irrv < 0) { + return 0; + } ppr = apic_get_ppr(s); - if (ppr && (irrv & 0xf0) <= (ppr & 0xf0)) + if (ppr && (irrv & 0xf0) <= (ppr & 0xf0)) { + return -1; + } + + return irrv; +} + +/* signal the CPU if an irq is pending */ +static void apic_update_irq(APICState *s) +{ + if (!(s->spurious_vec & APIC_SV_ENABLE)) { return; - cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD); + } + if (apic_irq_pending(s) > 0) { + cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD); + } } void apic_reset_irq_delivered(void) @@ -590,12 +607,13 @@ int apic_get_interrupt(DeviceState *d) if (!(s->spurious_vec & APIC_SV_ENABLE)) return -1; - /* XXX: spurious IRQ handling */ - intno = get_highest_priority_int(s->irr); - if (intno < 0) + intno = apic_irq_pending(s); + + if (intno == 0) { return -1; - if (s->tpr && intno <= s->tpr) + } else if (intno < 0) { return s->spurious_vec & 0xff; + } reset_bit(s->irr, intno); set_bit(s->isr, intno); apic_update_irq(s); -- cgit v1.2.3 From bd2483faf127abe9fa5abc3c8e199f5e7d6534d3 Mon Sep 17 00:00:00 2001 From: Bruce Rogers Date: Sat, 5 Feb 2011 14:47:56 -0700 Subject: PATCH] slirp: fix buffer overrun Since the addition of the slirp member to struct mbuf, the value of SLIRP_MSIZE and the initialization of m_size have not been correct, resulting in overrunning the end of the malloc'd buffer in some cases. Signed-off-by: Bruce Rogers Signed-off-by: Anthony Liguori --- slirp/mbuf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slirp/mbuf.c b/slirp/mbuf.c index 87508ba01..eadc80224 100644 --- a/slirp/mbuf.c +++ b/slirp/mbuf.c @@ -23,7 +23,7 @@ * Find a nice value for msize * XXX if_maxlinkhdr already in mtu */ -#define SLIRP_MSIZE (IF_MTU + IF_MAXLINKHDR + sizeof(struct m_hdr ) + 6) +#define SLIRP_MSIZE (IF_MTU + IF_MAXLINKHDR + offsetof(struct mbuf, m_dat) + 6) void m_init(Slirp *slirp) @@ -65,7 +65,7 @@ m_get(Slirp *slirp) m->m_flags = (flags | M_USEDLIST); /* Initialise it */ - m->m_size = SLIRP_MSIZE - sizeof(struct m_hdr); + m->m_size = SLIRP_MSIZE - offsetof(struct m_hdr, m_dat); m->m_data = m->m_dat; m->m_len = 0; m->m_nextpkt = NULL; -- cgit v1.2.3 From e3c8fc83aa75f90c82d0c5da5b2c9c4be28ad9bd Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Mon, 14 Feb 2011 14:24:24 -0600 Subject: Fix build from previous commit I unfortunately got on an unnamed branch and pushed the wrong bits Signed-off-by: Anthony Liguori --- slirp/mbuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slirp/mbuf.c b/slirp/mbuf.c index eadc80224..ce2eb843f 100644 --- a/slirp/mbuf.c +++ b/slirp/mbuf.c @@ -65,7 +65,7 @@ m_get(Slirp *slirp) m->m_flags = (flags | M_USEDLIST); /* Initialise it */ - m->m_size = SLIRP_MSIZE - offsetof(struct m_hdr, m_dat); + m->m_size = SLIRP_MSIZE - offsetof(struct mbuf, m_dat); m->m_data = m->m_dat; m->m_len = 0; m->m_nextpkt = NULL; -- cgit v1.2.3 From 6a7999b2226b4e999692016c47e50147c500f4c9 Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Mon, 14 Feb 2011 16:01:01 -0600 Subject: Update version for 0.14.0-rc2 Signed-off-by: Anthony Liguori --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index bdfb04f11..09708a96a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.13.91 +0.13.92 -- cgit v1.2.3 From 0850f81099cff3a37434352455ffbe831e7f62ae Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Wed, 16 Feb 2011 08:42:46 -0600 Subject: Update version for 0.14.0 Signed-off-by: Anthony Liguori --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 09708a96a..a803cc227 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.13.92 +0.14.0 -- cgit v1.2.3 From 8d610b6ba2b36bbe0159362556455b61c6566526 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Sat, 22 Jan 2011 13:07:26 +0000 Subject: qemu-char: Check for missing backend name Check if the backend option is missing before searching the backend table. This fixes a NULL pointer dereference when QEMU is invoked with the following invalid command-line: $ qemu -chardev id=foo,path=/tmp/socket Previously QEMU would segfault, now it produces this error message: chardev: "foo" missing backend Signed-off-by: Stefan Hajnoczi Signed-off-by: Aurelien Jarno --- qemu-char.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/qemu-char.c b/qemu-char.c index ee4f4cab2..bd4e944e1 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -2506,6 +2506,11 @@ CharDriverState *qemu_chr_open_opts(QemuOpts *opts, return NULL; } + if (qemu_opt_get(opts, "backend") == NULL) { + fprintf(stderr, "chardev: \"%s\" missing backend\n", + qemu_opts_id(opts)); + return NULL; + } for (i = 0; i < ARRAY_SIZE(backend_table); i++) { if (strcmp(backend_table[i].name, qemu_opt_get(opts, "backend")) == 0) break; -- cgit v1.2.3