Hi

Attached you'll find the full NMU patch to fix the outstanding qemu issues.

Cheers
Steffen
diff -u kvm-66+dfsg/debian/changelog kvm-66+dfsg/debian/changelog
--- kvm-66+dfsg/debian/changelog
+++ kvm-66+dfsg/debian/changelog
@@ -1,3 +1,27 @@
+kvm (66+dfsg-1.1) unstable; urgency=high
+
+  * Non-maintainer upload by the security team
+  * Merge the fixes for the security issues in the embedded qemu
+    version (Closes: #480011) Thanks to Jamie Strandboge
+   - Add CVE-2007-1320+1321+1322+1366+2893.patch from from qemu 0.9.1-1
+     to address the following issues:
+    - Cirrus LGD-54XX "bitblt" heap overflow.
+    - NE2000 "mtu" heap overflow.
+    - QEMU "net socket" heap overflow.
+    - QEMU NE2000 "receive" integer signedness error.
+    - Infinite loop in the emulated SB16 device.
+    - Unprivileged "aam" instruction does not correctly handle the
+      undocumented divisor operand.
+    - Unprivileged "icebp" instruction will halt emulation.
+  * Include patch which defaults to existing behaviour (probing based on file
+    contents), so it still requires the mgmt app (e.g. libvirt xml) to
+    pass a new "format=raw" parameter for raw disk images
+    - Fixes possible privilege escalation, which could allow guest users
+      to read arbitrary files on the host by modifying the header to identify
+      a different format (Closes: #481204) Fixes: CVE-2008-2004
+
+ -- Steffen Joeris <[EMAIL PROTECTED]>  Tue, 20 May 2008 13:28:14 +0000
+
 kvm (66+dfsg-1) unstable; urgency=low
 
   * New upstream release
diff -u kvm-66+dfsg/debian/patches/series kvm-66+dfsg/debian/patches/series
--- kvm-66+dfsg/debian/patches/series
+++ kvm-66+dfsg/debian/patches/series
@@ -10,0 +11,2 @@
+CVE-2007-1320+1321+1322+1366+2893.patch
+CVE-2008-2004.patch
only in patch2:
unchanged:
--- kvm-66+dfsg.orig/debian/patches/CVE-2008-2004.patch
+++ kvm-66+dfsg/debian/patches/CVE-2008-2004.patch
@@ -0,0 +1,58 @@
+diff --git a/qemu-doc.texi b/qemu-doc.texi
+index 45c89ce..1f409f4 100644
+--- a/qemu-doc.texi
++++ kvm-66+dfsg/qemu/qemu-doc.texi
+@@ -261,6 +261,10 @@ These options have the same definition as they have in @option{-hdachs}.
+ @var{snapshot} is "on" or "off" and allows to enable snapshot for given drive (see @option{-snapshot}).
+ @item [EMAIL PROTECTED]
+ @var{cache} is "on" or "off" and allows to disable host cache to access data.
[EMAIL PROTECTED] [EMAIL PROTECTED]
++Specify which disk @var{format} will be used rather than detecting
++the format.  Can be used to specifiy format=raw to avoid interpreting
++an untrusted format header.
+ @end table
+ 
+ Instead of @option{-cdrom} you can use:
+--- ../old/kvm-66+dfsg/qemu/vl.c	2008-04-15 13:35:58.000000000 +0000
++++ kvm-66+dfsg/qemu/vl.c	2008-05-20 14:11:58.000000000 +0000
+@@ -5079,6 +5079,7 @@
+     int bus_id, unit_id;
+     int cyls, heads, secs, translation;
+     BlockDriverState *bdrv;
++    BlockDriver *drv = NULL;
+     int max_devs;
+     int index;
+     int cache;
+@@ -5087,7 +5088,7 @@
+     char *str = arg->opt;
+     char *params[] = { "bus", "unit", "if", "index", "cyls", "heads",
+                        "secs", "trans", "media", "snapshot", "file",
+-                       "cache", "boot", NULL };
++                       "cache", "boot", "format", NULL };
+ 
+     if (check_params(buf, sizeof(buf), params, str) < 0) {
+          fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n",
+@@ -5271,6 +5272,14 @@
+ 	}
+     }
+ 
++    if (get_param_value(buf, sizeof(buf), "format", str)) {
++        drv = bdrv_find_format(buf);
++        if (!drv) {
++            fprintf(stderr, "qemu: '%s' invalid format\n", buf);
++            return -1;
++        }
++    }
++
+     if (arg->file == NULL)
+         get_param_value(file, sizeof(file), "file", str);
+     else
+@@ -5376,7 +5385,7 @@
+         bdrv_flags |= BDRV_O_SNAPSHOT;
+     if (!cache)
+         bdrv_flags |= BDRV_O_DIRECT;
+-    if (bdrv_open(bdrv, file, bdrv_flags) < 0 || qemu_key_check(bdrv, file)) {
++    if (bdrv_open2(bdrv, file, bdrv_flags, drv) < 0 || qemu_key_check(bdrv, file)) {
+         fprintf(stderr, "qemu: could not open disk image %s\n",
+                         file);
+         return -1;
only in patch2:
unchanged:
--- kvm-66+dfsg.orig/debian/patches/CVE-2007-1320+1321+1322+1366+2893.patch
+++ kvm-66+dfsg/debian/patches/CVE-2007-1320+1321+1322+1366+2893.patch
@@ -0,0 +1,324 @@
+diff -Nur kvm-66+dfsg/qemu/block.c kvm-66+dfsg.new/qemu/block.c
+--- kvm-66+dfsg/qemu/block.c	2008-05-07 09:59:51.000000000 -0400
++++ kvm-66+dfsg.new/qemu/block.c	2008-05-07 10:03:24.000000000 -0400
+@@ -612,6 +612,8 @@
+         return -ENOMEDIUM;
+     if (bs->read_only)
+         return -EACCES;
++    if (sector_num < 0)
++        return -EINVAL;
+     if (bdrv_wr_badreq_sectors(bs, sector_num, nb_sectors))
+         return -EDOM;
+     if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
+@@ -619,8 +621,14 @@
+     }
+     if (drv->bdrv_pwrite) {
+         int ret, len;
++        int64_t ns;
++
+         len = nb_sectors * 512;
+-        ret = drv->bdrv_pwrite(bs, sector_num * 512, buf, len);
++        ns = sector_num * 512;
++        if (ns < 0)
++            return -EINVAL;
++
++        ret = drv->bdrv_pwrite(bs, ns, buf, len);
+         if (ret < 0)
+             return ret;
+         else if (ret != len)
+diff -Nur kvm-66+dfsg/qemu/hw/cirrus_vga.c kvm-66+dfsg.new/qemu/hw/cirrus_vga.c
+--- kvm-66+dfsg/qemu/hw/cirrus_vga.c	2008-04-15 09:35:58.000000000 -0400
++++ kvm-66+dfsg.new/qemu/hw/cirrus_vga.c	2008-05-07 10:00:01.000000000 -0400
+@@ -224,6 +224,20 @@
+ #define CIRRUS_HOOK_NOT_HANDLED 0
+ #define CIRRUS_HOOK_HANDLED 1
+ 
++#define BLTUNSAFE(s) \
++    ( \
++        ( /* check dst is within bounds */ \
++            (s)->cirrus_blt_height * (s)->cirrus_blt_dstpitch \
++                + ((s)->cirrus_blt_dstaddr & (s)->cirrus_addr_mask) > \
++                    (s)->vram_size \
++        ) || \
++        ( /* check src is within bounds */ \
++            (s)->cirrus_blt_height * (s)->cirrus_blt_srcpitch \
++                + ((s)->cirrus_blt_srcaddr & (s)->cirrus_addr_mask) > \
++                    (s)->vram_size \
++        ) \
++    )
++
+ struct CirrusVGAState;
+ typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s,
+                                      uint8_t * dst, const uint8_t * src,
+@@ -645,7 +659,7 @@
+ 
+     for (y = 0; y < lines; y++) {
+ 	off_cur = off_begin;
+-	off_cur_end = off_cur + bytesperline;
++	off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask;
+ 	off_cur &= TARGET_PAGE_MASK;
+ 	while (off_cur < off_cur_end) {
+ 	    cpu_physical_memory_set_dirty(s->vram_offset + off_cur);
+@@ -660,7 +674,11 @@
+ {
+     uint8_t *dst;
+ 
+-    dst = s->vram_ptr + s->cirrus_blt_dstaddr;
++    dst = s->vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask);
++
++    if (BLTUNSAFE(s))
++        return 0;
++
+     (*s->cirrus_rop) (s, dst, src,
+                       s->cirrus_blt_dstpitch, 0,
+                       s->cirrus_blt_width, s->cirrus_blt_height);
+@@ -676,8 +694,10 @@
+ {
+     cirrus_fill_t rop_func;
+ 
++    if (BLTUNSAFE(s))
++        return 0;
+     rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
+-    rop_func(s, s->vram_ptr + s->cirrus_blt_dstaddr,
++    rop_func(s, s->vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask), 
+              s->cirrus_blt_dstpitch,
+              s->cirrus_blt_width, s->cirrus_blt_height);
+     cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
+@@ -696,8 +716,8 @@
+ static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
+ {
+     return cirrus_bitblt_common_patterncopy(s,
+-					    s->vram_ptr +
+-                                            (s->cirrus_blt_srcaddr & ~7));
++					    s->vram_ptr + ((s->cirrus_blt_srcaddr & ~7) &
++                                            s->cirrus_addr_mask));
+ }
+ 
+ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
+@@ -747,8 +767,10 @@
+     if (notify)
+ 	vga_hw_update();
+ 
+-    (*s->cirrus_rop) (s, s->vram_ptr + s->cirrus_blt_dstaddr,
+-		      s->vram_ptr + s->cirrus_blt_srcaddr,
++    (*s->cirrus_rop) (s, s->vram_ptr +
++		          (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
++		          s->vram_ptr +
++		          (s->cirrus_blt_srcaddr & s->cirrus_addr_mask),
+ 		      s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
+ 		      s->cirrus_blt_width, s->cirrus_blt_height);
+ 
+@@ -774,8 +796,14 @@
+ 		       s->cirrus_blt_srcaddr - s->start_addr,
+ 		       s->cirrus_blt_width, s->cirrus_blt_height);
+     } else {
+-	(*s->cirrus_rop) (s, s->vram_ptr + s->cirrus_blt_dstaddr,
+-			  s->vram_ptr + s->cirrus_blt_srcaddr,
++
++    if (BLTUNSAFE(s))
++        return 0;
++
++	(*s->cirrus_rop) (s, s->vram_ptr +
++                (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
++			  s->vram_ptr +
++                (s->cirrus_blt_srcaddr & s->cirrus_addr_mask),
+ 			  s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
+ 			  s->cirrus_blt_width, s->cirrus_blt_height);
+ 
+@@ -807,8 +835,9 @@
+         } else {
+             /* at least one scan line */
+             do {
+-                (*s->cirrus_rop)(s, s->vram_ptr + s->cirrus_blt_dstaddr,
+-                                 s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1);
++                (*s->cirrus_rop)(s, s->vram_ptr +
++                    (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
++                        s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1);
+                 cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
+                                          s->cirrus_blt_width, 1);
+                 s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch;
+@@ -1929,7 +1958,7 @@
+     unsigned val = mem_value;
+     uint8_t *dst;
+ 
+-    dst = s->vram_ptr + offset;
++    dst = s->vram_ptr + (offset &= s->cirrus_addr_mask);
+     for (x = 0; x < 8; x++) {
+ 	if (val & 0x80) {
+ 	    *dst = s->cirrus_shadow_gr1;
+@@ -1952,7 +1981,7 @@
+     unsigned val = mem_value;
+     uint8_t *dst;
+ 
+-    dst = s->vram_ptr + offset;
++    dst = s->vram_ptr + (offset &= s->cirrus_addr_mask);
+     for (x = 0; x < 8; x++) {
+ 	if (val & 0x80) {
+ 	    *dst = s->cirrus_shadow_gr1;
+diff -Nur kvm-66+dfsg/qemu/hw/cirrus_vga_rop.h kvm-66+dfsg.new/qemu/hw/cirrus_vga_rop.h
+--- kvm-66+dfsg/qemu/hw/cirrus_vga_rop.h	2008-04-15 09:35:58.000000000 -0400
++++ kvm-66+dfsg.new/qemu/hw/cirrus_vga_rop.h	2008-05-07 10:00:01.000000000 -0400
+@@ -31,6 +31,12 @@
+     int x,y;
+     dstpitch -= bltwidth;
+     srcpitch -= bltwidth;
++
++    if (dstpitch < 0 || srcpitch < 0) {
++        /* is 0 valid? srcpitch == 0 could be useful */
++        return;
++    }
++
+     for (y = 0; y < bltheight; y++) {
+         for (x = 0; x < bltwidth; x++) {
+             ROP_OP(*dst, *src);
+diff -Nur kvm-66+dfsg/qemu/hw/dma.c kvm-66+dfsg.new/qemu/hw/dma.c
+--- kvm-66+dfsg/qemu/hw/dma.c	2008-04-15 09:35:58.000000000 -0400
++++ kvm-66+dfsg.new/qemu/hw/dma.c	2008-05-07 10:00:01.000000000 -0400
+@@ -341,9 +341,11 @@
+ #endif
+ 
+     r = dma_controllers[ncont].regs + ichan;
+-    n = r->transfer_handler (r->opaque, ichan + (ncont << 2),
+-                             r->now[COUNT], (r->base[COUNT] + 1) << ncont);
+-    r->now[COUNT] = n;
++    if (r->transfer_handler) {
++        n = r->transfer_handler (r->opaque, ichan + (ncont << 2),
++                                 r->now[COUNT], (r->base[COUNT] + 1) << ncont);
++        r->now[COUNT] = n;
++    }
+     ldebug ("dma_pos %d size %d\n", n, (r->base[COUNT] + 1) << ncont);
+ }
+ 
+diff -Nur kvm-66+dfsg/qemu/hw/fdc.c kvm-66+dfsg.new/qemu/hw/fdc.c
+--- kvm-66+dfsg/qemu/hw/fdc.c	2008-04-15 09:35:58.000000000 -0400
++++ kvm-66+dfsg.new/qemu/hw/fdc.c	2008-05-07 10:00:01.000000000 -0400
+@@ -1344,7 +1344,13 @@
+             len = fdctrl->data_len - fdctrl->data_pos;
+             if (len > FD_SECTOR_LEN)
+                 len = FD_SECTOR_LEN;
+-            bdrv_read(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1);
++            if (cur_drv->bs) {
++                bdrv_read(cur_drv->bs, fd_sector(cur_drv), 
++                          fdctrl->fifo, 1);
++            } else {
++                FLOPPY_ERROR("can't read data from drive\n");
++                return 0;
++            }
+         }
+     }
+     retval = fdctrl->fifo[pos];
+diff -Nur kvm-66+dfsg/qemu/hw/pc.c kvm-66+dfsg.new/qemu/hw/pc.c
+--- kvm-66+dfsg/qemu/hw/pc.c	2008-04-15 09:35:58.000000000 -0400
++++ kvm-66+dfsg.new/qemu/hw/pc.c	2008-05-07 10:00:01.000000000 -0400
+@@ -341,7 +341,8 @@
+     case 0x400:
+     case 0x401:
+         fprintf(stderr, "BIOS panic at rombios.c, line %d\n", val);
+-        exit(1);
++        /* according to documentation, these can be safely ignored */
++        break;
+     case 0x402:
+     case 0x403:
+ #ifdef DEBUG_BIOS
+@@ -364,8 +365,9 @@
+         /* LGPL'ed VGA BIOS messages */
+     case 0x501:
+     case 0x502:
++        /* according to documentation, these can be safely ignored */
+         fprintf(stderr, "VGA BIOS panic, line %d\n", val);
+-        exit(1);
++        break;
+     case 0x500:
+     case 0x503:
+ #ifdef DEBUG_BIOS
+diff -Nur kvm-66+dfsg/qemu/hw/sb16.c kvm-66+dfsg.new/qemu/hw/sb16.c
+--- kvm-66+dfsg/qemu/hw/sb16.c	2008-04-15 09:35:58.000000000 -0400
++++ kvm-66+dfsg.new/qemu/hw/sb16.c	2008-05-07 10:00:01.000000000 -0400
+@@ -1246,8 +1246,10 @@
+             s->block_size);
+ #endif
+ 
+-    while (s->left_till_irq <= 0) {
+-        s->left_till_irq = s->block_size + s->left_till_irq;
++    if (s->block_size) {
++        while (s->left_till_irq <= 0) {
++            s->left_till_irq = s->block_size + s->left_till_irq;
++        }
+     }
+ 
+     return dma_pos;
+diff -Nur kvm-66+dfsg/qemu/slirp/slirp.c kvm-66+dfsg.new/qemu/slirp/slirp.c
+--- kvm-66+dfsg/qemu/slirp/slirp.c	2008-04-15 09:35:58.000000000 -0400
++++ kvm-66+dfsg.new/qemu/slirp/slirp.c	2008-05-07 10:00:01.000000000 -0400
+@@ -620,6 +620,10 @@
+         if (!m)
+             return;
+         /* Note: we add to align the IP header */
++        /* taviso: large values in ne2k TCNT register may exceed msize on transmit */
++        if (M_FREEROOM(m) < pkt_len + 2) {
++            m_inc(m, pkt_len + 2);
++        }
+         m->m_len = pkt_len + 2;
+         memcpy(m->m_data + 2, pkt, pkt_len);
+ 
+diff -Nur kvm-66+dfsg/qemu/target-i386/translate.c kvm-66+dfsg.new/qemu/target-i386/translate.c
+--- kvm-66+dfsg/qemu/target-i386/translate.c	2008-04-15 09:35:58.000000000 -0400
++++ kvm-66+dfsg.new/qemu/target-i386/translate.c	2008-05-07 10:00:01.000000000 -0400
+@@ -5452,6 +5452,7 @@
+         gen_jmp_im(pc_start - s->cs_base);
+         gen_op_into(s->pc - pc_start);
+         break;
++#ifdef WANT_ICEBP
+     case 0xf1: /* icebp (undocumented, exits to external debugger) */
+         if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_ICEBP))
+             break;
+@@ -5463,6 +5464,7 @@
+         cpu_set_log(CPU_LOG_INT | CPU_LOG_TB_IN_ASM);
+ #endif
+         break;
++#endif /* icebp */
+     case 0xfa: /* cli */
+         if (!s->vm86) {
+             if (s->cpl <= s->iopl) {
+diff -Nur kvm-66+dfsg/qemu/vl.c kvm-66+dfsg.new/qemu/vl.c
+--- kvm-66+dfsg/qemu/vl.c	2008-05-07 09:59:51.000000000 -0400
++++ kvm-66+dfsg.new/qemu/vl.c	2008-05-07 10:00:01.000000000 -0400
+@@ -4294,8 +4294,8 @@
+     VLANClientState *vc;
+     int fd;
+     int state; /* 0 = getting length, 1 = getting data */
+-    int index;
+-    int packet_len;
++    unsigned int index;
++    unsigned int packet_len;
+     uint8_t buf[4096];
+     struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */
+ } NetSocketState;
+@@ -4326,7 +4326,8 @@
+ static void net_socket_send(void *opaque)
+ {
+     NetSocketState *s = opaque;
+-    int l, size, err;
++    int size, err;
++    unsigned l;
+     uint8_t buf1[4096];
+     const uint8_t *buf;
+ 
+@@ -4365,7 +4366,15 @@
+             l = s->packet_len - s->index;
+             if (l > size)
+                 l = size;
+-            memcpy(s->buf + s->index, buf, l);
++            if (s->index + l <= sizeof(s->buf)) {
++                memcpy(s->buf + s->index, buf, l);
++            } else {
++                fprintf(stderr, "serious error: oversized packet received,"
++                    "connection terminated.\n");
++                s->state = 0;
++                goto eoc;
++            }
++
+             s->index += l;
+             buf += l;
+             size -= l;
+

Attachment: signature.asc
Description: This is a digitally signed message part.

Reply via email to