Mail archive
alpine-aports

[alpine-aports] [PATCH] main/xen: security fixes for XSA-252, XSA-255, and XSA-256

From: Daniel Sabogal <dsabogalcc_at_gmail.com>
Date: Fri, 16 Mar 2018 11:31:18 -0400

CVE-2018-7540 XSA-252
CVE-2018-7541 XSA-255
CVE-2018-7542 XSA-256

fixes #8613
---
 main/xen/APKBUILD       |  14 +++-
 main/xen/xsa252.patch   |  27 ++++++++
 main/xen/xsa255-1.patch | 133 ++++++++++++++++++++++++++++++++++++++
 main/xen/xsa255-2.patch | 167 ++++++++++++++++++++++++++++++++++++++++++++++++
 main/xen/xsa256.patch   |  40 ++++++++++++
 5 files changed, 380 insertions(+), 1 deletion(-)
 create mode 100644 main/xen/xsa252.patch
 create mode 100644 main/xen/xsa255-1.patch
 create mode 100644 main/xen/xsa255-2.patch
 create mode 100644 main/xen/xsa256.patch
diff --git a/main/xen/APKBUILD b/main/xen/APKBUILD
index f48891c864..c2887566e1 100644
--- a/main/xen/APKBUILD
+++ b/main/xen/APKBUILD
_at_@ -3,7 +3,7 @@
 # Maintainer: William Pitcock <nenolod_at_dereferenced.org>
 pkgname=xen
 pkgver=4.10.0
-pkgrel=1
+pkgrel=2
 pkgdesc="Xen hypervisor"
 url="http://www.xen.org/"
 arch="x86_64 armhf aarch64"
_at_@ -108,6 +108,10 @@ options="!strip"
 #     - XSA-251
 #     - XSA-253
 #     - XSA-254
+#   4.10.0-r2:
+#     - CVE-2018-7540 XSA-252
+#     - CVE-2018-7541 XSA-255
+#     - CVE-2018-7542 XSA-256
 
 case "$CARCH" in
 x86*)
_at_@ -155,8 +159,12 @@ source="https://downloads.xenproject.org/release/$pkgname/$pkgver/$pkgname-$pkgv
 	http://xenbits.xen.org/xen-extfiles/zlib-$_ZLIB_VERSION.tar.gz
 	http://xenbits.xen.org/xen-extfiles/ipxe-git-$_IPXE_GIT_TAG.tar.gz
 
+	xsa252.patch
 	xsa253-4.10.patch
 	xsa254-4.10.patch
+	xsa255-1.patch
+	xsa255-2.patch
+	xsa256.patch
 
 	qemu-xen_paths.patch
 
_at_@ -416,8 +424,12 @@ c2bc9ffc8583aeae71cee9ddcc4418969768d4e3764d47307da54f93981c0109fb07d84b061b3a36
 4928b5b82f57645be9408362706ff2c4d9baa635b21b0d41b1c82930e8c60a759b1ea4fa74d7e6c7cae1b7692d006aa5cb72df0c3b88bf049779aa2b566f9d35  tpm_emulator-0.7.4.tar.gz
 021b958fcd0d346c4ba761bcf0cc40f3522de6186cf5a0a6ea34a70504ce9622b1c2626fce40675bc8282cf5f5ade18473656abc38050f72f5d6480507a2106e  zlib-1.2.3.tar.gz
 bbcce5e55040e7e29adebd4a5253a046016a6e2e7ff34cf801a42d147e1ec1af57e0297318249bfa9c5bbeac969fe4b37c18cbf845a80b2136d65387a4fc31da  ipxe-git-356f6c1b64d7a97746d1816cef8ca22bdd8d0b5d.tar.gz
