diff --git a/xen.spec b/xen.spec index 92581d9..09c1c84 100644 --- a/xen.spec +++ b/xen.spec @@ -51,7 +51,7 @@ Summary: Xen is a virtual machine monitor Name: xen Version: 4.6.0 -Release: 4%{?dist} +Release: 5%{?dist} Group: Development/Libraries License: GPLv2+ and LGPLv2+ and BSD URL: http://xen.org/ @@ -107,6 +107,9 @@ Patch39: xsa156.patch Patch40: xsa162-qemut.patch Patch41: xsa162-qemuu.patch Patch42: xsa163.patch +Patch43: xsa158.patch +Patch44: xsa159.patch +Patch45: xsa160-4.6.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root @@ -315,6 +318,9 @@ manage Xen virtual machines. %patch40 -p1 %patch41 -p1 %patch42 -p1 +%patch43 -p1 +%patch44 -p1 +%patch45 -p1 # stubdom sources cp -v %{SOURCE10} %{SOURCE11} %{SOURCE12} %{SOURCE13} %{SOURCE14} %{SOURCE15} stubdom @@ -841,6 +847,12 @@ rm -rf %{buildroot} %endif %changelog +* Tue Dec 08 2015 Michael Young - 4.6.0-5 +- three security updates (#1289568) + long running memory operations on ARM [XSA-158, CVE-2015-8338] + XENMEM_exchange error handling issues [XSA-159, CVE-2015-8339, CVE-2015-8340] + libxl leak of pv kernel and initrd on error [XSA-160, CVE-2015-8341] + * Sun Dec 06 2015 Michael Young - 4.6.0-4 - heap buffer overflow vulnerability in pcnet emulator [XSA-162, CVE-2015-7504] (#1286544) diff --git a/xsa158.patch b/xsa158.patch new file mode 100644 index 0000000..751a74c --- /dev/null +++ b/xsa158.patch @@ -0,0 +1,217 @@ +memory: split and tighten maximum order permitted in memops + +Introduce and enforce separate limits for ordinary DomU, DomU with +pass-through device(s), control domain, and hardware domain. + +The DomU defaults were determined based on what so far was allowed by +multipage_allocation_permitted(). + +The x86 hwdom default was chosen based on linux-2.6.18-xen.hg c/s +1102:82782f1361a9 indicating 2Mb is not enough, plus some slack. + +The ARM hwdom default was chosen to allow 2Mb (order-9) mappings, plus +a little bit of slack. + +This is XSA-158. + +Reported-by: Julien Grall +Signed-off-by: Jan Beulich +Acked-by: Ian Campbell +--- +v2: Rename command line option to "memop-max-order". Clarify domain + kinds in command line option doc. Correct its syntax description. + +--- a/docs/misc/xen-command-line.markdown ++++ b/docs/misc/xen-command-line.markdown +@@ -1029,6 +1029,17 @@ with **crashinfo_maxaddr**. + Specify the threshold below which Xen will inform dom0 that the quantity of + free memory is getting low. Specifying `0` will disable this notification. + ++### memop-max-order ++> `= [][,[][,[][,]]]` ++ ++> x86 default: `9,18,12,12` ++> ARM default: `9,18,10,10` ++ ++Change the maximum order permitted for allocation (or allocation-like) ++requests issued by the various kinds of domains (in this order: ++ordinary DomU, control domain, hardware domain, and - when supported ++by the platform - DomU with pass-through device assigned). ++ + ### max\_cstate + > `= ` + +--- a/xen/common/memory.c ++++ b/xen/common/memory.c +@@ -43,6 +43,50 @@ struct memop_args { + int preempted; /* Was the hypercall preempted? */ + }; + ++#ifndef CONFIG_CTLDOM_MAX_ORDER ++#define CONFIG_CTLDOM_MAX_ORDER CONFIG_PAGEALLOC_MAX_ORDER ++#endif ++#ifndef CONFIG_PTDOM_MAX_ORDER ++#define CONFIG_PTDOM_MAX_ORDER CONFIG_HWDOM_MAX_ORDER ++#endif ++ ++static unsigned int __read_mostly domu_max_order = CONFIG_DOMU_MAX_ORDER; ++static unsigned int __read_mostly ctldom_max_order = CONFIG_CTLDOM_MAX_ORDER; ++static unsigned int __read_mostly hwdom_max_order = CONFIG_HWDOM_MAX_ORDER; ++#ifdef HAS_PASSTHROUGH ++static unsigned int __read_mostly ptdom_max_order = CONFIG_PTDOM_MAX_ORDER; ++#else ++# define ptdom_max_order domu_max_order ++#endif ++static void __init parse_max_order(const char *s) ++{ ++ if ( *s != ',' ) ++ domu_max_order = simple_strtoul(s, &s, 0); ++ if ( *s == ',' && *++s != ',' ) ++ ctldom_max_order = simple_strtoul(s, &s, 0); ++ if ( *s == ',' && *++s != ',' ) ++ hwdom_max_order = simple_strtoul(s, &s, 0); ++#ifdef HAS_PASSTHROUGH ++ if ( *s == ',' && *++s != ',' ) ++ ptdom_max_order = simple_strtoul(s, &s, 0); ++#endif ++} ++custom_param("memop-max-order", parse_max_order); ++ ++static unsigned int max_order(const struct domain *d) ++{ ++ unsigned int order = cache_flush_permitted(d) ? domu_max_order ++ : ptdom_max_order; ++ ++ if ( is_control_domain(d) && order < ctldom_max_order ) ++ order = ctldom_max_order; ++ ++ if ( is_hardware_domain(d) && order < hwdom_max_order ) ++ order = hwdom_max_order; ++ ++ return min(order, MAX_ORDER + 0U); ++} ++ + static void increase_reservation(struct memop_args *a) + { + struct page_info *page; +@@ -55,7 +99,7 @@ static void increase_reservation(struct + a->nr_extents-1) ) + return; + +- if ( !multipage_allocation_permitted(current->domain, a->extent_order) ) ++ if ( a->extent_order > max_order(current->domain) ) + return; + + for ( i = a->nr_done; i < a->nr_extents; i++ ) +@@ -100,8 +144,8 @@ static void populate_physmap(struct memo + a->nr_extents-1) ) + return; + +- if ( a->memflags & MEMF_populate_on_demand ? a->extent_order > MAX_ORDER : +- !multipage_allocation_permitted(current->domain, a->extent_order) ) ++ if ( a->extent_order > (a->memflags & MEMF_populate_on_demand ? MAX_ORDER : ++ max_order(current->domain)) ) + return; + + for ( i = a->nr_done; i < a->nr_extents; i++ ) +@@ -285,7 +329,7 @@ static void decrease_reservation(struct + + if ( !guest_handle_subrange_okay(a->extent_list, a->nr_done, + a->nr_extents-1) || +- a->extent_order > MAX_ORDER ) ++ a->extent_order > max_order(current->domain) ) + return; + + for ( i = a->nr_done; i < a->nr_extents; i++ ) +@@ -343,13 +387,17 @@ static long memory_exchange(XEN_GUEST_HA + if ( copy_from_guest(&exch, arg, 1) ) + return -EFAULT; + ++ if ( max(exch.in.extent_order, exch.out.extent_order) > ++ max_order(current->domain) ) ++ { ++ rc = -EPERM; ++ goto fail_early; ++ } ++ + /* Various sanity checks. */ + if ( (exch.nr_exchanged > exch.in.nr_extents) || + /* Input and output domain identifiers match? */ + (exch.in.domid != exch.out.domid) || +- /* Extent orders are sensible? */ +- (exch.in.extent_order > MAX_ORDER) || +- (exch.out.extent_order > MAX_ORDER) || + /* Sizes of input and output lists do not overflow a long? */ + ((~0UL >> exch.in.extent_order) < exch.in.nr_extents) || + ((~0UL >> exch.out.extent_order) < exch.out.nr_extents) || +@@ -368,16 +416,6 @@ static long memory_exchange(XEN_GUEST_HA + goto fail_early; + } + +- /* Only privileged guests can allocate multi-page contiguous extents. */ +- if ( !multipage_allocation_permitted(current->domain, +- exch.in.extent_order) || +- !multipage_allocation_permitted(current->domain, +- exch.out.extent_order) ) +- { +- rc = -EPERM; +- goto fail_early; +- } +- + if ( exch.in.extent_order <= exch.out.extent_order ) + { + in_chunk_order = exch.out.extent_order - exch.in.extent_order; +--- a/xen/include/asm-arm/config.h ++++ b/xen/include/asm-arm/config.h +@@ -39,6 +39,10 @@ + + #define CONFIG_IRQ_HAS_MULTIPLE_ACTION 1 + ++#define CONFIG_PAGEALLOC_MAX_ORDER 18 ++#define CONFIG_DOMU_MAX_ORDER 9 ++#define CONFIG_HWDOM_MAX_ORDER 10 ++ + #define OPT_CONSOLE_STR "dtuart" + + #ifdef MAX_PHYS_CPUS +--- a/xen/include/asm-arm/iocap.h ++++ b/xen/include/asm-arm/iocap.h +@@ -4,10 +4,6 @@ + #define cache_flush_permitted(d) \ + (!rangeset_is_empty((d)->iomem_caps)) + +-#define multipage_allocation_permitted(d, order) \ +- (((order) <= 9) || /* allow 2MB superpages */ \ +- !rangeset_is_empty((d)->iomem_caps)) +- + #endif + + /* +--- a/xen/include/asm-x86/config.h ++++ b/xen/include/asm-x86/config.h +@@ -28,9 +28,12 @@ + #define CONFIG_NUMA 1 + #define CONFIG_DISCONTIGMEM 1 + #define CONFIG_NUMA_EMU 1 +-#define CONFIG_PAGEALLOC_MAX_ORDER (2 * PAGETABLE_ORDER) + #define CONFIG_DOMAIN_PAGE 1 + ++#define CONFIG_PAGEALLOC_MAX_ORDER (2 * PAGETABLE_ORDER) ++#define CONFIG_DOMU_MAX_ORDER PAGETABLE_ORDER ++#define CONFIG_HWDOM_MAX_ORDER 12 ++ + /* Intel P4 currently has largest cache line (L2 line size is 128 bytes). */ + #define CONFIG_X86_L1_CACHE_SHIFT 7 + +--- a/xen/include/asm-x86/iocap.h ++++ b/xen/include/asm-x86/iocap.h +@@ -18,9 +18,4 @@ + (!rangeset_is_empty((d)->iomem_caps) || \ + !rangeset_is_empty((d)->arch.ioport_caps)) + +-#define multipage_allocation_permitted(d, order) \ +- (((order) <= 9) || /* allow 2MB superpages */ \ +- !rangeset_is_empty((d)->iomem_caps) || \ +- !rangeset_is_empty((d)->arch.ioport_caps)) +- + #endif /* __X86_IOCAP_H__ */ diff --git a/xsa159.patch b/xsa159.patch new file mode 100644 index 0000000..5e4e20c --- /dev/null +++ b/xsa159.patch @@ -0,0 +1,47 @@ +memory: fix XENMEM_exchange error handling + +assign_pages() can fail due to the domain getting killed in parallel, +which should not result in a hypervisor crash. + +Also delete a redundant put_gfn() - all relevant paths leading to the +"fail" label already do this (and there are also paths where it was +plain wrong). All of the put_gfn()-s got introduced by 51032ca058 +("Modify naming of queries into the p2m"), including the otherwise +unneeded initializer for k (with even a kind of misleading comment - +the compiler warning could actually have served as a hint that the use +is wrong). + +This is XSA-159. + +Reported-by: Julien Grall +Signed-off-by: Jan Beulich +Acked-by: Ian Campbell + +--- a/xen/common/memory.c ++++ b/xen/common/memory.c +@@ -334,7 +334,7 @@ static long memory_exchange(XEN_GUEST_HA + PAGE_LIST_HEAD(out_chunk_list); + unsigned long in_chunk_order, out_chunk_order; + xen_pfn_t gpfn, gmfn, mfn; +- unsigned long i, j, k = 0; /* gcc ... */ ++ unsigned long i, j, k; + unsigned int memflags = 0; + long rc = 0; + struct domain *d; +@@ -572,11 +572,12 @@ static long memory_exchange(XEN_GUEST_HA + fail: + /* Reassign any input pages we managed to steal. */ + while ( (page = page_list_remove_head(&in_chunk_list)) ) +- { +- put_gfn(d, gmfn + k--); + if ( assign_pages(d, page, 0, MEMF_no_refcount) ) +- BUG(); +- } ++ { ++ BUG_ON(!d->is_dying); ++ if ( test_and_clear_bit(_PGC_allocated, &page->count_info) ) ++ put_page(page); ++ } + + dying: + rcu_unlock_domain(d); diff --git a/xsa160-4.6.patch b/xsa160-4.6.patch new file mode 100644 index 0000000..36db34f --- /dev/null +++ b/xsa160-4.6.patch @@ -0,0 +1,69 @@ +From adcbd15b1aec8367f790774c998db199c9b577bf Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Wed, 18 Nov 2015 15:34:54 +0000 +Subject: [PATCH] libxl: Fix bootloader-related virtual memory leak on pv + build failure + +The bootloader may call libxl__file_reference_map(), which mmap's the +pv_kernel and pv_ramdisk into process memory. This was only unmapped, +however, on the success path of libxl__build_pv(). If there were a +failure anywhere between libxl_bootloader.c:parse_bootloader_result() +and the end of libxl__build_pv(), the calls to +libxl__file_reference_unmap() would be skipped, leaking the mapped +virtual memory. + +Ideally this would be fixed by adding the unmap calls to the +destruction path for libxl__domain_build_state. Unfortunately the +lifetime of the libxl__domain_build_state is opaque, and it doesn't +have a proper destruction path. But, the only thing in it that isn't +from the gc are these bootloader references, and they are only ever +set for one libxl__domain_build_state, the one which is +libxl__domain_create_state.build_state. + +So we can clean up in the exit path from libxl__domain_create_*, which +always comes through domcreate_complete. + +Remove the now-redundant unmaps in libxl__build_pv's success path. + +This is XSA-160. + +Signed-off-by: George Dunlap +Signed-off-by: Ian Jackson +Tested-by: George Dunlap +Acked-by: Ian Campbell +--- + tools/libxl/libxl_create.c | 3 +++ + tools/libxl/libxl_dom.c | 3 --- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c +index f5771da..278b9ed 100644 +--- a/tools/libxl/libxl_create.c ++++ b/tools/libxl/libxl_create.c +@@ -1484,6 +1484,9 @@ static void domcreate_complete(libxl__egc *egc, + libxl_domain_config *const d_config = dcs->guest_config; + libxl_domain_config *d_config_saved = &dcs->guest_config_saved; + ++ libxl__file_reference_unmap(&dcs->build_state.pv_kernel); ++ libxl__file_reference_unmap(&dcs->build_state.pv_ramdisk); ++ + if (!rc && d_config->b_info.exec_ssidref) + rc = xc_flask_relabel_domain(CTX->xch, dcs->guest_domid, d_config->b_info.exec_ssidref); + +diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c +index 8019f4e..2da3ac4 100644 +--- a/tools/libxl/libxl_dom.c ++++ b/tools/libxl/libxl_dom.c +@@ -750,9 +750,6 @@ int libxl__build_pv(libxl__gc *gc, uint32_t domid, + state->store_mfn = xc_dom_p2m_host(dom, dom->xenstore_pfn); + } + +- libxl__file_reference_unmap(&state->pv_kernel); +- libxl__file_reference_unmap(&state->pv_ramdisk); +- + ret = 0; + out: + xc_dom_release(dom); +-- +1.7.10.4 +