diff -u qemu-kvm-1.0+noroms/debian/changelog qemu-kvm-1.0+noroms/debian/changelog --- qemu-kvm-1.0+noroms/debian/changelog +++ qemu-kvm-1.0+noroms/debian/changelog @@ -1,3 +1,52 @@ +qemu-kvm (1.0+noroms-0ubuntu14.13) precise-security; urgency=medium + + * SECURITY UPDATE: privilege escalation via REPORT LUNS + - debian/patches/CVE-2013-4344.patch: support more than 256 LUNS in + hw/scsi-bus.c, hw/scsi.h. + - CVE-2013-4344 + + -- Marc Deslauriers Tue, 28 Jan 2014 09:08:09 -0500 + +qemu-kvm (1.0+noroms-0ubuntu14.12) precise-proposed; urgency=low + + * migration-do-not-overwrite-zero-pages.patch, + call-madv-hugepage-for-guest-ram-allocations.patch: + Fix performance degradation after migrations, and savevm/loadvm. + (LP: #1100843) + + -- Chris J Arges Wed, 02 Oct 2013 16:26:27 -0500 + +qemu-kvm (1.0+noroms-0ubuntu14.11) precise-proposed; urgency=low + + * debian/control and qemu-kvm.postinst: remove any g:--- acl on /dev/kvm + (left over from udev-acl). (LP: #1057024) + + -- Serge Hallyn Wed, 17 Jul 2013 10:14:46 -0500 + +qemu-kvm (1.0+noroms-0ubuntu14.10) precise-proposed; urgency=low + + * remove 9004-qcow2-Simplify-count_cow_clusters.patch, which may or may + not have actually fixed bug 1189926. Replace ith with: + 9004-qcow2-start-at-0-when-counting-cow-clusters.patch: Fixes corruption + issues with qcow2. (LP: #1189926) + + -- Chris J Arges Mon, 17 Jun 2013 10:11:38 -0500 + +qemu-kvm (1.0+noroms-0ubuntu14.9) precise-proposed; urgency=low + + * 9004-qcow2-Simplify-count_cow_clusters.patch: fixes corruption + with qcow2. (LP: #1189926) + + -- Chris J Arges Wed, 12 Jun 2013 13:19:46 -0500 + +qemu-kvm (1.0+noroms-0ubuntu14.8) precise-proposed; urgency=low + + * qemu-utils.links: fix kvm-nbd.8.gz and kvm-img.1.gz symlinks. (LP: #1089402) + * take 9pfs-remove-noatime-flag-from-ro-open-calls.patch from upstream git + to make readonly+nonroot 9p mounts succeed. (LP: #1091430) + + -- Serge Hallyn Tue, 29 Jan 2013 22:41:42 -0600 + qemu-kvm (1.0+noroms-0ubuntu14.7) precise-security; urgency=low * SECURITY UPDATE: guest denial of service and possible code execution diff -u qemu-kvm-1.0+noroms/debian/qemu-utils.links qemu-kvm-1.0+noroms/debian/qemu-utils.links --- qemu-kvm-1.0+noroms/debian/qemu-utils.links +++ qemu-kvm-1.0+noroms/debian/qemu-utils.links @@ -3,2 +3,2 @@ -usr/share/man/man1/qemu-img.1 usr/share/man/man1/kvm-img.1 -usr/share/man/man8/qemu-nbd.8 usr/share/man/man8/kvm-nbd.8 +usr/share/man/man1/qemu-img.1.gz usr/share/man/man1/kvm-img.1.gz +usr/share/man/man8/qemu-nbd.8.gz usr/share/man/man8/kvm-nbd.8.gz diff -u qemu-kvm-1.0+noroms/debian/control qemu-kvm-1.0+noroms/debian/control --- qemu-kvm-1.0+noroms/debian/control +++ qemu-kvm-1.0+noroms/debian/control @@ -34,7 +34,7 @@ Package: qemu-kvm Architecture: any -Depends: iproute, +Depends: acl, iproute, python, qemu-common (>= ${source:Version}), qemu-utils (>= ${source:Version}), udev, diff -u qemu-kvm-1.0+noroms/debian/qemu-kvm.postinst qemu-kvm-1.0+noroms/debian/qemu-kvm.postinst --- qemu-kvm-1.0+noroms/debian/qemu-kvm.postinst +++ qemu-kvm-1.0+noroms/debian/qemu-kvm.postinst @@ -13,6 +13,13 @@ #DEBHELPER# +# Remove group::--- acl mistakenly placed on /dev/kvm by udev-acl +if [ -c /dev/kvm -a ! -L /dev/kvm ] +then + /usr/bin/setfacl -m g::rw /dev/kvm +fi + + # We've added new udev rules for /dev/kvm, so if kvm module is already loaded, # make udev recalculate owner/perms. udevadm trigger --subsystem-match=misc --action=change diff -u qemu-kvm-1.0+noroms/debian/patches/series qemu-kvm-1.0+noroms/debian/patches/series --- qemu-kvm-1.0+noroms/debian/patches/series +++ qemu-kvm-1.0+noroms/debian/patches/series @@ -1,3 +1,5 @@ +call-madv-hugepage-for-guest-ram-allocations.patch +migration-do-not-overwrite-zero-pages.patch larger_default_ram_size.patch CVE-2011-2212-virtqueue-indirect-overflow.patch qemuifup-fix-paths.patch @@ -31,0 +34,3 @@ +9pfs-remove-noatime-flag-from-ro-open-calls.patch +9004-qcow2-start-at-0-when-counting-cow-clusters.patch +CVE-2013-4344.patch only in patch2: unchanged: --- qemu-kvm-1.0+noroms.orig/debian/patches/9pfs-remove-noatime-flag-from-ro-open-calls.patch +++ qemu-kvm-1.0+noroms/debian/patches/9pfs-remove-noatime-flag-from-ro-open-calls.patch @@ -0,0 +1,40 @@ +commit eed968607d656a218712df47a5e0432c21fd6994 +Author: Daniel P. Berrange +Date: Mon Jan 16 18:11:40 2012 +0000 + + hw/9pfs: Remove O_NOATIME flag from 9pfs open() calls in readonly mode + + When 2c74c2cb4bedddbfa67628fbd5f9273b4e0e9903 added support for + the 'readonly' flag against 9p filesystems, it also made QEMU + add the O_NOATIME flag as a side-effect. + + The O_NOATIME flag, however, may only be set by the file owner, + or a user with CAP_FOWNER capability. QEMU cannot assume that + this is the case for filesytems exported to QEMU. + + eg, run QEMU as non-root, and attempt to pass the host OS + filesystem through to the guest OS with readonly enable. + The result is that the guest OS cannot open any files at + all. + + If O_NOATIME is really required, it should be optionally + enabled via a separate QEMU command line flag. + + * hw/9pfs/virtio-9p.c: Remove O_NOATIME + + Acked-by: M. Mohan Kumar + Signed-off-by: Daniel P. Berrange + Signed-off-by: Aneesh Kumar K.V + +Index: qemu-kvm-1.0+noroms/hw/9pfs/virtio-9p.c +=================================================================== +--- qemu-kvm-1.0+noroms.orig/hw/9pfs/virtio-9p.c 2013-01-29 22:44:58.395850759 -0600 ++++ qemu-kvm-1.0+noroms/hw/9pfs/virtio-9p.c 2013-01-29 22:44:58.391850759 -0600 +@@ -1597,7 +1597,6 @@ + err = -EROFS; + goto out; + } +- flags |= O_NOATIME; + } + err = v9fs_co_open(pdu, fidp, flags); + if (err < 0) { only in patch2: unchanged: --- qemu-kvm-1.0+noroms.orig/debian/patches/migration-do-not-overwrite-zero-pages.patch +++ qemu-kvm-1.0+noroms/debian/patches/migration-do-not-overwrite-zero-pages.patch @@ -0,0 +1,152 @@ +From 211ea74022f51164a7729030b28eec90b6c99a08 Mon Sep 17 00:00:00 2001 +From: Peter Lieven +Date: Mon, 10 Jun 2013 12:14:20 +0200 +Subject: [PATCH] migration: do not overwrite zero pages + +on incoming migration do not memset pages to zero if they already read as zero. +this will allocate a new zero page and consume memory unnecessarily. even +if we madvise a MADV_DONTNEED later this will only deallocate the memory +asynchronously. + +Signed-off-by: Peter Lieven +Signed-off-by: Juan Quintela +(backported from commit 211ea74022f51164a7729030b28eec90b6c99a08) +Signed-off-by: Chris J Arges + +--- a/arch_init.c ++++ b/arch_init.c +@@ -109,6 +109,67 @@ static int is_dup_page(uint8_t *page, ui + return 1; + } + ++/* ++ * Searches for an area with non-zero content in a buffer ++ * ++ * Attention! The len must be a multiple of ++ * BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR * sizeof(VECTYPE) ++ * and addr must be a multiple of sizeof(VECTYPE) due to ++ * restriction of optimizations in this function. ++ * ++ * can_use_buffer_find_nonzero_offset() can be used to check ++ * these requirements. ++ * ++ * The return value is the offset of the non-zero area rounded ++ * down to a multiple of sizeof(VECTYPE) for the first ++ * BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR chunks and down to ++ * BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR * sizeof(VECTYPE) ++ * afterwards. ++ * ++ * If the buffer is all zero the return value is equal to len. ++ */ ++ ++size_t buffer_find_nonzero_offset(const void *buf, size_t len) ++{ ++ const VECTYPE *p = buf; ++ const VECTYPE zero = (VECTYPE){0}; ++ size_t i; ++ ++ assert(can_use_buffer_find_nonzero_offset(buf, len)); ++ ++ if (!len) { ++ return 0; ++ } ++ ++ for (i = 0; i < BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR; i++) { ++ if (!ALL_EQ(p[i], zero)) { ++ return i * sizeof(VECTYPE); ++ } ++ } ++ ++ for (i = BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR; ++ i < len / sizeof(VECTYPE); ++ i += BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR) { ++ VECTYPE tmp0 = p[i + 0] | p[i + 1]; ++ VECTYPE tmp1 = p[i + 2] | p[i + 3]; ++ VECTYPE tmp2 = p[i + 4] | p[i + 5]; ++ VECTYPE tmp3 = p[i + 6] | p[i + 7]; ++ VECTYPE tmp01 = tmp0 | tmp1; ++ VECTYPE tmp23 = tmp2 | tmp3; ++ if (!ALL_EQ(tmp01 | tmp23, zero)) { ++ break; ++ } ++ } ++ ++ return i * sizeof(VECTYPE); ++} ++ ++static inline bool is_zero_page(uint8_t *p) ++{ ++ return buffer_find_nonzero_offset(p, TARGET_PAGE_SIZE) == ++ TARGET_PAGE_SIZE; ++} ++ + static RAMBlock *last_block; + static ram_addr_t last_offset; + +@@ -440,13 +501,15 @@ int ram_load(QEMUFile *f, void *opaque, + } + + ch = qemu_get_byte(f); +- memset(host, ch, TARGET_PAGE_SIZE); ++ if (ch != 0 || !is_zero_page(host)) { ++ memset(host, ch, TARGET_PAGE_SIZE); + #ifndef _WIN32 +- if (ch == 0 && +- (!kvm_enabled() || kvm_has_sync_mmu())) { +- qemu_madvise(host, TARGET_PAGE_SIZE, QEMU_MADV_DONTNEED); +- } ++ if (ch == 0 && ++ (!kvm_enabled() || kvm_has_sync_mmu())) { ++ qemu_madvise(host, TARGET_PAGE_SIZE, QEMU_MADV_DONTNEED); ++ } + #endif ++ } + } else if (flags & RAM_SAVE_FLAG_PAGE) { + void *host; + +--- a/qemu-common.h ++++ b/qemu-common.h +@@ -341,6 +341,43 @@ static inline uint64_t muldiv64(uint64_t + return res.ll; + } + ++/* vector definitions */ ++#ifdef __ALTIVEC__ ++#include ++/* The altivec.h header says we're allowed to undef these for ++ * C++ compatibility. Here we don't care about C++, but we ++ * undef them anyway to avoid namespace pollution. ++ */ ++#undef vector ++#undef pixel ++#undef bool ++#define VECTYPE __vector unsigned char ++#define SPLAT(p) vec_splat(vec_ld(0, p), 0) ++#define ALL_EQ(v1, v2) vec_all_eq(v1, v2) ++/* altivec.h may redefine the bool macro as vector type. ++ * Reset it to POSIX semantics. */ ++#define bool _Bool ++#elif defined __SSE2__ ++#include ++#define VECTYPE __m128i ++#define SPLAT(p) _mm_set1_epi8(*(p)) ++#define ALL_EQ(v1, v2) (_mm_movemask_epi8(_mm_cmpeq_epi8(v1, v2)) == 0xFFFF) ++#else ++#define VECTYPE unsigned long ++#define SPLAT(p) (*(p) * (~0UL / 255)) ++#define ALL_EQ(v1, v2) ((v1) == (v2)) ++#endif ++ ++#define BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR 8 ++static inline bool ++can_use_buffer_find_nonzero_offset(const void *buf, size_t len) ++{ ++ return (len % (BUFFER_FIND_NONZERO_OFFSET_UNROLL_FACTOR ++ * sizeof(VECTYPE)) == 0 ++ && ((uintptr_t) buf) % sizeof(VECTYPE) == 0); ++} ++size_t buffer_find_nonzero_offset(const void *buf, size_t len); ++ + #include "module.h" + + #endif only in patch2: unchanged: --- qemu-kvm-1.0+noroms.orig/debian/patches/call-madv-hugepage-for-guest-ram-allocations.patch +++ qemu-kvm-1.0+noroms/debian/patches/call-madv-hugepage-for-guest-ram-allocations.patch @@ -0,0 +1,39 @@ +From ad0b5321f1f797274603ebbe20108b0750baee94 +From: Luiz Capitulino +Date: Fri Oct 5 16:47:57 2012 -0300 +Subject: [PATCH] Call MADV_HUGEPAGE for guest RAM allocations + +This makes it possible for QEMU to use transparent huge pages (THP) +when transparent_hugepage/enabled=madvise. Otherwise THP is only +used when it's enabled system wide. + +Signed-off-by: Luiz Capitulino +Signed-off-by: Anthony Liguori +(backported from commit ad0b5321f1f797274603ebbe20108b0750baee94) +Signed-off-by: Chris J Arges + +--- a/exec.c ++++ b/exec.c +@@ -2990,6 +2990,8 @@ ram_addr_t qemu_ram_alloc_from_ptr(Devic + memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS), + 0xff, size >> TARGET_PAGE_BITS); + ++ qemu_madvise(new_block->host, size, QEMU_MADV_HUGEPAGE); ++ + if (kvm_enabled()) + kvm_setup_guest_memory(new_block->host, size); + +--- a/osdep.h ++++ b/osdep.h +@@ -102,6 +102,11 @@ void qemu_vfree(void *ptr); + #else + #define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID + #endif ++#ifdef MADV_HUGEPAGE ++#define QEMU_MADV_HUGEPAGE MADV_HUGEPAGE ++#else ++#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID ++#endif + + #elif defined(CONFIG_POSIX_MADVISE) + only in patch2: unchanged: --- qemu-kvm-1.0+noroms.orig/debian/patches/CVE-2013-4344.patch +++ qemu-kvm-1.0+noroms/debian/patches/CVE-2013-4344.patch @@ -0,0 +1,137 @@ +Description: fix privilege escalation via REPORT LUNS +Origin: backport, http://git.qemu.org/?p=qemu.git;a=commit;h=846424350b292f16b732b573273a5c1f195cd7a3 +Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=725944 + +Index: qemu-kvm-1.0+noroms/hw/scsi-bus.c +=================================================================== +--- qemu-kvm-1.0+noroms.orig/hw/scsi-bus.c 2014-01-28 09:04:14.789275422 -0500 ++++ qemu-kvm-1.0+noroms/hw/scsi-bus.c 2014-01-28 09:05:48.741277938 -0500 +@@ -9,6 +9,8 @@ + static char *scsibus_get_fw_dev_path(DeviceState *dev); + static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf); + static void scsi_req_dequeue(SCSIRequest *req); ++static uint8_t *scsi_target_alloc_buf(SCSIRequest *req, size_t len); ++static void scsi_target_free_buf(SCSIRequest *req); + + static struct BusInfo scsi_bus_info = { + .name = "SCSI", +@@ -247,7 +249,8 @@ + struct SCSITargetReq { + SCSIRequest req; + int len; +- uint8_t buf[2056]; ++ uint8_t *buf; ++ int buf_len; + }; + + static void store_lun(uint8_t *outbuf, int lun) +@@ -290,14 +293,12 @@ + if (!found_lun0) { + n += 8; + } +- len = MIN(n + 8, r->req.cmd.xfer & ~7); +- if (len > sizeof(r->buf)) { +- /* TODO: > 256 LUNs? */ +- return false; +- } + ++ scsi_target_alloc_buf(&r->req, n + 8); ++ ++ len = MIN(n + 8, r->req.cmd.xfer & ~7); + memset(r->buf, 0, len); +- stl_be_p(&r->buf, n); ++ stl_be_p(&r->buf[0], n); + i = found_lun0 ? 8 : 16; + QTAILQ_FOREACH(qdev, &r->req.bus->qbus.children, sibling) { + SCSIDevice *dev = DO_UPCAST(SCSIDevice, qdev, qdev); +@@ -315,6 +316,9 @@ + static bool scsi_target_emulate_inquiry(SCSITargetReq *r) + { + assert(r->req.dev->lun != r->req.lun); ++ ++ scsi_target_alloc_buf(&r->req, SCSI_INQUIRY_LEN); ++ + if (r->req.cmd.buf[1] & 0x2) { + /* Command support data - optional, not implemented */ + return false; +@@ -343,7 +347,7 @@ + return false; + } + /* done with EVPD */ +- assert(r->len < sizeof(r->buf)); ++ assert(r->len < r->buf_len); + r->len = MIN(r->req.cmd.xfer, r->len); + return true; + } +@@ -358,7 +362,7 @@ + return -1; + } + +- r->len = MIN(r->req.cmd.xfer, 36); ++ r->len = MIN(r->req.cmd.xfer, SCSI_INQUIRY_LEN); + memset(r->buf, 0, r->len); + if (r->req.lun != 0) { + r->buf[0] = TYPE_NO_LUN; +@@ -394,8 +398,9 @@ + if (req->cmd.xfer < 4) { + goto illegal_request; + } ++ scsi_target_alloc_buf(&r->req, SCSI_SENSE_LEN); + r->len = scsi_device_get_sense(r->req.dev, r->buf, +- MIN(req->cmd.xfer, sizeof r->buf), ++ MIN(req->cmd.xfer, r->buf_len), + (req->cmd.buf[1] & 1) == 0); + if (r->req.dev->sense_is_ua) { + if (r->req.dev->info->unit_attention_reported) { +@@ -442,11 +447,29 @@ + return r->buf; + } + ++static uint8_t *scsi_target_alloc_buf(SCSIRequest *req, size_t len) ++{ ++ SCSITargetReq *r = DO_UPCAST(SCSITargetReq, req, req); ++ ++ r->buf = g_malloc(len); ++ r->buf_len = len; ++ ++ return r->buf; ++} ++ ++static void scsi_target_free_buf(SCSIRequest *req) ++{ ++ SCSITargetReq *r = DO_UPCAST(SCSITargetReq, req, req); ++ ++ g_free(r->buf); ++} ++ + static const struct SCSIReqOps reqops_target_command = { + .size = sizeof(SCSITargetReq), + .send_command = scsi_target_send_command, + .read_data = scsi_target_read_data, + .get_buf = scsi_target_get_buf, ++ .free_req = scsi_target_free_buf, + }; + + +@@ -1092,7 +1115,7 @@ + buf[7] = 10; + buf[12] = sense.asc; + buf[13] = sense.ascq; +- return MIN(len, 18); ++ return MIN(len, SCSI_SENSE_LEN); + } else { + /* Return descriptor format sense buffer */ + buf[0] = 0x72; +Index: qemu-kvm-1.0+noroms/hw/scsi.h +=================================================================== +--- qemu-kvm-1.0+noroms.orig/hw/scsi.h 2014-01-28 09:04:14.789275422 -0500 ++++ qemu-kvm-1.0+noroms/hw/scsi.h 2014-01-28 09:04:14.785275422 -0500 +@@ -8,6 +8,8 @@ + #define MAX_SCSI_DEVS 255 + + #define SCSI_CMD_BUF_SIZE 16 ++#define SCSI_SENSE_LEN 18 ++#define SCSI_INQUIRY_LEN 36 + + typedef struct SCSIBus SCSIBus; + typedef struct SCSIBusInfo SCSIBusInfo; only in patch2: unchanged: --- qemu-kvm-1.0+noroms.orig/debian/patches/9004-qcow2-start-at-0-when-counting-cow-clusters.patch +++ qemu-kvm-1.0+noroms/debian/patches/9004-qcow2-start-at-0-when-counting-cow-clusters.patch @@ -0,0 +1,33 @@ +From b076a5de8014334fc7e592dae2a1d2d16479ef90 Mon Sep 17 00:00:00 2001 +From: Chris J Arges +Date: Fri, 14 Jun 2013 16:17:46 -0500 +Subject: [PATCH] qcow2: start at 0 when counting cow clusters + +BugLink: http://bugs.launchpad.net/bugs/1189926 + +This patch fixes corruption issues. +While searching for available clusters, if we detect an ongoing AIO +write request, then we restart after the other has completed. By not +re-setting i to 0, we fail to re-check clusters which may no longer be +available. + +Signed-off-by: Chris J Arges +--- + block/qcow2-cluster.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c +index f4e049f..ed3c14e 100644 +--- a/block/qcow2-cluster.c ++++ b/block/qcow2-cluster.c +@@ -748,7 +748,7 @@ again: + nb_clusters = 1; + + /* how many available clusters ? */ +- ++ i = 0; + while (i < nb_clusters) { + i += count_contiguous_clusters(nb_clusters - i, s->cluster_size, + &l2_table[l2_index], i, 0); +-- +1.7.9.5