From: Greg Kroah-Hartman Date: Thu, 20 Feb 2014 20:13:20 +0000 (-0800) Subject: 3.10-stable patches X-Git-Tag: v3.4.82~46 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f1d63fd6d081bbf40378efff9d3c79e1138013ea;p=thirdparty%2Fkernel%2Fstable-queue.git 3.10-stable patches added patches: xen-blkfront-handle-backend-closed-without-closing.patch xen-fix-possible-user-space-selector-corruption.patch xen-p2m-check-mfn-is-in-range-before-using-the-m2p-table.patch --- diff --git a/queue-3.10/series b/queue-3.10/series new file mode 100644 index 00000000000..a263391703f --- /dev/null +++ b/queue-3.10/series @@ -0,0 +1,3 @@ +xen-blkfront-handle-backend-closed-without-closing.patch +xen-p2m-check-mfn-is-in-range-before-using-the-m2p-table.patch +xen-fix-possible-user-space-selector-corruption.patch diff --git a/queue-3.10/xen-blkfront-handle-backend-closed-without-closing.patch b/queue-3.10/xen-blkfront-handle-backend-closed-without-closing.patch new file mode 100644 index 00000000000..34805947ecf --- /dev/null +++ b/queue-3.10/xen-blkfront-handle-backend-closed-without-closing.patch @@ -0,0 +1,44 @@ +From 3661371701e714f0cea4120f6a365340858fb4e4 Mon Sep 17 00:00:00 2001 +From: David Vrabel +Date: Tue, 4 Feb 2014 18:53:56 +0000 +Subject: xen-blkfront: handle backend CLOSED without CLOSING + +From: David Vrabel + +commit 3661371701e714f0cea4120f6a365340858fb4e4 upstream. + +Backend drivers shouldn't transistion to CLOSED unless the frontend is +CLOSED. If a backend does transition to CLOSED too soon then the +frontend may not see the CLOSING state and will not properly shutdown. + +So, treat an unexpected backend CLOSED state the same as CLOSING. + +Signed-off-by: David Vrabel +Acked-by: Konrad Rzeszutek Wilk +Signed-off-by: Konrad Rzeszutek Wilk +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/xen-blkfront.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/block/xen-blkfront.c ++++ b/drivers/block/xen-blkfront.c +@@ -1518,13 +1518,16 @@ static void blkback_changed(struct xenbu + case XenbusStateReconfiguring: + case XenbusStateReconfigured: + case XenbusStateUnknown: +- case XenbusStateClosed: + break; + + case XenbusStateConnected: + blkfront_connect(info); + break; + ++ case XenbusStateClosed: ++ if (dev->state == XenbusStateClosed) ++ break; ++ /* Missed the backend's Closing state -- fallthrough */ + case XenbusStateClosing: + blkfront_closing(info); + break; diff --git a/queue-3.10/xen-fix-possible-user-space-selector-corruption.patch b/queue-3.10/xen-fix-possible-user-space-selector-corruption.patch new file mode 100644 index 00000000000..5e5c475b5db --- /dev/null +++ b/queue-3.10/xen-fix-possible-user-space-selector-corruption.patch @@ -0,0 +1,62 @@ +From 7cde9b27e7b3a2e09d647bb4f6d94e842698d2d5 Mon Sep 17 00:00:00 2001 +From: Frediano Ziglio +Date: Thu, 10 Oct 2013 14:39:37 +0000 +Subject: xen: Fix possible user space selector corruption + +From: Frediano Ziglio + +commit 7cde9b27e7b3a2e09d647bb4f6d94e842698d2d5 upstream. + +Due to the way kernel is initialized under Xen is possible that the +ring1 selector used by the kernel for the boot cpu end up to be copied +to userspace leading to segmentation fault in the userspace. + +Xen code in the kernel initialize no-boot cpus with correct selectors (ds +and es set to __USER_DS) but the boot one keep the ring1 (passed by Xen). +On task context switch (switch_to) we assume that ds, es and cs already +point to __USER_DS and __KERNEL_CSso these selector are not changed. + +If processor is an Intel that support sysenter instruction sysenter/sysexit +is used so ds and es are not restored switching back from kernel to +userspace. In the case the selectors point to a ring1 instead of __USER_DS +the userspace code will crash on first memory access attempt (to be +precise Xen on the emulated iret used to do sysexit will detect and set ds +and es to zero which lead to GPF anyway). + +Now if an userspace process call kernel using sysenter and get rescheduled +(for me it happen on a specific init calling wait4) could happen that the +ring1 selector is set to ds and es. + +This is quite hard to detect cause after a while these selectors are fixed +(__USER_DS seems sticky). + +Bisecting the code commit 7076aada1040de4ed79a5977dbabdb5e5ea5e249 appears +to be the first one that have this issue. + +Signed-off-by: Frediano Ziglio +Signed-off-by: Stefano Stabellini +Reviewed-by: Andrew Cooper +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/xen/smp.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/arch/x86/xen/smp.c ++++ b/arch/x86/xen/smp.c +@@ -245,6 +245,15 @@ static void __init xen_smp_prepare_boot_ + old memory can be recycled */ + make_lowmem_page_readwrite(xen_initial_gdt); + ++#ifdef CONFIG_X86_32 ++ /* ++ * Xen starts us with XEN_FLAT_RING1_DS, but linux code ++ * expects __USER_DS ++ */ ++ loadsegment(ds, __USER_DS); ++ loadsegment(es, __USER_DS); ++#endif ++ + xen_filter_cpu_maps(); + xen_setup_vcpu_info_placement(); + } diff --git a/queue-3.10/xen-p2m-check-mfn-is-in-range-before-using-the-m2p-table.patch b/queue-3.10/xen-p2m-check-mfn-is-in-range-before-using-the-m2p-table.patch new file mode 100644 index 00000000000..8becb0da5c5 --- /dev/null +++ b/queue-3.10/xen-p2m-check-mfn-is-in-range-before-using-the-m2p-table.patch @@ -0,0 +1,155 @@ +From 0160676bba69523e8b0ac83f306cce7d342ed7c8 Mon Sep 17 00:00:00 2001 +From: David Vrabel +Date: Fri, 13 Sep 2013 15:13:30 +0100 +Subject: xen/p2m: check MFN is in range before using the m2p table + +From: David Vrabel + +commit 0160676bba69523e8b0ac83f306cce7d342ed7c8 upstream. + +On hosts with more than 168 GB of memory, a 32-bit guest may attempt +to grant map an MFN that is error cannot lookup in its mapping of the +m2p table. There is an m2p lookup as part of m2p_add_override() and +m2p_remove_override(). The lookup falls off the end of the mapped +portion of the m2p and (because the mapping is at the highest virtual +address) wraps around and the lookup causes a fault on what appears to +be a user space address. + +do_page_fault() (thinking it's a fault to a userspace address), tries +to lock mm->mmap_sem. If the gntdev device is used for the grant map, +m2p_add_override() is called from from gnttab_mmap() with mm->mmap_sem +already locked. do_page_fault() then deadlocks. + +The deadlock would most commonly occur when a 64-bit guest is started +and xenconsoled attempts to grant map its console ring. + +Introduce mfn_to_pfn_no_overrides() which checks the MFN is within the +mapped portion of the m2p table before accessing the table and use +this in m2p_add_override(), m2p_remove_override(), and mfn_to_pfn() +(which already had the correct range check). + +All faults caused by accessing the non-existant parts of the m2p are +thus within the kernel address space and exception_fixup() is called +without trying to lock mm->mmap_sem. + +This means that for MFNs that are outside the mapped range of the m2p +then mfn_to_pfn() will always look in the m2p overrides. This is +correct because it must be a foreign MFN (and the PFN in the m2p in +this case is only relevant for the other domain). + +v3: check for auto_translated_physmap in mfn_to_pfn_no_overrides() +v2: in mfn_to_pfn() look in m2p_overrides if the MFN is out of + range as it's probably foreign. + +Signed-off-by: David Vrabel +Cc: Stefano Stabellini +Cc: Jan Beulich +Signed-off-by: Konrad Rzeszutek Wilk +Acked-by: Stefano Stabellini +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/include/asm/xen/page.h | 31 ++++++++++++++++++++----------- + arch/x86/xen/p2m.c | 10 ++++------ + 2 files changed, 24 insertions(+), 17 deletions(-) + +--- a/arch/x86/include/asm/xen/page.h ++++ b/arch/x86/include/asm/xen/page.h +@@ -79,30 +79,38 @@ static inline int phys_to_machine_mappin + return get_phys_to_machine(pfn) != INVALID_P2M_ENTRY; + } + +-static inline unsigned long mfn_to_pfn(unsigned long mfn) ++static inline unsigned long mfn_to_pfn_no_overrides(unsigned long mfn) + { + unsigned long pfn; +- int ret = 0; ++ int ret; + + if (xen_feature(XENFEAT_auto_translated_physmap)) + return mfn; + +- if (unlikely(mfn >= machine_to_phys_nr)) { +- pfn = ~0; +- goto try_override; +- } +- pfn = 0; ++ if (unlikely(mfn >= machine_to_phys_nr)) ++ return ~0; ++ + /* + * The array access can fail (e.g., device space beyond end of RAM). + * In such cases it doesn't matter what we return (we return garbage), + * but we must handle the fault without crashing! + */ + ret = __get_user(pfn, &machine_to_phys_mapping[mfn]); +-try_override: +- /* ret might be < 0 if there are no entries in the m2p for mfn */ + if (ret < 0) +- pfn = ~0; +- else if (get_phys_to_machine(pfn) != mfn) ++ return ~0; ++ ++ return pfn; ++} ++ ++static inline unsigned long mfn_to_pfn(unsigned long mfn) ++{ ++ unsigned long pfn; ++ ++ if (xen_feature(XENFEAT_auto_translated_physmap)) ++ return mfn; ++ ++ pfn = mfn_to_pfn_no_overrides(mfn); ++ if (get_phys_to_machine(pfn) != mfn) { + /* + * If this appears to be a foreign mfn (because the pfn + * doesn't map back to the mfn), then check the local override +@@ -111,6 +119,7 @@ try_override: + * m2p_find_override_pfn returns ~0 if it doesn't find anything. + */ + pfn = m2p_find_override_pfn(mfn, ~0); ++ } + + /* + * pfn is ~0 if there are no entries in the m2p for mfn or if the +--- a/arch/x86/xen/p2m.c ++++ b/arch/x86/xen/p2m.c +@@ -878,7 +878,6 @@ int m2p_add_override(unsigned long mfn, + unsigned long uninitialized_var(address); + unsigned level; + pte_t *ptep = NULL; +- int ret = 0; + + pfn = page_to_pfn(page); + if (!PageHighMem(page)) { +@@ -925,8 +924,8 @@ int m2p_add_override(unsigned long mfn, + * frontend pages while they are being shared with the backend, + * because mfn_to_pfn (that ends up being called by GUPF) will + * return the backend pfn rather than the frontend pfn. */ +- ret = __get_user(pfn, &machine_to_phys_mapping[mfn]); +- if (ret == 0 && get_phys_to_machine(pfn) == mfn) ++ pfn = mfn_to_pfn_no_overrides(mfn); ++ if (get_phys_to_machine(pfn) == mfn) + set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)); + + return 0; +@@ -941,7 +940,6 @@ int m2p_remove_override(struct page *pag + unsigned long uninitialized_var(address); + unsigned level; + pte_t *ptep = NULL; +- int ret = 0; + + pfn = page_to_pfn(page); + mfn = get_phys_to_machine(pfn); +@@ -1019,8 +1017,8 @@ int m2p_remove_override(struct page *pag + * the original pfn causes mfn_to_pfn(mfn) to return the frontend + * pfn again. */ + mfn &= ~FOREIGN_FRAME_BIT; +- ret = __get_user(pfn, &machine_to_phys_mapping[mfn]); +- if (ret == 0 && get_phys_to_machine(pfn) == FOREIGN_FRAME(mfn) && ++ pfn = mfn_to_pfn_no_overrides(mfn); ++ if (get_phys_to_machine(pfn) == FOREIGN_FRAME(mfn) && + m2p_find_override(mfn) == NULL) + set_phys_to_machine(pfn, mfn); +