+63fd6cee56ef04506efd6bf632998dc90514ff967e9435514a5ba8d2c5781735f986241344a479b6f44df9c6e6a278a165ba14834b0b3236064e24f71cd600f1  xsa252.patch
 58f288fb3087ecdd42075031b5604a493adef0754f68d596dce8576fbc46bfe8b1bf3dc429269cab3797b6f193036bdafeb32cf2c7cca34d9c89d5fe95a0453c  xsa253-4.10.patch
 f15350c0b44d3a6d5a3056dfac81d25f2af047135c528f6258f3d42ef26e6d87511d8e148a63e8d7d88108e07dc5b3551ed54c915be6dc3fe3f978ab72094321  xsa254-4.10.patch
+d16ead93486beee767c3c80d11981d940dfce55d9aabfe7adee480d02f575a2df074bb83a1e62e455ac754f6d8f3fb83abe7139b93b94b77233c2918b46dc2e2  xsa255-1.patch
+2f0719fbbde261a51e1ec66eb677fb2b17c94e0631d583c0a99357b7c2dfb2c695b6970ebbe8e05f68154344af74fa31e8b47b0d25c778b3aef1b284101ae528  xsa255-2.patch
+3bd2697a8ad66197264af8a713bf97152ed414c4b11910cc986c6adaa85bd86b4d35319675799edccf04aaff9ae48a58ca5c438cb6b5b95f60fffbfeec5e4faf  xsa256.patch
 1936ab39a1867957fa640eb81c4070214ca4856a2743ba7e49c0cd017917071a9680d015f002c57fa7b9600dbadd29dcea5887f50e6c133305df2669a7a933f3  qemu-xen_paths.patch
 f095ea373f36381491ad36f0662fb4f53665031973721256b23166e596318581da7cbb0146d0beb2446729adfdb321e01468e377793f6563a67d68b8b0f7ffe3  hotplug-vif-vtrill.patch
 77b08e9655e091b0352e4630d520b54c6ca6d659d1d38fbb4b3bfc9ff3e66db433a2e194ead32bb10ff962c382d800a670e82b7a62835b238e294b22808290ea  musl-hvmloader-fix-stdint.patch
