xen/23723-x86-CMOS-lock.patch
Charles Arnold 3f55414718 - Update to Xen 4.1.3 c/s 23336
- Upstream or pending upstream patches from Jan
  25587-fix-off-by-one-parsing-error.patch
  25616-x86-MCi_CTL-default.patch
  25617-vtd-qinval-addr.patch
  25688-x86-nr_irqs_gsi.patch
- bnc#773393 - VUL-0: CVE-2012-3433: xen: HVM guest destroy p2m
  teardown host DoS vulnerability
  CVE-2012-3433-xsa11.patch
- bnc#773401 - VUL-1: CVE-2012-3432: xen: HVM guest user mode MMIO
  emulation DoS
  25682-x86-inconsistent-io-state.patch

- bnc#762484 - VUL-1: CVE-2012-2625: xen: pv bootloader doesn't
  check the size of the bzip2 or lzma compressed kernel, leading to
  denial of service
  25589-pygrub-size-limits.patch

- Make it build with latest TeXLive 2012 with new package layout

OBS-URL: https://build.opensuse.org/package/show/Virtualization/xen?expand=0&rev=196
2012-08-10 21:38:41 +00:00

284 lines
9.7 KiB
Diff

# HG changeset patch
# User Jan Beulich <jbeulich@novell.com>
# Date 1311081053 -3600
# Node ID 18653a163b1e8e10b4353272bcb9e8302bfd2e19
# Parent 7bc5825e471db5a3a989f47d21334ef63a6b5610
x86: consistently serialize CMOS/RTC accesses on rtc_lock
Since RTC/CMOS accesses aren't atomic, there are possible races
between code paths setting the index register and subsequently
reading/writing the data register. This is supposed to be dealt with
by acquiring rtc_lock, but two places up to now lacked respective
synchronization: Accesses to the EFI time functions and
smpboot_{setup,restore}_warm_reset_vector().
This in turn requires no longer directly passing through guest writes
to the index register, but instead using a machanism similar to that
for PCI config space method 1 accesses.
Signed-off-by: Jan Beulich <jbeulich@novell.com>
Index: xen-4.1.3-testing/xen/arch/x86/efi/runtime.c
===================================================================
--- xen-4.1.3-testing.orig/xen/arch/x86/efi/runtime.c
+++ xen-4.1.3-testing/xen/arch/x86/efi/runtime.c
@@ -3,6 +3,7 @@
#include <xen/errno.h>
#include <xen/guest_access.h>
#include <xen/time.h>
+#include <asm/mc146818rtc.h>
DEFINE_XEN_GUEST_HANDLE(CHAR16);
@@ -80,9 +81,11 @@ unsigned long efi_get_time(void)
{
EFI_TIME time;
EFI_STATUS status;
- unsigned long cr3 = efi_rs_enter();
+ unsigned long cr3 = efi_rs_enter(), flags;
+ spin_lock_irqsave(&rtc_lock, flags);
status = efi_rs->GetTime(&time, NULL);
+ spin_unlock_irqrestore(&rtc_lock, flags);
efi_rs_leave(cr3);
if ( EFI_ERROR(status) )
@@ -223,7 +226,7 @@ static inline EFI_GUID *cast_guid(struct
int efi_runtime_call(struct xenpf_efi_runtime_call *op)
{
- unsigned long cr3;
+ unsigned long cr3, flags;
EFI_STATUS status = EFI_NOT_STARTED;
int rc = 0;
@@ -237,7 +240,9 @@ int efi_runtime_call(struct xenpf_efi_ru
return -EINVAL;
cr3 = efi_rs_enter();
+ spin_lock_irqsave(&rtc_lock, flags);
status = efi_rs->GetTime(cast_time(&op->u.get_time.time), &caps);
+ spin_unlock_irqrestore(&rtc_lock, flags);
efi_rs_leave(cr3);
if ( !EFI_ERROR(status) )
@@ -255,7 +260,9 @@ int efi_runtime_call(struct xenpf_efi_ru
return -EINVAL;
cr3 = efi_rs_enter();
+ spin_lock_irqsave(&rtc_lock, flags);
status = efi_rs->SetTime(cast_time(&op->u.set_time));
+ spin_unlock_irqrestore(&rtc_lock, flags);
efi_rs_leave(cr3);
break;
@@ -267,8 +274,10 @@ int efi_runtime_call(struct xenpf_efi_ru
return -EINVAL;
cr3 = efi_rs_enter();
+ spin_lock_irqsave(&rtc_lock, flags);
status = efi_rs->GetWakeupTime(&enabled, &pending,
cast_time(&op->u.get_wakeup_time));
+ spin_unlock_irqrestore(&rtc_lock, flags);
efi_rs_leave(cr3);
if ( !EFI_ERROR(status) )
@@ -287,12 +296,14 @@ int efi_runtime_call(struct xenpf_efi_ru
return -EINVAL;
cr3 = efi_rs_enter();
+ spin_lock_irqsave(&rtc_lock, flags);
status = efi_rs->SetWakeupTime(!!(op->misc &
XEN_EFI_SET_WAKEUP_TIME_ENABLE),
(op->misc &
XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY) ?
NULL :
cast_time(&op->u.set_wakeup_time));
+ spin_unlock_irqrestore(&rtc_lock, flags);
efi_rs_leave(cr3);
op->misc = 0;
Index: xen-4.1.3-testing/xen/arch/x86/hpet.c
===================================================================
--- xen-4.1.3-testing.orig/xen/arch/x86/hpet.c
+++ xen-4.1.3-testing/xen/arch/x86/hpet.c
@@ -525,18 +525,10 @@ static void hpet_detach_channel(int cpu,
#include <asm/mc146818rtc.h>
-void (*pv_rtc_handler)(unsigned int port, uint8_t value);
+void (*__read_mostly pv_rtc_handler)(uint8_t index, uint8_t value);
-static void handle_rtc_once(unsigned int port, uint8_t value)
+static void handle_rtc_once(uint8_t index, uint8_t value)
{
- static int index;
-
- if ( port == 0x70 )
- {
- index = value;
- return;
- }
-
if ( index != RTC_REG_B )
return;
Index: xen-4.1.3-testing/xen/arch/x86/traps.c
===================================================================
--- xen-4.1.3-testing.orig/xen/arch/x86/traps.c
+++ xen-4.1.3-testing/xen/arch/x86/traps.c
@@ -67,6 +67,8 @@
#include <asm/hypercall.h>
#include <asm/mce.h>
#include <asm/apic.h>
+#include <asm/mc146818rtc.h>
+#include <asm/hpet.h>
#include <public/arch-x86/cpuid.h>
/*
@@ -1656,6 +1658,10 @@ static int admin_io_okay(
if ( (port == 0xcf8) && (bytes == 4) )
return 0;
+ /* We also never permit direct access to the RTC/CMOS registers. */
+ if ( ((port & ~1) == RTC_PORT(0)) )
+ return 0;
+
return ioports_access_permitted(v->domain, port, port + bytes - 1);
}
@@ -1685,6 +1691,21 @@ static uint32_t guest_io_read(
{
sub_data = pv_pit_handler(port, 0, 0);
}
+ else if ( (port == RTC_PORT(0)) )
+ {
+ sub_data = v->domain->arch.cmos_idx;
+ }
+ else if ( (port == RTC_PORT(1)) &&
+ ioports_access_permitted(v->domain, RTC_PORT(0),
+ RTC_PORT(1)) )
+ {
+ unsigned long flags;
+
+ spin_lock_irqsave(&rtc_lock, flags);
+ outb(v->domain->arch.cmos_idx & 0x7f, RTC_PORT(0));
+ sub_data = inb(RTC_PORT(1));
+ spin_unlock_irqrestore(&rtc_lock, flags);
+ }
else if ( (port == 0xcf8) && (bytes == 4) )
{
size = 4;
@@ -1710,8 +1731,6 @@ static uint32_t guest_io_read(
return data;
}
-extern void (*pv_rtc_handler)(unsigned int port, uint8_t value);
-
static void guest_io_write(
unsigned int port, unsigned int bytes, uint32_t data,
struct vcpu *v, struct cpu_user_regs *regs)
@@ -1720,8 +1739,6 @@ static void guest_io_write(
{
switch ( bytes ) {
case 1:
- if ( ((port == 0x70) || (port == 0x71)) && pv_rtc_handler )
- pv_rtc_handler(port, (uint8_t)data);
outb((uint8_t)data, port);
if ( pv_post_outb_hook )
pv_post_outb_hook(port, (uint8_t)data);
@@ -1744,6 +1761,23 @@ static void guest_io_write(
{
pv_pit_handler(port, (uint8_t)data, 1);
}
+ else if ( (port == RTC_PORT(0)) )
+ {
+ v->domain->arch.cmos_idx = data;
+ }
+ else if ( (port == RTC_PORT(1)) &&
+ ioports_access_permitted(v->domain, RTC_PORT(0),
+ RTC_PORT(1)) )
+ {
+ unsigned long flags;
+
+ if ( pv_rtc_handler )
+ pv_rtc_handler(v->domain->arch.cmos_idx & 0x7f, data);
+ spin_lock_irqsave(&rtc_lock, flags);
+ outb(v->domain->arch.cmos_idx & 0x7f, RTC_PORT(0));
+ outb(data, RTC_PORT(1));
+ spin_unlock_irqrestore(&rtc_lock, flags);
+ }
else if ( (port == 0xcf8) && (bytes == 4) )
{
size = 4;
@@ -2109,10 +2143,6 @@ static int emulate_privileged_op(struct
goto fail;
if ( admin_io_okay(port, op_bytes, v, regs) )
{
- if ( (op_bytes == 1) &&
- ((port == 0x71) || (port == 0x70)) &&
- pv_rtc_handler )
- pv_rtc_handler(port, regs->eax);
io_emul(regs);
if ( (op_bytes == 1) && pv_post_outb_hook )
pv_post_outb_hook(port, regs->eax);
Index: xen-4.1.3-testing/xen/include/asm-x86/domain.h
===================================================================
--- xen-4.1.3-testing.orig/xen/include/asm-x86/domain.h
+++ xen-4.1.3-testing/xen/include/asm-x86/domain.h
@@ -251,6 +251,7 @@ struct arch_domain
/* I/O-port admin-specified access capabilities. */
struct rangeset *ioport_caps;
uint32_t pci_cf8;
+ uint8_t cmos_idx;
struct list_head pdev_list;
struct hvm_domain hvm_domain;
Index: xen-4.1.3-testing/xen/include/asm-x86/hpet.h
===================================================================
--- xen-4.1.3-testing.orig/xen/include/asm-x86/hpet.h
+++ xen-4.1.3-testing/xen/include/asm-x86/hpet.h
@@ -52,6 +52,7 @@
#define HPET_TN_FSB_CAP 0x8000
#define HPET_TN_ROUTE_SHIFT 9
+extern void (*pv_rtc_handler)(uint8_t reg, uint8_t value);
#define hpet_read32(x) \
(*(volatile u32 *)(fix_to_virt(FIX_HPET_BASE) + (x)))
Index: xen-4.1.3-testing/xen/include/asm-x86/mach-default/smpboot_hooks.h
===================================================================
--- xen-4.1.3-testing.orig/xen/include/asm-x86/mach-default/smpboot_hooks.h
+++ xen-4.1.3-testing/xen/include/asm-x86/mach-default/smpboot_hooks.h
@@ -3,7 +3,11 @@
static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&rtc_lock, flags);
CMOS_WRITE(0xa, 0xf);
+ spin_unlock_irqrestore(&rtc_lock, flags);
flush_tlb_local();
Dprintk("1.\n");
*((volatile unsigned short *) TRAMPOLINE_HIGH) = start_eip >> 4;
@@ -14,6 +18,8 @@ static inline void smpboot_setup_warm_re
static inline void smpboot_restore_warm_reset_vector(void)
{
+ unsigned long flags;
+
/*
* Install writable page 0 entry to set BIOS data area.
*/
@@ -23,7 +29,9 @@ static inline void smpboot_restore_warm_
* Paranoid: Set warm reset code and vector here back
* to default values.
*/
+ spin_lock_irqsave(&rtc_lock, flags);
CMOS_WRITE(0, 0xf);
+ spin_unlock_irqrestore(&rtc_lock, flags);
*((volatile int *) maddr_to_virt(0x467)) = 0;
}