diff options
author | Roger Pau Monne <roger.pau@citrix.com> | 2013-02-06 10:02:31 +0100 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2013-02-06 11:37:38 +0000 |
commit | ab769fcca45a6672cfcd923c9af4dca5b149483c (patch) | |
tree | 3b069838ba944e3df02d6b2f501406f20831d59a /main/xen | |
parent | 4d99c9eae809711fa0c486aeaf18e9f5f58bf695 (diff) | |
download | aports-ab769fcca45a6672cfcd923c9af4dca5b149483c.tar.bz2 aports-ab769fcca45a6672cfcd923c9af4dca5b149483c.tar.xz |
xen: XSA-36 and XSA-38
Diffstat (limited to 'main/xen')
-rw-r--r-- | main/xen/APKBUILD | 6 | ||||
-rw-r--r-- | main/xen/xsa36-4.2.patch | 323 | ||||
-rw-r--r-- | main/xen/xsa38.patch | 73 |
3 files changed, 401 insertions, 1 deletions
diff --git a/main/xen/APKBUILD b/main/xen/APKBUILD index 5e07fabdfe..51ff406c45 100644 --- a/main/xen/APKBUILD +++ b/main/xen/APKBUILD @@ -3,7 +3,7 @@ # Maintainer: William Pitcock <nenolod@dereferenced.org> pkgname=xen pkgver=4.2.1 -pkgrel=5 +pkgrel=6 pkgdesc="Xen hypervisor" url="http://www.xen.org/" arch="x86 x86_64" @@ -24,6 +24,8 @@ source="http://bits.xensource.com/oss-xen/release/$pkgver/$pkgname-$pkgver.tar.g xsa41c.patch xsa34-4.2.patch xsa35-4.2-with-xsa34.patch + xsa36-4.2.patch + xsa38.patch xenstored.initd xenstored.confd @@ -145,6 +147,8 @@ ed7d0399c6ca6aeee479da5d8f807fe0 xsa41b.patch 2f3dd7bdc59d104370066d6582725575 xsa41c.patch af10e1a3f757a184a1d79904a5ef8572 xsa34-4.2.patch 8270dbf929e26b5e95532d10a697e404 xsa35-4.2-with-xsa34.patch +87a54b2a1f1ea3d955017fe1fd8c0398 xsa36-4.2.patch +47589e06d077d71282ec1b87dd4d87a9 xsa38.patch 95d8af17bf844d41a015ff32aae51ba1 xenstored.initd b017ccdd5e1c27bbf1513e3569d4ff07 xenstored.confd ed262f15fb880badb53575539468646c xenconsoled.initd diff --git a/main/xen/xsa36-4.2.patch b/main/xen/xsa36-4.2.patch new file mode 100644 index 0000000000..8477701a22 --- /dev/null +++ b/main/xen/xsa36-4.2.patch @@ -0,0 +1,323 @@ +ACPI: acpi_table_parse() should return handler's error code + +Currently, the error code returned by acpi_table_parse()'s handler +is ignored. This patch will propagate handler's return value to +acpi_table_parse()'s caller. + +AMD,IOMMU: Clean up old entries in remapping tables when creating new +interrupt mapping. + +When changing the affinity of an IRQ associated with a passed +through PCI device, clear previous mapping. + +In addition, because some BIOSes may incorrectly program IVRS +entries for IOAPIC try to check for entry's consistency. Specifically, +if conflicting entries are found disable IOMMU if per-device +remapping table is used. If entries refer to bogus IOAPIC IDs +disable IOMMU unconditionally + +AMD,IOMMU: Disable IOMMU if SATA Combined mode is on + +AMD's SP5100 chipset can be placed into SATA Combined mode +that may cause prevent dom0 from booting when IOMMU is +enabled and per-device interrupt remapping table is used. +While SP5100 erratum 28 requires BIOSes to disable this mode, +some may still use it. + +This patch checks whether this mode is on and, if per-device +table is in use, disables IOMMU. + +AMD,IOMMU: Make per-device interrupt remapping table default + +Using global interrupt remapping table may be insecure, as +described by XSA-36. This patch makes per-device mode default. + +This is XSA-36 / CVE-2013-0153. + +Signed-off-by: Jan Beulich <jbeulich@suse.com> +Signed-off-by: Boris Ostrovsky <boris.ostrovsky@amd.com> + +--- a/xen/arch/x86/irq.c ++++ b/xen/arch/x86/irq.c +@@ -1942,9 +1942,6 @@ int map_domain_pirq( + spin_lock_irqsave(&desc->lock, flags); + set_domain_irq_pirq(d, irq, info); + spin_unlock_irqrestore(&desc->lock, flags); +- +- if ( opt_irq_vector_map == OPT_IRQ_VECTOR_MAP_PERDEV ) +- printk(XENLOG_INFO "Per-device vector maps for GSIs not implemented yet.\n"); + } + + done: +--- a/xen/drivers/acpi/tables.c ++++ b/xen/drivers/acpi/tables.c +@@ -267,7 +267,7 @@ acpi_table_parse_madt(enum acpi_madt_typ + * @handler: handler to run + * + * Scan the ACPI System Descriptor Table (STD) for a table matching @id, +- * run @handler on it. Return 0 if table found, return on if not. ++ * run @handler on it. + */ + int __init acpi_table_parse(char *id, acpi_table_handler handler) + { +@@ -282,8 +282,7 @@ int __init acpi_table_parse(char *id, ac + acpi_get_table(id, 0, &table); + + if (table) { +- handler(table); +- return 0; ++ return handler(table); + } else + return 1; + } +--- a/xen/drivers/passthrough/amd/iommu_acpi.c ++++ b/xen/drivers/passthrough/amd/iommu_acpi.c +@@ -22,6 +22,7 @@ + #include <xen/errno.h> + #include <xen/acpi.h> + #include <asm/apicdef.h> ++#include <asm/io_apic.h> + #include <asm/amd-iommu.h> + #include <asm/hvm/svm/amd-iommu-proto.h> + +@@ -635,6 +636,7 @@ static u16 __init parse_ivhd_device_spec + u16 header_length, u16 block_length, struct amd_iommu *iommu) + { + u16 dev_length, bdf; ++ int apic; + + dev_length = sizeof(*special); + if ( header_length < (block_length + dev_length) ) +@@ -651,10 +653,59 @@ static u16 __init parse_ivhd_device_spec + } + + add_ivrs_mapping_entry(bdf, bdf, special->header.data_setting, iommu); +- /* set device id of ioapic */ +- ioapic_sbdf[special->handle].bdf = bdf; +- ioapic_sbdf[special->handle].seg = seg; +- return dev_length; ++ ++ if ( special->variety != ACPI_IVHD_IOAPIC ) ++ { ++ if ( special->variety != ACPI_IVHD_HPET ) ++ printk(XENLOG_ERR "Unrecognized IVHD special variety %#x\n", ++ special->variety); ++ return dev_length; ++ } ++ ++ /* ++ * Some BIOSes have IOAPIC broken entries so we check for IVRS ++ * consistency here --- whether entry's IOAPIC ID is valid and ++ * whether there are conflicting/duplicated entries. ++ */ ++ for ( apic = 0; apic < nr_ioapics; apic++ ) ++ { ++ if ( IO_APIC_ID(apic) != special->handle ) ++ continue; ++ ++ if ( ioapic_sbdf[special->handle].pin_setup ) ++ { ++ if ( ioapic_sbdf[special->handle].bdf == bdf && ++ ioapic_sbdf[special->handle].seg == seg ) ++ AMD_IOMMU_DEBUG("IVHD Warning: Duplicate IO-APIC %#x entries\n", ++ special->handle); ++ else ++ { ++ printk(XENLOG_ERR "IVHD Error: Conflicting IO-APIC %#x entries\n", ++ special->handle); ++ if ( amd_iommu_perdev_intremap ) ++ return 0; ++ } ++ } ++ else ++ { ++ /* set device id of ioapic */ ++ ioapic_sbdf[special->handle].bdf = bdf; ++ ioapic_sbdf[special->handle].seg = seg; ++ ++ ioapic_sbdf[special->handle].pin_setup = xzalloc_array( ++ unsigned long, BITS_TO_LONGS(nr_ioapic_entries[apic])); ++ if ( nr_ioapic_entries[apic] && ++ !ioapic_sbdf[IO_APIC_ID(apic)].pin_setup ) ++ { ++ printk(XENLOG_ERR "IVHD Error: Out of memory\n"); ++ return 0; ++ } ++ } ++ return dev_length; ++ } ++ ++ printk(XENLOG_ERR "IVHD Error: Invalid IO-APIC %#x\n", special->handle); ++ return 0; + } + + static int __init parse_ivhd_block(const struct acpi_ivrs_hardware *ivhd_block) +--- a/xen/drivers/passthrough/amd/iommu_init.c ++++ b/xen/drivers/passthrough/amd/iommu_init.c +@@ -1126,12 +1126,45 @@ static int __init amd_iommu_setup_device + return 0; + } + ++/* Check whether SP5100 SATA Combined mode is on */ ++static bool_t __init amd_sp5100_erratum28(void) ++{ ++ u32 bus, id; ++ u16 vendor_id, dev_id; ++ u8 byte; ++ ++ for (bus = 0; bus < 256; bus++) ++ { ++ id = pci_conf_read32(0, bus, 0x14, 0, PCI_VENDOR_ID); ++ ++ vendor_id = id & 0xffff; ++ dev_id = (id >> 16) & 0xffff; ++ ++ /* SP5100 SMBus module sets Combined mode on */ ++ if (vendor_id != 0x1002 || dev_id != 0x4385) ++ continue; ++ ++ byte = pci_conf_read8(0, bus, 0x14, 0, 0xad); ++ if ( (byte >> 3) & 1 ) ++ { ++ printk(XENLOG_WARNING "AMD-Vi: SP5100 erratum 28 detected, disabling IOMMU.\n" ++ "If possible, disable SATA Combined mode in BIOS or contact your vendor for BIOS update.\n"); ++ return 1; ++ } ++ } ++ ++ return 0; ++} ++ + int __init amd_iommu_init(void) + { + struct amd_iommu *iommu; + + BUG_ON( !iommu_found() ); + ++ if ( amd_iommu_perdev_intremap && amd_sp5100_erratum28() ) ++ goto error_out; ++ + ivrs_bdf_entries = amd_iommu_get_ivrs_dev_entries(); + + if ( !ivrs_bdf_entries ) +--- a/xen/drivers/passthrough/amd/iommu_intr.c ++++ b/xen/drivers/passthrough/amd/iommu_intr.c +@@ -99,12 +99,12 @@ static void update_intremap_entry(u32* e + static void update_intremap_entry_from_ioapic( + int bdf, + struct amd_iommu *iommu, +- struct IO_APIC_route_entry *ioapic_rte) ++ const struct IO_APIC_route_entry *rte, ++ const struct IO_APIC_route_entry *old_rte) + { + unsigned long flags; + u32* entry; + u8 delivery_mode, dest, vector, dest_mode; +- struct IO_APIC_route_entry *rte = ioapic_rte; + int req_id; + spinlock_t *lock; + int offset; +@@ -120,6 +120,14 @@ static void update_intremap_entry_from_i + spin_lock_irqsave(lock, flags); + + offset = get_intremap_offset(vector, delivery_mode); ++ if ( old_rte ) ++ { ++ int old_offset = get_intremap_offset(old_rte->vector, ++ old_rte->delivery_mode); ++ ++ if ( offset != old_offset ) ++ free_intremap_entry(iommu->seg, bdf, old_offset); ++ } + entry = (u32*)get_intremap_entry(iommu->seg, req_id, offset); + update_intremap_entry(entry, vector, delivery_mode, dest_mode, dest); + +@@ -188,6 +196,7 @@ int __init amd_iommu_setup_ioapic_remapp + amd_iommu_flush_intremap(iommu, req_id); + spin_unlock_irqrestore(&iommu->lock, flags); + } ++ set_bit(pin, ioapic_sbdf[IO_APIC_ID(apic)].pin_setup); + } + } + return 0; +@@ -199,6 +208,7 @@ void amd_iommu_ioapic_update_ire( + struct IO_APIC_route_entry old_rte = { 0 }; + struct IO_APIC_route_entry new_rte = { 0 }; + unsigned int rte_lo = (reg & 1) ? reg - 1 : reg; ++ unsigned int pin = (reg - 0x10) / 2; + int saved_mask, seg, bdf; + struct amd_iommu *iommu; + +@@ -236,6 +246,14 @@ void amd_iommu_ioapic_update_ire( + *(((u32 *)&new_rte) + 1) = value; + } + ++ if ( new_rte.mask && ++ !test_bit(pin, ioapic_sbdf[IO_APIC_ID(apic)].pin_setup) ) ++ { ++ ASSERT(saved_mask); ++ __io_apic_write(apic, reg, value); ++ return; ++ } ++ + /* mask the interrupt while we change the intremap table */ + if ( !saved_mask ) + { +@@ -244,7 +262,11 @@ void amd_iommu_ioapic_update_ire( + } + + /* Update interrupt remapping entry */ +- update_intremap_entry_from_ioapic(bdf, iommu, &new_rte); ++ update_intremap_entry_from_ioapic( ++ bdf, iommu, &new_rte, ++ test_and_set_bit(pin, ++ ioapic_sbdf[IO_APIC_ID(apic)].pin_setup) ? &old_rte ++ : NULL); + + /* Forward write access to IO-APIC RTE */ + __io_apic_write(apic, reg, value); +@@ -354,6 +376,12 @@ void amd_iommu_msi_msg_update_ire( + return; + } + ++ if ( msi_desc->remap_index >= 0 ) ++ update_intremap_entry_from_msi_msg(iommu, pdev, msi_desc, NULL); ++ ++ if ( !msg ) ++ return; ++ + update_intremap_entry_from_msi_msg(iommu, pdev, msi_desc, msg); + } + +--- a/xen/drivers/passthrough/amd/pci_amd_iommu.c ++++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c +@@ -205,6 +205,8 @@ int __init amd_iov_detect(void) + { + printk("AMD-Vi: Not overriding irq_vector_map setting\n"); + } ++ if ( !amd_iommu_perdev_intremap ) ++ printk(XENLOG_WARNING "AMD-Vi: Using global interrupt remap table is not recommended (see XSA-36)!\n"); + return scan_pci_devices(); + } + +--- a/xen/drivers/passthrough/iommu.c ++++ b/xen/drivers/passthrough/iommu.c +@@ -52,7 +52,7 @@ bool_t __read_mostly iommu_qinval = 1; + bool_t __read_mostly iommu_intremap = 1; + bool_t __read_mostly iommu_hap_pt_share = 1; + bool_t __read_mostly iommu_debug; +-bool_t __read_mostly amd_iommu_perdev_intremap; ++bool_t __read_mostly amd_iommu_perdev_intremap = 1; + + DEFINE_PER_CPU(bool_t, iommu_dont_flush_iotlb); + +--- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h ++++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +@@ -100,6 +100,7 @@ void amd_iommu_read_msi_from_ire( + + extern struct ioapic_sbdf { + u16 bdf, seg; ++ unsigned long *pin_setup; + } ioapic_sbdf[MAX_IO_APICS]; + extern void *shared_intremap_table; + diff --git a/main/xen/xsa38.patch b/main/xen/xsa38.patch new file mode 100644 index 0000000000..f4a5dc0881 --- /dev/null +++ b/main/xen/xsa38.patch @@ -0,0 +1,73 @@ +diff --git a/tools/ocaml/libs/xb/partial.ml b/tools/ocaml/libs/xb/partial.ml +index 3558889..d4d1c7b 100644 +--- a/tools/ocaml/libs/xb/partial.ml ++++ b/tools/ocaml/libs/xb/partial.ml +@@ -27,8 +27,15 @@ external header_size: unit -> int = "stub_header_size" + external header_of_string_internal: string -> int * int * int * int + = "stub_header_of_string" + ++let xenstore_payload_max = 4096 (* xen/include/public/io/xs_wire.h *) ++ + let of_string s = + let tid, rid, opint, dlen = header_of_string_internal s in ++ (* A packet which is bigger than xenstore_payload_max is illegal. ++ This will leave the guest connection is a bad state and will ++ be hard to recover from without restarting the connection ++ (ie rebooting the guest) *) ++ let dlen = min xenstore_payload_max dlen in + { + tid = tid; + rid = rid; +@@ -38,6 +45,7 @@ let of_string s = + } + + let append pkt s sz = ++ if pkt.len > 4096 then failwith "Buffer.add: cannot grow buffer"; + Buffer.add_string pkt.buf (String.sub s 0 sz) + + let to_complete pkt = +diff --git a/tools/ocaml/libs/xb/xs_ring_stubs.c b/tools/ocaml/libs/xb/xs_ring_stubs.c +index 00414c5..4888ac5 100644 +--- a/tools/ocaml/libs/xb/xs_ring_stubs.c ++++ b/tools/ocaml/libs/xb/xs_ring_stubs.c +@@ -39,21 +39,23 @@ static int xs_ring_read(struct mmap_interface *interface, + char *buffer, int len) + { + struct xenstore_domain_interface *intf = interface->addr; +- XENSTORE_RING_IDX cons, prod; ++ XENSTORE_RING_IDX cons, prod; /* offsets only */ + int to_read; + +- cons = intf->req_cons; +- prod = intf->req_prod; ++ cons = *(volatile uint32*)&intf->req_cons; ++ prod = *(volatile uint32*)&intf->req_prod; + xen_mb(); ++ cons = MASK_XENSTORE_IDX(cons); ++ prod = MASK_XENSTORE_IDX(prod); + if (prod == cons) + return 0; +- if (MASK_XENSTORE_IDX(prod) > MASK_XENSTORE_IDX(cons)) ++ if (prod > cons) + to_read = prod - cons; + else +- to_read = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons); ++ to_read = XENSTORE_RING_SIZE - cons; + if (to_read < len) + len = to_read; +- memcpy(buffer, intf->req + MASK_XENSTORE_IDX(cons), len); ++ memcpy(buffer, intf->req + cons, len); + xen_mb(); + intf->req_cons += len; + return len; +@@ -66,8 +68,8 @@ static int xs_ring_write(struct mmap_interface *interface, + XENSTORE_RING_IDX cons, prod; + int can_write; + +- cons = intf->rsp_cons; +- prod = intf->rsp_prod; ++ cons = *(volatile uint32*)&intf->rsp_cons; ++ prod = *(volatile uint32*)&intf->rsp_prod; + xen_mb(); + if ( (prod - cons) >= XENSTORE_RING_SIZE ) + return 0; |