diff --git a/main/xen/xsa252.patch b/main/xen/xsa252.patch
new file mode 100644
index 0000000000..8615928142
--- /dev/null
+++ b/main/xen/xsa252.patch
_at_@ -0,0 +1,27 @@
+From: Jan Beulich <jbeulich_at_suse.com>
+Subject: memory: don't implicitly unpin for decrease-reservation
+
+It very likely was a mistake (copy-and-paste from domain cleanup code)
+to implicitly unpin here: The caller should really unpin itself before
+(or after, if they so wish) requesting the page to be removed.
+
+This is XSA-252.
+
+Reported-by: Jann Horn <jannh_at_google.com>
+Signed-off-by: Jan Beulich <jbeulich_at_suse.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3_at_citrix.com>
+
+--- a/xen/common/memory.c
++++ b/xen/common/memory.c
+_at_@ -357,11 +357,6 @@ int guest_remove_page(struct domain *d,
+ 
+     rc = guest_physmap_remove_page(d, _gfn(gmfn), mfn, 0);
+ 
+-#ifdef _PGT_pinned
+-    if ( !rc && test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
+-        put_page_and_type(page);
+-#endif
+-
+     /*
+      * With the lack of an IOMMU on some platforms, domains with DMA-capable
+      * device must retrieve the same pfn when the hypercall populate_physmap
diff --git a/main/xen/xsa255-1.patch b/main/xen/xsa255-1.patch
new file mode 100644
index 0000000000..f8bba9e516
--- /dev/null
+++ b/main/xen/xsa255-1.patch
_at_@ -0,0 +1,133 @@
+From: Jan Beulich <jbeulich_at_suse.com>
+Subject: gnttab/ARM: don't corrupt shared GFN array
+
+... by writing status GFNs to it. Introduce a second array instead.
+Also implement gnttab_status_gmfn() properly now that the information is
+suitably being tracked.
+
+While touching it anyway, remove a misguided (but luckily benign) upper
+bound check from gnttab_shared_gmfn(): We should never access beyond the
+bounds of that array.
+
+This is part of XSA-255.
+
+Signed-off-by: Jan Beulich <jbeulich_at_suse.com>
+Reviewed-by: Stefano Stabellini <sstabellini_at_kernel.org>
+Reviewed-by: Andrew Cooper <andrew.cooper3_at_citrix.com>
+---
+v3: Don't init the ARM GFN arrays to zero anymore, use INVALID_GFN.
+v2: New.
+
+--- a/xen/common/grant_table.c
++++ b/xen/common/grant_table.c
+_at_@ -3775,6 +3775,7 @@ int gnttab_map_frame(struct domain *d, u
+ {
+     int rc = 0;
+     struct grant_table *gt = d->grant_table;
++    bool status = false;
+ 
+     grant_write_lock(gt);
+ 
+_at_@ -3785,6 +3786,7 @@ int gnttab_map_frame(struct domain *d, u
+          (idx & XENMAPIDX_grant_table_status) )
+     {
+         idx &= ~XENMAPIDX_grant_table_status;
++        status = true;
+         if ( idx < nr_status_frames(gt) )
+             *mfn = _mfn(virt_to_mfn(gt->status[idx]));
+         else
+_at_@ -3802,7 +3804,7 @@ int gnttab_map_frame(struct domain *d, u
+     }
+ 
+     if ( !rc )
+-        gnttab_set_frame_gfn(gt, idx, gfn);
++        gnttab_set_frame_gfn(gt, status, idx, gfn);
+ 
+     grant_write_unlock(gt);
+ 
+--- a/xen/include/asm-arm/grant_table.h
++++ b/xen/include/asm-arm/grant_table.h
+_at_@ -9,7 +9,8 @@
+ #define INITIAL_NR_GRANT_FRAMES 1U
+ 
+ struct grant_table_arch {
+-    gfn_t *gfn;
++    gfn_t *shared_gfn;
++    gfn_t *status_gfn;
+ };
+ 
+ void gnttab_clear_flag(unsigned long nr, uint16_t *addr);
+_at_@ -21,7 +22,6 @@ int replace_grant_host_mapping(unsigned
+         unsigned long new_gpaddr, unsigned int flags);
+ void gnttab_mark_dirty(struct domain *d, unsigned long l);
+ #define gnttab_create_status_page(d, t, i) do {} while (0)
+-#define gnttab_status_gmfn(d, t, i) (0)
+ #define gnttab_release_host_mappings(domain) 1
+ static inline int replace_grant_supported(void)
+ {
+_at_@ -42,19 +42,35 @@ static inline unsigned int gnttab_dom0_m
+ 
+ #define gnttab_init_arch(gt)                                             \
+ ({                                                                       \
+-    (gt)->arch.gfn = xzalloc_array(gfn_t, (gt)->max_grant_frames);       \
+-    ( (gt)->arch.gfn ? 0 : -ENOMEM );                                    \
++    unsigned int ngf_ = (gt)->max_grant_frames;                          \
++    unsigned int nsf_ = grant_to_status_frames(ngf_);                    \
++                                                                         \
++    (gt)->arch.shared_gfn = xmalloc_array(gfn_t, ngf_);                  \
++    (gt)->arch.status_gfn = xmalloc_array(gfn_t, nsf_);                  \
++    if ( (gt)->arch.shared_gfn && (gt)->arch.status_gfn )                \
++    {                                                                    \
++        while ( ngf_-- )                                                 \
++            (gt)->arch.shared_gfn[ngf_] = INVALID_GFN;                   \
++        while ( nsf_-- )                                                 \
++            (gt)->arch.status_gfn[nsf_] = INVALID_GFN;                   \
++    }                                                                    \
++    else                                                                 \
++        gnttab_destroy_arch(gt);                                         \
++    (gt)->arch.shared_gfn ? 0 : -ENOMEM;                                 \
+ })
+ 
+ #define gnttab_destroy_arch(gt)                                          \
+     do {                                                                 \
+-        xfree((gt)->arch.gfn);                                           \
+-        (gt)->arch.gfn = NULL;                                           \
++        xfree((gt)->arch.shared_gfn);                                    \
++        (gt)->arch.shared_gfn = NULL;                                    \
++        xfree((gt)->arch.status_gfn);                                    \
++        (gt)->arch.status_gfn = NULL;                                    \
+     } while ( 0 )
+ 
+-#define gnttab_set_frame_gfn(gt, idx, gfn)                               \
++#define gnttab_set_frame_gfn(gt, st, idx, gfn)                           \
+     do {                                                                 \
+-        (gt)->arch.gfn[idx] = gfn;                                       \
++        ((st) ? (gt)->arch.status_gfn : (gt)->arch.shared_gfn)[idx] =    \
++            (gfn);                                                       \
+     } while ( 0 )
+ 
+ #define gnttab_create_shared_page(d, t, i)                               \
+_at_@ -65,8 +81,10 @@ static inline unsigned int gnttab_dom0_m
+     } while ( 0 )
+ 
+ #define gnttab_shared_gmfn(d, t, i)                                      \
+-    ( ((i >= nr_grant_frames(t)) &&                                      \
+-       (i < (t)->max_grant_frames))? 0 : gfn_x((t)->arch.gfn[i]))
++    gfn_x(((i) >= nr_grant_frames(t)) ? INVALID_GFN : (t)->arch.shared_gfn[i])
++
++#define gnttab_status_gmfn(d, t, i)                                      \
++    gfn_x(((i) >= nr_status_frames(t)) ? INVALID_GFN : (t)->arch.status_gfn[i])
+ 
+ #define gnttab_need_iommu_mapping(d)                    \
+     (is_domain_direct_mapped(d) && need_iommu(d))
+--- a/xen/include/asm-x86/grant_table.h
++++ b/xen/include/asm-x86/grant_table.h
+_at_@ -46,7 +46,7 @@ static inline unsigned int gnttab_dom0_m
+ 
+ #define gnttab_init_arch(gt) 0
+ #define gnttab_destroy_arch(gt) do {} while ( 0 )
+-#define gnttab_set_frame_gfn(gt, idx, gfn) do {} while ( 0 )
++#define gnttab_set_frame_gfn(gt, st, idx, gfn) do {} while ( 0 )
+ 
+ #define gnttab_create_shared_page(d, t, i)                               \
+     do {                                                                 \
diff --git a/main/xen/xsa255-2.patch b/main/xen/xsa255-2.patch
new file mode 100644
index 0000000000..402b6efe98
--- /dev/null
+++ b/main/xen/xsa255-2.patch
_at_@ -0,0 +1,167 @@
+From: Jan Beulich <jbeulich_at_suse.com>
+Subject: gnttab: don't blindly free status pages upon version change
+
+There may still be active mappings, which would trigger the respective
+BUG_ON(). Split the loop into one dealing with the page attributes and
+the second (when the first fully passed) freeing the pages. Return an
+error if any pages still have pending references.
+
+This is part of XSA-255.
+
+Signed-off-by: Jan Beulich <jbeulich_at_suse.com>
+Reviewed-by: Stefano Stabellini <sstabellini_at_kernel.org>
+Reviewed-by: Andrew Cooper <andrew.cooper3_at_citrix.com>
+---
+v4: Add gprintk(XENLOG_ERR, ...) to domain_crash() invocations.
+v3: Call guest_physmap_remove_page() from gnttab_map_frame(), making the
+    code unconditional at the same time. Re-base over changes to first
+    patch.
+v2: Also deal with translated guests.
+
+--- a/xen/common/grant_table.c
++++ b/xen/common/grant_table.c
+_at_@ -1636,23 +1636,74 @@ status_alloc_failed:
+     return -ENOMEM;
+ }
+ 
+-static void
++static int
+ gnttab_unpopulate_status_frames(struct domain *d, struct grant_table *gt)
+ {
+-    int i;
++    unsigned int i;
+ 
+     for ( i = 0; i < nr_status_frames(gt); i++ )
+     {
+         struct page_info *pg = virt_to_page(gt->status[i]);
++        gfn_t gfn = gnttab_get_frame_gfn(gt, true, i);
++
++        /*
++         * For translated domains, recovering from failure after partial
++         * changes were made is more complicated than it seems worth
++         * implementing at this time. Hence respective error paths below
++         * crash the domain in such a case.
++         */
++        if ( paging_mode_translate(d) )
++        {
++            int rc = gfn_eq(gfn, INVALID_GFN)
++                     ? 0
++                     : guest_physmap_remove_page(d, gfn,
++                                                 _mfn(page_to_mfn(pg)), 0);
++
++            if ( rc )
++            {
++                gprintk(XENLOG_ERR,
++                        "Could not remove status frame %u (GFN %#lx) from P2M\n",
++                        i, gfn_x(gfn));
++                domain_crash(d);
++                return rc;
++            }
++            gnttab_set_frame_gfn(gt, true, i, INVALID_GFN);
++        }
+ 
+         BUG_ON(page_get_owner(pg) != d);
+         if ( test_and_clear_bit(_PGC_allocated, &pg->count_info) )
+             put_page(pg);
+-        BUG_ON(pg->count_info & ~PGC_xen_heap);
++
++        if ( pg->count_info & ~PGC_xen_heap )
++        {
++            if ( paging_mode_translate(d) )
++            {
++                gprintk(XENLOG_ERR,
++                        "Wrong page state %#lx of status frame %u (GFN %#lx)\n",
++                        pg->count_info, i, gfn_x(gfn));
++                domain_crash(d);
++            }
++            else
++            {
++                if ( get_page(pg, d) )
++                    set_bit(_PGC_allocated, &pg->count_info);
++                while ( i-- )
++                    gnttab_create_status_page(d, gt, i);
++            }
++            return -EBUSY;
++        }
++
++        page_set_owner(pg, NULL);
++    }
++
++    for ( i = 0; i < nr_status_frames(gt); i++ )
++    {
+         free_xenheap_page(gt->status[i]);
+         gt->status[i] = NULL;
+     }
+     gt->nr_status_frames = 0;
++
++    return 0;
+ }
+ 
+ /*
+_at_@ -2962,8 +3013,9 @@ gnttab_set_version(XEN_GUEST_HANDLE_PARA
+         break;
+     }
+ 
+-    if ( op.version < 2 && gt->gt_version == 2 )
+-        gnttab_unpopulate_status_frames(currd, gt);
++    if ( op.version < 2 && gt->gt_version == 2 &&
++         (res = gnttab_unpopulate_status_frames(currd, gt)) != 0 )
++        goto out_unlock;
+ 
+     /* Make sure there's no crud left over from the old version. */
+     for ( i = 0; i < nr_grant_frames(gt); i++ )
+_at_@ -3803,6 +3855,11 @@ int gnttab_map_frame(struct domain *d, u
+             rc = -EINVAL;
+     }
+ 
++    if ( !rc && paging_mode_translate(d) &&
++         !gfn_eq(gnttab_get_frame_gfn(gt, status, idx), INVALID_GFN) )
++        rc = guest_physmap_remove_page(d, gnttab_get_frame_gfn(gt, status, idx),
++                                       *mfn, 0);
++
+     if ( !rc )
+         gnttab_set_frame_gfn(gt, status, idx, gfn);
+ 
+--- a/xen/include/asm-arm/grant_table.h
++++ b/xen/include/asm-arm/grant_table.h
+_at_@ -73,6 +73,11 @@ static inline unsigned int gnttab_dom0_m
+             (gfn);                                                       \
+     } while ( 0 )
+ 
++#define gnttab_get_frame_gfn(gt, st, idx) ({                             \
++   _gfn((st) ? gnttab_status_gmfn(NULL, gt, idx)                         \
++             : gnttab_shared_gmfn(NULL, gt, idx));                       \
++})
++
+ #define gnttab_create_shared_page(d, t, i)                               \
+     do {                                                                 \
+         share_xen_page_with_guest(                                       \
+--- a/xen/include/asm-x86/grant_table.h
++++ b/xen/include/asm-x86/grant_table.h
+_at_@ -47,6 +47,12 @@ static inline unsigned int gnttab_dom0_m
+ #define gnttab_init_arch(gt) 0
+ #define gnttab_destroy_arch(gt) do {} while ( 0 )
+ #define gnttab_set_frame_gfn(gt, st, idx, gfn) do {} while ( 0 )
++#define gnttab_get_frame_gfn(gt, st, idx) ({                             \
++    unsigned long mfn_ = (st) ? gnttab_status_mfn(gt, idx)               \
++                              : gnttab_shared_mfn(gt, idx);              \
++    unsigned long gpfn_ = get_gpfn_from_mfn(mfn_);                       \
++    VALID_M2P(gpfn_) ? _gfn(gpfn_) : INVALID_GFN;                        \
++})
+ 
+ #define gnttab_create_shared_page(d, t, i)                               \
+     do {                                                                 \
+_at_@ -63,11 +69,11 @@ static inline unsigned int gnttab_dom0_m
+     } while ( 0 )
+ 
+ 
+-#define gnttab_shared_mfn(d, t, i)                      \
++#define gnttab_shared_mfn(t, i)                         \
+     ((virt_to_maddr((t)->shared_raw[i]) >> PAGE_SHIFT))
+ 
+ #define gnttab_shared_gmfn(d, t, i)                     \
+-    (mfn_to_gmfn(d, gnttab_shared_mfn(d, t, i)))
++    (mfn_to_gmfn(d, gnttab_shared_mfn(t, i)))
+ 
+ 
+ #define gnttab_status_mfn(t, i)                         \
diff --git a/main/xen/xsa256.patch b/main/xen/xsa256.patch
new file mode 100644
index 0000000000..50ff24e17b
--- /dev/null
+++ b/main/xen/xsa256.patch
_at_@ -0,0 +1,40 @@
+From: Andrew Cooper <andrew.cooper3_at_citrix.com>
+Subject: x86/hvm: Disallow the creation of HVM domains without Local APIC emulation
+
+There are multiple problems, not necesserily limited to:
+
+ * Guests which configure event channels via hvmop_set_evtchn_upcall_vector(),
+   or which hit %cr8 emulation will cause Xen to fall over a NULL vlapic->regs
+   pointer.
+
+ * On Intel hardware, disabling the TPR_SHADOW execution control without
+   reenabling CR8_{LOAD,STORE} interception means that the guests %cr8
+   accesses interact with the real TPR.  Amongst other things, setting the
+   real TPR to 0xf blocks even IPIs from interrupting this CPU.
+
+ * On hardware which sets up the use of Interrupt Posting, including
+   IOMMU-Posting, guests run without the appropriate non-root configuration,
+   which at a minimum will result in dropped interrupts.
+
+Whether no-LAPIC mode is of any use at all remains to be seen.
+
+This is XSA-256.
+
+Reported-by: Ian Jackson <ian.jackson_at_eu.citrix.com>
+Reviewed-by: Roger Pau Monné <roger.pau_at_citrix.com>
+Signed-off-by: Andrew Cooper <andrew.cooper3_at_citrix.com>
+Reviewed-by: Jan Beulich <jbeulich_at_suse.com>
+
+diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
+index f93327b..f65fc12 100644
+--- a/xen/arch/x86/domain.c
++++ b/xen/arch/x86/domain.c
+_at_@ -413,7 +413,7 @@ static bool emulation_flags_ok(const struct domain *d, uint32_t emflags)
+         if ( is_hardware_domain(d) &&
+              emflags != (XEN_X86_EMU_LAPIC|XEN_X86_EMU_IOAPIC) )
+             return false;
+-        if ( !is_hardware_domain(d) && emflags &&
++        if ( !is_hardware_domain(d) &&
+              emflags != XEN_X86_EMU_ALL && emflags != XEN_X86_EMU_LAPIC )
+             return false;
+     }
-- 
2.16.2
---
Unsubscribe:  alpine-aports+unsubscribe_at_lists.alpinelinux.org
Help:         alpine-aports+help_at_lists.alpinelinux.org
---
Received on Fri Mar 16 2018 - 11:31:18 GMT