[Pkg-xen-changes] r599 - in branches/etch/xen-3.0/debian: . patches
Bastian Blank
waldi at alioth.debian.org
Sat Jul 12 11:03:33 UTC 2008
Author: waldi
Date: Sat Jul 12 11:03:33 2008
New Revision: 599
Log:
Fix CVE-2007-5906 and CVE-2008-0928.
* debian/changelog: Update.
* debian/patches/00list: Add new patches.
* debian/patches/CVE-2007-5906.dpatch, debian/patches/CVE-2008-0928.dpatch: Add.
Added:
branches/etch/xen-3.0/debian/patches/CVE-2007-5906.dpatch (contents, props changed)
branches/etch/xen-3.0/debian/patches/CVE-2008-0928.dpatch
Modified:
branches/etch/xen-3.0/debian/changelog
branches/etch/xen-3.0/debian/patches/00list
Modified: branches/etch/xen-3.0/debian/changelog
==============================================================================
--- branches/etch/xen-3.0/debian/changelog (original)
+++ branches/etch/xen-3.0/debian/changelog Sat Jul 12 11:03:33 2008
@@ -1,3 +1,12 @@
+xen-3.0 (3.0.3-0-5) UNRELEASED; urgency=low
+
+ * Clear debug registers for HVM guests.
+ See: CVE-2007-5906
+ * Fix range checks in ioemu block support.
+ See: CVE-2008-0928
+
+ -- Bastian Blank <waldi at debian.org> Sat, 12 Jul 2008 12:52:46 +0200
+
xen-3.0 (3.0.3-0-4) stable-security; urgency=low
* Non-maintainer upload by The Security Team.
Modified: branches/etch/xen-3.0/debian/patches/00list
==============================================================================
--- branches/etch/xen-3.0/debian/patches/00list (original)
+++ branches/etch/xen-3.0/debian/patches/00list Sat Jul 12 11:03:33 2008
@@ -10,3 +10,5 @@
not-reinvent-udev
CVE-2007-4993
CVE-2007-1320
+CVE-2007-5906
+CVE-2008-0928
Added: branches/etch/xen-3.0/debian/patches/CVE-2007-5906.dpatch
==============================================================================
--- (empty file)
+++ branches/etch/xen-3.0/debian/patches/CVE-2007-5906.dpatch Sat Jul 12 11:03:33 2008
@@ -0,0 +1,379 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+
+ at DPATCH@
+diff -r d4449461dc16 -r 5f6dc1bafffd xen/arch/x86/domain.c
+--- a/xen/arch/x86/domain.c Tue Oct 17 22:09:27 2006 +0100
++++ b/xen/arch/x86/domain.c Thu Nov 01 16:26:38 2007 +0000
+@@ -305,13 +305,13 @@ int arch_set_info_guest(
+ hvm_load_cpu_guest_regs(v, &v->arch.guest_context.user_regs);
+ }
+
+- if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) )
+- return 0;
+-
+ memset(v->arch.guest_context.debugreg, 0,
+ sizeof(v->arch.guest_context.debugreg));
+ for ( i = 0; i < 8; i++ )
+ (void)set_debugreg(v, i, c->debugreg[i]);
++
++ if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) )
++ return 0;
+
+ if ( v->vcpu_id == 0 )
+ d->vm_assist = c->vm_assist;
+@@ -633,16 +633,32 @@ static void paravirt_ctxt_switch_from(st
+ static void paravirt_ctxt_switch_from(struct vcpu *v)
+ {
+ save_segments(v);
++
++ /*
++ * Disable debug breakpoints. We do this aggressively because if we switch
++ * to an HVM guest we may load DR0-DR3 with values that can cause #DE
++ * inside Xen, before we get a chance to reload DR7, and this cannot always
++ * safely be handled.
++ */
++ if ( unlikely(v->arch.guest_context.debugreg[7]) )
++ write_debugreg(7, 0);
+ }
+
+ static void paravirt_ctxt_switch_to(struct vcpu *v)
+ {
+ set_int80_direct_trap(v);
+ switch_kernel_stack(v);
++
++ if ( unlikely(v->arch.guest_context.debugreg[7]) )
++ {
++ write_debugreg(0, v->arch.guest_context.debugreg[0]);
++ write_debugreg(1, v->arch.guest_context.debugreg[1]);
++ write_debugreg(2, v->arch.guest_context.debugreg[2]);
++ write_debugreg(3, v->arch.guest_context.debugreg[3]);
++ write_debugreg(6, v->arch.guest_context.debugreg[6]);
++ write_debugreg(7, v->arch.guest_context.debugreg[7]);
++ }
+ }
+-
+-#define loaddebug(_v,_reg) \
+- __asm__ __volatile__ ("mov %0,%%db" #_reg : : "r" ((_v)->debugreg[_reg]))
+
+ static void __context_switch(void)
+ {
+@@ -668,18 +684,6 @@ static void __context_switch(void)
+ memcpy(stack_regs,
+ &n->arch.guest_context.user_regs,
+ CTXT_SWITCH_STACK_BYTES);
+-
+- /* Maybe switch the debug registers. */
+- if ( unlikely(n->arch.guest_context.debugreg[7]) )
+- {
+- loaddebug(&n->arch.guest_context, 0);
+- loaddebug(&n->arch.guest_context, 1);
+- loaddebug(&n->arch.guest_context, 2);
+- loaddebug(&n->arch.guest_context, 3);
+- /* no 4 and 5 */
+- loaddebug(&n->arch.guest_context, 6);
+- loaddebug(&n->arch.guest_context, 7);
+- }
+ n->arch.ctxt_switch_to(n);
+ }
+
+diff -r d4449461dc16 -r 5f6dc1bafffd xen/arch/x86/hvm/svm/svm.c
+--- a/xen/arch/x86/hvm/svm/svm.c Tue Oct 17 22:09:27 2006 +0100
++++ b/xen/arch/x86/hvm/svm/svm.c Thu Nov 01 16:26:38 2007 +0000
+@@ -418,45 +418,48 @@ static inline int long_mode_do_msr_write
+ }
+
+
+-#define loaddebug(_v,_reg) \
+- __asm__ __volatile__ ("mov %0,%%db" #_reg : : "r" ((_v)->debugreg[_reg]))
+-#define savedebug(_v,_reg) \
+- __asm__ __volatile__ ("mov %%db" #_reg ",%0" : : "r" ((_v)->debugreg[_reg]))
+-
+-
+ static inline void svm_save_dr(struct vcpu *v)
+ {
+ if (v->arch.hvm_vcpu.flag_dr_dirty)
+ {
+ /* clear the DR dirty flag and re-enable intercepts for DR accesses */
+ v->arch.hvm_vcpu.flag_dr_dirty = 0;
+- v->arch.hvm_svm.vmcb->dr_intercepts = DR_INTERCEPT_ALL_WRITES;
++ v->arch.hvm_svm.vmcb->dr_intercepts = ~0u;
+
+- savedebug(&v->arch.guest_context, 0);
+- savedebug(&v->arch.guest_context, 1);
+- savedebug(&v->arch.guest_context, 2);
+- savedebug(&v->arch.guest_context, 3);
++ v->arch.guest_context.debugreg[0] = read_debugreg(0);
++ v->arch.guest_context.debugreg[1] = read_debugreg(1);
++ v->arch.guest_context.debugreg[2] = read_debugreg(2);
++ v->arch.guest_context.debugreg[3] = read_debugreg(3);
+ }
+ }
+
+
+ static inline void __restore_debug_registers(struct vcpu *v)
+ {
+- loaddebug(&v->arch.guest_context, 0);
+- loaddebug(&v->arch.guest_context, 1);
+- loaddebug(&v->arch.guest_context, 2);
+- loaddebug(&v->arch.guest_context, 3);
++ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
++
++ ASSERT(!v->arch.hvm_vcpu.flag_dr_dirty);
++ v->arch.hvm_vcpu.flag_dr_dirty = 1;
++ vmcb->dr_intercepts = 0;
++
++ write_debugreg(0, v->arch.guest_context.debugreg[0]);
++ write_debugreg(1, v->arch.guest_context.debugreg[1]);
++ write_debugreg(2, v->arch.guest_context.debugreg[2]);
++ write_debugreg(3, v->arch.guest_context.debugreg[3]);
+ }
+
+
+-static inline void svm_restore_dr(struct vcpu *v)
++/*
++ * DR7 is saved and restored on every vmexit. Other debug registers only
++ * need to be restored if their value is going to affect execution -- i.e.,
++ * if one of the breakpoints is enabled. So mask out all bits that don't
++ * enable some breakpoint functionality.
++ */
++#define DR7_ACTIVE_MASK 0xff
++
++static void svm_restore_dr(struct vcpu *v)
+ {
+- struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+-
+- if (!vmcb)
+- return;
+-
+- if (unlikely(vmcb->dr7 & 0xFF))
++ if ( unlikely(v->arch.guest_context.debugreg[7] & DR7_ACTIVE_MASK) )
+ __restore_debug_registers(v);
+ }
+
+@@ -1233,14 +1236,7 @@ static inline void set_reg(unsigned int
+
+ static void svm_dr_access(struct vcpu *v, struct cpu_user_regs *regs)
+ {
+- struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+-
+- v->arch.hvm_vcpu.flag_dr_dirty = 1;
+-
+ __restore_debug_registers(v);
+-
+- /* allow the guest full access to the debug registers */
+- vmcb->dr_intercepts = 0;
+ }
+
+
+diff -r d4449461dc16 -r 5f6dc1bafffd xen/arch/x86/hvm/svm/vmcb.c
+--- a/xen/arch/x86/hvm/svm/vmcb.c Tue Oct 17 22:09:27 2006 +0100
++++ b/xen/arch/x86/hvm/svm/vmcb.c Thu Nov 01 16:26:38 2007 +0000
+@@ -121,7 +121,7 @@ static int construct_vmcb_controls(struc
+ GENERAL2_INTERCEPT_SKINIT | GENERAL2_INTERCEPT_RDTSCP;
+
+ /* read or write all debug registers 0 - 15 */
+- vmcb->dr_intercepts = DR_INTERCEPT_ALL_WRITES;
++ vmcb->dr_intercepts = ~0u;
+
+ /* RD/WR all control registers 0 - 15, but not read CR2 */
+ vmcb->cr_intercepts = ~(CR_INTERCEPT_CR2_READ | CR_INTERCEPT_CR2_WRITE);
+diff -r d4449461dc16 -r 5f6dc1bafffd xen/arch/x86/hvm/vmx/vmx.c
+--- a/xen/arch/x86/hvm/vmx/vmx.c Tue Oct 17 22:09:27 2006 +0100
++++ b/xen/arch/x86/hvm/vmx/vmx.c Thu Nov 01 16:26:38 2007 +0000
+@@ -395,37 +395,34 @@ static inline int long_mode_do_msr_write
+
+ #endif /* __i386__ */
+
+-#define loaddebug(_v,_reg) \
+- __asm__ __volatile__ ("mov %0,%%db" #_reg : : "r" ((_v)->debugreg[_reg]))
+-#define savedebug(_v,_reg) \
+- __asm__ __volatile__ ("mov %%db" #_reg ",%0" : : "r" ((_v)->debugreg[_reg]))
+-
+ static inline void vmx_save_dr(struct vcpu *v)
+ {
+ if ( v->arch.hvm_vcpu.flag_dr_dirty )
+ {
+- savedebug(&v->arch.guest_context, 0);
+- savedebug(&v->arch.guest_context, 1);
+- savedebug(&v->arch.guest_context, 2);
+- savedebug(&v->arch.guest_context, 3);
+- savedebug(&v->arch.guest_context, 6);
+-
+ v->arch.hvm_vcpu.flag_dr_dirty = 0;
+
+ v->arch.hvm_vcpu.u.vmx.exec_control |= CPU_BASED_MOV_DR_EXITING;
+ __vmwrite(CPU_BASED_VM_EXEC_CONTROL,
+ v->arch.hvm_vcpu.u.vmx.exec_control);
++
++ v->arch.guest_context.debugreg[0] = read_debugreg(0);
++ v->arch.guest_context.debugreg[1] = read_debugreg(1);
++ v->arch.guest_context.debugreg[2] = read_debugreg(2);
++ v->arch.guest_context.debugreg[3] = read_debugreg(3);
++ v->arch.guest_context.debugreg[6] = read_debugreg(6);
+ }
+ }
+
+ static inline void __restore_debug_registers(struct vcpu *v)
+ {
+- loaddebug(&v->arch.guest_context, 0);
+- loaddebug(&v->arch.guest_context, 1);
+- loaddebug(&v->arch.guest_context, 2);
+- loaddebug(&v->arch.guest_context, 3);
+- /* No 4 and 5 */
+- loaddebug(&v->arch.guest_context, 6);
++ ASSERT(!v->arch.hvm_vcpu.flag_dr_dirty);
++ v->arch.hvm_vcpu.flag_dr_dirty = 1;
++
++ write_debugreg(0, v->arch.guest_context.debugreg[0]);
++ write_debugreg(1, v->arch.guest_context.debugreg[1]);
++ write_debugreg(2, v->arch.guest_context.debugreg[2]);
++ write_debugreg(3, v->arch.guest_context.debugreg[3]);
++ write_debugreg(6, v->arch.guest_context.debugreg[6]);
+ /* DR7 is loaded from the vmcs. */
+ }
+
+@@ -1008,10 +1005,8 @@ static void vmx_dr_access(unsigned long
+ {
+ struct vcpu *v = current;
+
+- v->arch.hvm_vcpu.flag_dr_dirty = 1;
+-
+- /* We could probably be smarter about this */
+- __restore_debug_registers(v);
++ if ( !v->arch.hvm_vcpu.flag_dr_dirty )
++ __restore_debug_registers(v);
+
+ /* Allow guest direct access to DR registers */
+ v->arch.hvm_vcpu.u.vmx.exec_control &= ~CPU_BASED_MOV_DR_EXITING;
+diff -r d4449461dc16 -r 5f6dc1bafffd xen/arch/x86/traps.c
+--- a/xen/arch/x86/traps.c Tue Oct 17 22:09:27 2006 +0100
++++ b/xen/arch/x86/traps.c Thu Nov 01 16:26:38 2007 +0000
+@@ -1667,20 +1667,9 @@ asmlinkage int math_state_restore(struct
+
+ asmlinkage int do_debug(struct cpu_user_regs *regs)
+ {
+- unsigned long condition;
+ struct vcpu *v = current;
+ struct trap_bounce *tb = &v->arch.trap_bounce;
+ struct trap_info *ti;
+-
+- __asm__ __volatile__("mov %%db6,%0" : "=r" (condition));
+-
+- /* Mask out spurious debug traps due to lazy DR7 setting */
+- if ( (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) &&
+- (v->arch.guest_context.debugreg[7] == 0) )
+- {
+- __asm__("mov %0,%%db7" : : "r" (0UL));
+- goto out;
+- }
+
+ DEBUGGER_trap_entry(TRAP_debug, regs);
+
+@@ -1698,7 +1687,7 @@ asmlinkage int do_debug(struct cpu_user_
+ }
+
+ /* Save debug status register where guest OS can peek at it */
+- v->arch.guest_context.debugreg[6] = condition;
++ v->arch.guest_context.debugreg[6] = read_debugreg(6);
+
+ ti = &v->arch.guest_context.trap_ctxt[TRAP_debug];
+ tb->flags = TBF_EXCEPTION;
+@@ -1844,25 +1833,25 @@ long set_debugreg(struct vcpu *p, int re
+ if ( !access_ok(value, sizeof(long)) )
+ return -EPERM;
+ if ( p == current )
+- __asm__ ( "mov %0, %%db0" : : "r" (value) );
++ write_debugreg(0, value);
+ break;
+ case 1:
+ if ( !access_ok(value, sizeof(long)) )
+ return -EPERM;
+ if ( p == current )
+- __asm__ ( "mov %0, %%db1" : : "r" (value) );
++ write_debugreg(1, value);
+ break;
+ case 2:
+ if ( !access_ok(value, sizeof(long)) )
+ return -EPERM;
+ if ( p == current )
+- __asm__ ( "mov %0, %%db2" : : "r" (value) );
++ write_debugreg(2, value);
+ break;
+ case 3:
+ if ( !access_ok(value, sizeof(long)) )
+ return -EPERM;
+ if ( p == current )
+- __asm__ ( "mov %0, %%db3" : : "r" (value) );
++ write_debugreg(3, value);
+ break;
+ case 6:
+ /*
+@@ -1872,7 +1861,7 @@ long set_debugreg(struct vcpu *p, int re
+ value &= 0xffffefff; /* reserved bits => 0 */
+ value |= 0xffff0ff0; /* reserved bits => 1 */
+ if ( p == current )
+- __asm__ ( "mov %0, %%db6" : : "r" (value) );
++ write_debugreg(6, value);
+ break;
+ case 7:
+ /*
+@@ -1891,9 +1880,22 @@ long set_debugreg(struct vcpu *p, int re
+ if ( (value & (1<<13)) != 0 ) return -EPERM;
+ for ( i = 0; i < 16; i += 2 )
+ if ( ((value >> (i+16)) & 3) == 2 ) return -EPERM;
++ /*
++ * If DR7 was previously clear then we need to load all other
++ * debug registers at this point as they were not restored during
++ * context switch.
++ */
++ if ( (p == current) && (p->arch.guest_context.debugreg[7] == 0) )
++ {
++ write_debugreg(0, p->arch.guest_context.debugreg[0]);
++ write_debugreg(1, p->arch.guest_context.debugreg[1]);
++ write_debugreg(2, p->arch.guest_context.debugreg[2]);
++ write_debugreg(3, p->arch.guest_context.debugreg[3]);
++ write_debugreg(6, p->arch.guest_context.debugreg[6]);
++ }
+ }
+ if ( p == current )
+- __asm__ ( "mov %0, %%db7" : : "r" (value) );
++ write_debugreg(7, value);
+ break;
+ default:
+ return -EINVAL;
+diff -r d4449461dc16 -r 5f6dc1bafffd xen/include/asm-x86/hvm/svm/vmcb.h
+--- a/xen/include/asm-x86/hvm/svm/vmcb.h Tue Oct 17 22:09:27 2006 +0100
++++ b/xen/include/asm-x86/hvm/svm/vmcb.h Thu Nov 01 16:26:38 2007 +0000
+@@ -151,13 +151,6 @@ enum DRInterceptBits
+ DR_INTERCEPT_DR14_WRITE = 1 << 30,
+ DR_INTERCEPT_DR15_WRITE = 1 << 31,
+ };
+-
+-/* for lazy save/restore we'd like to intercept all DR writes */
+-#define DR_INTERCEPT_ALL_WRITES \
+- (DR_INTERCEPT_DR0_WRITE|DR_INTERCEPT_DR1_WRITE|DR_INTERCEPT_DR2_WRITE \
+- |DR_INTERCEPT_DR3_WRITE|DR_INTERCEPT_DR4_WRITE|DR_INTERCEPT_DR5_WRITE \
+- |DR_INTERCEPT_DR6_WRITE|DR_INTERCEPT_DR7_WRITE)
+-
+
+ enum VMEXIT_EXITCODE
+ {
+diff -r d4449461dc16 -r 5f6dc1bafffd xen/include/asm-x86/processor.h
+--- a/xen/include/asm-x86/processor.h Tue Oct 17 22:09:27 2006 +0100
++++ b/xen/include/asm-x86/processor.h Thu Nov 01 16:26:38 2007 +0000
+@@ -478,6 +478,15 @@ long set_gdt(struct vcpu *d,
+ unsigned long *frames,
+ unsigned int entries);
+
++#define write_debugreg(reg, val) do { \
++ unsigned long __val = val; \
++ asm volatile ( "mov %0,%%db" #reg : : "r" (__val) ); \
++} while (0)
++#define read_debugreg(reg) ({ \
++ unsigned long __val; \
++ asm volatile ( "mov %%db" #reg ",%0" : "=r" (__val) ); \
++ __val; \
++})
+ long set_debugreg(struct vcpu *p, int reg, unsigned long value);
+
+ struct microcode_header {
Added: branches/etch/xen-3.0/debian/patches/CVE-2008-0928.dpatch
==============================================================================
--- (empty file)
+++ branches/etch/xen-3.0/debian/patches/CVE-2008-0928.dpatch Sat Jul 12 11:03:33 2008
@@ -0,0 +1,67 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+
+ at DPATCH@
+diff -r 5f6dc1bafffd -r 42c6318fb648 tools/ioemu/block.c
+--- a/tools/ioemu/block.c Thu Nov 01 16:26:38 2007 +0000
++++ b/tools/ioemu/block.c Wed Feb 20 17:46:10 2008 +0000
+@@ -47,6 +47,8 @@
+ #ifdef __sun__
+ #include <sys/dkio.h>
+ #endif
++
++#define SECTOR_BITS 9
+
+ static BlockDriverState *bdrv_first;
+ static BlockDriver *first_drv;
+@@ -108,6 +110,15 @@ kern_return_t GetBSDPath( io_iterator_t
+ }
+
+ #endif
++
++static int bdrv_rw_badreq_sectors(BlockDriverState *bs,
++ int64_t sector_num, int nb_sectors)
++{
++ return
++ nb_sectors < 0 ||
++ nb_sectors > bs->total_sectors ||
++ sector_num > bs->total_sectors - nb_sectors;
++}
+
+ void bdrv_register(BlockDriver *bdrv)
+ {
+@@ -307,6 +318,7 @@ int bdrv_open2(BlockDriverState *bs, con
+ }
+ bs->drv = drv;
+ bs->opaque = qemu_mallocz(drv->instance_size);
++ bs->total_sectors = 0; /* driver will set if it does not do getlength */
+ if (bs->opaque == NULL && drv->instance_size > 0)
+ return -1;
+
+@@ -358,6 +370,7 @@ void bdrv_close(BlockDriverState *bs)
+ bs->inserted = 0;
+
+ /* call the change callback */
++ bs->total_sectors = 0;
+ if (bs->change_cb)
+ bs->change_cb(bs->change_opaque);
+ }
+@@ -418,8 +431,8 @@ int bdrv_read(BlockDriverState *bs, int6
+ int ret, n;
+ BlockDriver *drv = bs->drv;
+
+- if (!bs->inserted)
+- return -1;
++ if (bdrv_rw_badreq_sectors(bs, sector_num, nb_sectors))
++ return -EDOM;
+
+ while (nb_sectors > 0) {
+ if (sector_num == 0 && bs->boot_sector_enabled) {
+@@ -458,6 +471,8 @@ int bdrv_write(BlockDriverState *bs, int
+ return -1;
+ if (bs->read_only)
+ return -1;
++ if (bdrv_rw_badreq_sectors(bs, sector_num, nb_sectors))
++ return -EDOM;
+ if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
+ memcpy(bs->boot_sector_data, buf, 512);
+ }
More information about the Pkg-xen-changes
mailing list