From 0738227939177fbbbf4af44238b4222d2be040c8 Mon Sep 17 00:00:00 2001
From: Mario Preksavec <mario@slackware.hr>
Date: Mon, 18 Sep 2017 23:05:24 +0200
Subject: system/xen: XSA 231-235 update.

Signed-off-by: Mario Preksavec <mario@slackware.hr>
---
 system/xen/dom0/config-4.4.75-xen.i686   |   2 +-
 system/xen/dom0/config-4.4.75-xen.x86_64 |   2 +-
 system/xen/dom0/kernel-xen.sh            |   2 +-
 system/xen/domU/domU.sh                  |   2 +-
 system/xen/xen.SlackBuild                |   2 +-
 system/xen/xsa/xsa231-4.9.patch          | 108 +++++++++++++++++
 system/xen/xsa/xsa232.patch              |  23 ++++
 system/xen/xsa/xsa233.patch              |  52 +++++++++
 system/xen/xsa/xsa234-4.9.patch          | 192 +++++++++++++++++++++++++++++++
 system/xen/xsa/xsa235-4.9.patch          |  49 ++++++++
 10 files changed, 429 insertions(+), 5 deletions(-)
 create mode 100644 system/xen/xsa/xsa231-4.9.patch
 create mode 100644 system/xen/xsa/xsa232.patch
 create mode 100644 system/xen/xsa/xsa233.patch
 create mode 100644 system/xen/xsa/xsa234-4.9.patch
 create mode 100644 system/xen/xsa/xsa235-4.9.patch

(limited to 'system/xen')

diff --git a/system/xen/dom0/config-4.4.75-xen.i686 b/system/xen/dom0/config-4.4.75-xen.i686
index b29da0f7b087e..ab22d64f08e07 100644
--- a/system/xen/dom0/config-4.4.75-xen.i686
+++ b/system/xen/dom0/config-4.4.75-xen.i686
@@ -1,6 +1,6 @@
 #
 # Automatically generated file; DO NOT EDIT.
-# Linux/x86 4.4.75 Kernel Configuration
+# Linux/x86 4.4.88 Kernel Configuration
 #
 # CONFIG_64BIT is not set
 CONFIG_X86_32=y
diff --git a/system/xen/dom0/config-4.4.75-xen.x86_64 b/system/xen/dom0/config-4.4.75-xen.x86_64
index 9ed52dccfb117..5b8b948341203 100644
--- a/system/xen/dom0/config-4.4.75-xen.x86_64
+++ b/system/xen/dom0/config-4.4.75-xen.x86_64
@@ -1,6 +1,6 @@
 #
 # Automatically generated file; DO NOT EDIT.
-# Linux/x86 4.4.75 Kernel Configuration
+# Linux/x86 4.4.88 Kernel Configuration
 #
 CONFIG_64BIT=y
 CONFIG_X86_64=y
diff --git a/system/xen/dom0/kernel-xen.sh b/system/xen/dom0/kernel-xen.sh
index d13851c97fdca..e33676d04225c 100644
--- a/system/xen/dom0/kernel-xen.sh
+++ b/system/xen/dom0/kernel-xen.sh
@@ -5,7 +5,7 @@
 # Written by Chris Abela <chris.abela@maltats.com>, 20100515
 # Modified by Mario Preksavec <mario@slackware.hr>
 
-KERNEL=${KERNEL:-4.4.75}
+KERNEL=${KERNEL:-4.4.88}
 XEN=${XEN:-4.9.0}
 BOOTLOADER=${BOOTLOADER:-lilo}
 
diff --git a/system/xen/domU/domU.sh b/system/xen/domU/domU.sh
index 584132724e314..87165495360a6 100644
--- a/system/xen/domU/domU.sh
+++ b/system/xen/domU/domU.sh
@@ -7,7 +7,7 @@
 
 set -e
 
-KERNEL=${KERNEL:-4.4.75}
+KERNEL=${KERNEL:-4.4.88}
 
 # Build an image for the root file system and another for the swap
 # Default values : 8GB and 500MB resepectively.
diff --git a/system/xen/xen.SlackBuild b/system/xen/xen.SlackBuild
index 78a7548e1c7f8..8b56171fbd5b3 100644
--- a/system/xen/xen.SlackBuild
+++ b/system/xen/xen.SlackBuild
@@ -24,7 +24,7 @@
 
 PRGNAM=xen
 VERSION=${VERSION:-4.9.0}
-BUILD=${BUILD:-2}
+BUILD=${BUILD:-3}
 TAG=${TAG:-_SBo}
 
 SEABIOS=${SEABIOS:-1.10.0}
diff --git a/system/xen/xsa/xsa231-4.9.patch b/system/xen/xsa/xsa231-4.9.patch
new file mode 100644
index 0000000000000..251165e6bddb0
--- /dev/null
+++ b/system/xen/xsa/xsa231-4.9.patch
@@ -0,0 +1,108 @@
+From: George Dunlap <george.dunlap@citrix.com>
+Subject: xen/mm: make sure node is less than MAX_NUMNODES
+
+The output of MEMF_get_node(memflags) can be as large as nodeid_t can
+hold (currently 255).  This is then used as an index to arrays of size
+MAX_NUMNODE, which is 64 on x86 and 1 on ARM, can be passed in by an
+untrusted guest (via memory_exchange and increase_reservation) and is
+not currently bounds-checked.
+
+Check the value in page_alloc.c before using it, and also check the
+value in the hypercall call sites and return -EINVAL if appropriate.
+Don't permit domains other than the hardware or control domain to
+allocate node-constrained memory.
+
+This is XSA-231.
+
+Reported-by: Matthew Daley <mattd@bugfuzz.com>
+Signed-off-by: George Dunlap <george.dunlap@citrix.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+
+--- a/xen/common/memory.c
++++ b/xen/common/memory.c
+@@ -411,6 +411,31 @@ static void decrease_reservation(struct
+     a->nr_done = i;
+ }
+ 
++static bool propagate_node(unsigned int xmf, unsigned int *memflags)
++{
++    const struct domain *currd = current->domain;
++
++    BUILD_BUG_ON(XENMEMF_get_node(0) != NUMA_NO_NODE);
++    BUILD_BUG_ON(MEMF_get_node(0) != NUMA_NO_NODE);
++
++    if ( XENMEMF_get_node(xmf) == NUMA_NO_NODE )
++        return true;
++
++    if ( is_hardware_domain(currd) || is_control_domain(currd) )
++    {
++        if ( XENMEMF_get_node(xmf) >= MAX_NUMNODES )
++            return false;
++
++        *memflags |= MEMF_node(XENMEMF_get_node(xmf));
++        if ( xmf & XENMEMF_exact_node_request )
++            *memflags |= MEMF_exact_node;
++    }
++    else if ( xmf & XENMEMF_exact_node_request )
++        return false;
++
++    return true;
++}
++
+ static long memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) arg)
+ {
+     struct xen_memory_exchange exch;
+@@ -483,6 +508,12 @@ static long memory_exchange(XEN_GUEST_HA
+         }
+     }
+ 
++    if ( unlikely(!propagate_node(exch.out.mem_flags, &memflags)) )
++    {
++        rc = -EINVAL;
++        goto fail_early;
++    }
++
+     d = rcu_lock_domain_by_any_id(exch.in.domid);
+     if ( d == NULL )
+     {
+@@ -501,7 +532,6 @@ static long memory_exchange(XEN_GUEST_HA
+         d,
+         XENMEMF_get_address_bits(exch.out.mem_flags) ? :
+         (BITS_PER_LONG+PAGE_SHIFT)));
+-    memflags |= MEMF_node(XENMEMF_get_node(exch.out.mem_flags));
+ 
+     for ( i = (exch.nr_exchanged >> in_chunk_order);
+           i < (exch.in.nr_extents >> in_chunk_order);
+@@ -864,12 +894,8 @@ static int construct_memop_from_reservat
+         }
+         read_unlock(&d->vnuma_rwlock);
+     }
+-    else
+-    {
+-        a->memflags |= MEMF_node(XENMEMF_get_node(r->mem_flags));
+-        if ( r->mem_flags & XENMEMF_exact_node_request )
+-            a->memflags |= MEMF_exact_node;
+-    }
++    else if ( unlikely(!propagate_node(r->mem_flags, &a->memflags)) )
++        return -EINVAL;
+ 
+     return 0;
+ }
+--- a/xen/common/page_alloc.c
++++ b/xen/common/page_alloc.c
+@@ -706,9 +706,13 @@ static struct page_info *alloc_heap_page
+         if ( node >= MAX_NUMNODES )
+             node = cpu_to_node(smp_processor_id());
+     }
++    else if ( unlikely(node >= MAX_NUMNODES) )
++    {
++        ASSERT_UNREACHABLE();
++        return NULL;
++    }
+     first_node = node;
+ 
+-    ASSERT(node < MAX_NUMNODES);
+     ASSERT(zone_lo <= zone_hi);
+     ASSERT(zone_hi < NR_ZONES);
+ 
diff --git a/system/xen/xsa/xsa232.patch b/system/xen/xsa/xsa232.patch
new file mode 100644
index 0000000000000..9e5f35c7d6dcd
--- /dev/null
+++ b/system/xen/xsa/xsa232.patch
@@ -0,0 +1,23 @@
+From: Andrew Cooper <andrew.cooper3@citrix.com>
+Subject: grant_table: fix GNTTABOP_cache_flush handling
+
+Don't fall over a NULL grant_table pointer when the owner of the domain
+is a system domain (DOMID_{XEN,IO} etc).
+
+This is XSA-232.
+
+Reported-by: Matthew Daley <mattd@bugfuzz.com>
+Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Reviewed-by: Jan Beulich <jbeulich@suse.com>
+
+--- a/xen/common/grant_table.c
++++ b/xen/common/grant_table.c
+@@ -3053,7 +3053,7 @@ static int cache_flush(gnttab_cache_flus
+ 
+     page = mfn_to_page(mfn);
+     owner = page_get_owner_and_reference(page);
+-    if ( !owner )
++    if ( !owner || !owner->grant_table )
+     {
+         rcu_unlock_domain(d);
+         return -EPERM;
diff --git a/system/xen/xsa/xsa233.patch b/system/xen/xsa/xsa233.patch
new file mode 100644
index 0000000000000..6013c52b410be
--- /dev/null
+++ b/system/xen/xsa/xsa233.patch
@@ -0,0 +1,52 @@
+From: Juergen Gross <jgross@suse.com>
+Subject: tools/xenstore: dont unlink connection object twice
+
+A connection object of a domain with associated stubdom has two
+parents: the domain and the stubdom. When cleaning up the list of
+active domains in domain_cleanup() make sure not to unlink the
+connection twice from the same domain. This could happen when the
+domain and its stubdom are being destroyed at the same time leading
+to the domain loop being entered twice.
+
+Additionally don't use talloc_free() in this case as it will remove
+a random parent link, leading eventually to a memory leak. Use
+talloc_unlink() instead specifying the context from which the
+connection object should be removed.
+
+This is XSA-233.
+
+Reported-by: Eric Chanudet <chanudete@ainfosec.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Reviewed-by: Ian Jackson <ian.jackson@eu.citrix.com>
+
+--- a/tools/xenstore/xenstored_domain.c
++++ b/tools/xenstore/xenstored_domain.c
+@@ -221,10 +221,11 @@ static int destroy_domain(void *_domain)
+ static void domain_cleanup(void)
+ {
+ 	xc_dominfo_t dominfo;
+-	struct domain *domain, *tmp;
++	struct domain *domain;
+ 	int notify = 0;
+ 
+-	list_for_each_entry_safe(domain, tmp, &domains, list) {
++ again:
++	list_for_each_entry(domain, &domains, list) {
+ 		if (xc_domain_getinfo(*xc_handle, domain->domid, 1,
+ 				      &dominfo) == 1 &&
+ 		    dominfo.domid == domain->domid) {
+@@ -236,8 +237,12 @@ static void domain_cleanup(void)
+ 			if (!dominfo.dying)
+ 				continue;
+ 		}
+-		talloc_free(domain->conn);
+-		notify = 0; /* destroy_domain() fires the watch */
++		if (domain->conn) {
++			talloc_unlink(talloc_autofree_context(), domain->conn);
++			domain->conn = NULL;
++			notify = 0; /* destroy_domain() fires the watch */
++			goto again;
++		}
+ 	}
+ 
+ 	if (notify)
diff --git a/system/xen/xsa/xsa234-4.9.patch b/system/xen/xsa/xsa234-4.9.patch
new file mode 100644
index 0000000000000..8dbf40172053a
--- /dev/null
+++ b/system/xen/xsa/xsa234-4.9.patch
@@ -0,0 +1,192 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: gnttab: also validate PTE permissions upon destroy/replace
+
+In order for PTE handling to match up with the reference counting done
+by common code, presence and writability of grant mapping PTEs must
+also be taken into account; validating just the frame number is not
+enough. This is in particular relevant if a guest fiddles with grant
+PTEs via non-grant hypercalls.
+
+Note that the flags being passed to replace_grant_host_mapping()
+already happen to be those of the existing mapping, so no new function
+parameter is needed.
+
+This is XSA-234.
+
+Reported-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
+
+--- a/xen/arch/x86/mm.c
++++ b/xen/arch/x86/mm.c
+@@ -4058,7 +4058,8 @@ static int create_grant_pte_mapping(
+ }
+ 
+ static int destroy_grant_pte_mapping(
+-    uint64_t addr, unsigned long frame, struct domain *d)
++    uint64_t addr, unsigned long frame, unsigned int grant_pte_flags,
++    struct domain *d)
+ {
+     int rc = GNTST_okay;
+     void *va;
+@@ -4104,17 +4105,29 @@ static int destroy_grant_pte_mapping(
+ 
+     ol1e = *(l1_pgentry_t *)va;
+     
+-    /* Check that the virtual address supplied is actually mapped to frame. */
+-    if ( unlikely(l1e_get_pfn(ol1e) != frame) )
++    /*
++     * Check that the PTE supplied actually maps frame (with appropriate
++     * permissions).
++     */
++    if ( unlikely(l1e_get_pfn(ol1e) != frame) ||
++         unlikely((l1e_get_flags(ol1e) ^ grant_pte_flags) &
++                  (_PAGE_PRESENT | _PAGE_RW)) )
+     {
+         page_unlock(page);
+-        gdprintk(XENLOG_WARNING,
+-                 "PTE entry %"PRIpte" for address %"PRIx64" doesn't match frame %lx\n",
+-                 l1e_get_intpte(ol1e), addr, frame);
++        gdprintk(XENLOG_ERR,
++                 "PTE %"PRIpte" at %"PRIx64" doesn't match grant (%"PRIpte")\n",
++                 l1e_get_intpte(ol1e), addr,
++                 l1e_get_intpte(l1e_from_pfn(frame, grant_pte_flags)));
+         rc = GNTST_general_error;
+         goto failed;
+     }
+ 
++    if ( unlikely((l1e_get_flags(ol1e) ^ grant_pte_flags) &
++                  ~(_PAGE_AVAIL | PAGE_CACHE_ATTRS)) )
++        gdprintk(XENLOG_WARNING,
++                 "PTE flags %x at %"PRIx64" don't match grant (%x)\n",
++                 l1e_get_flags(ol1e), addr, grant_pte_flags);
++
+     /* Delete pagetable entry. */
+     if ( unlikely(!UPDATE_ENTRY
+                   (l1, 
+@@ -4123,7 +4136,8 @@ static int destroy_grant_pte_mapping(
+                    0)) )
+     {
+         page_unlock(page);
+-        gdprintk(XENLOG_WARNING, "Cannot delete PTE entry at %p\n", va);
++        gdprintk(XENLOG_WARNING, "Cannot delete PTE entry at %"PRIx64"\n",
++                 addr);
+         rc = GNTST_general_error;
+         goto failed;
+     }
+@@ -4191,7 +4205,8 @@ static int create_grant_va_mapping(
+ }
+ 
+ static int replace_grant_va_mapping(
+-    unsigned long addr, unsigned long frame, l1_pgentry_t nl1e, struct vcpu *v)
++    unsigned long addr, unsigned long frame, unsigned int grant_pte_flags,
++    l1_pgentry_t nl1e, struct vcpu *v)
+ {
+     l1_pgentry_t *pl1e, ol1e;
+     unsigned long gl1mfn;
+@@ -4227,20 +4242,33 @@ static int replace_grant_va_mapping(
+ 
+     ol1e = *pl1e;
+ 
+-    /* Check that the virtual address supplied is actually mapped to frame. */
+-    if ( unlikely(l1e_get_pfn(ol1e) != frame) )
+-    {
+-        gdprintk(XENLOG_WARNING,
+-                 "PTE entry %lx for address %lx doesn't match frame %lx\n",
+-                 l1e_get_pfn(ol1e), addr, frame);
++    /*
++     * Check that the virtual address supplied is actually mapped to frame
++     * (with appropriate permissions).
++     */
++    if ( unlikely(l1e_get_pfn(ol1e) != frame) ||
++         unlikely((l1e_get_flags(ol1e) ^ grant_pte_flags) &
++                  (_PAGE_PRESENT | _PAGE_RW)) )
++    {
++        gdprintk(XENLOG_ERR,
++                 "PTE %"PRIpte" for %lx doesn't match grant (%"PRIpte")\n",
++                 l1e_get_intpte(ol1e), addr,
++                 l1e_get_intpte(l1e_from_pfn(frame, grant_pte_flags)));
+         rc = GNTST_general_error;
+         goto unlock_and_out;
+     }
+ 
++    if ( unlikely((l1e_get_flags(ol1e) ^ grant_pte_flags) &
++                  ~(_PAGE_AVAIL | PAGE_CACHE_ATTRS)) )
++        gdprintk(XENLOG_WARNING,
++                 "PTE flags %x for %"PRIx64" don't match grant (%x)\n",
++                 l1e_get_flags(ol1e), addr, grant_pte_flags);
++
+     /* Delete pagetable entry. */
+     if ( unlikely(!UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, v, 0)) )
+     {
+-        gdprintk(XENLOG_WARNING, "Cannot delete PTE entry at %p\n", pl1e);
++        gdprintk(XENLOG_WARNING, "Cannot delete PTE entry for %"PRIx64"\n",
++                 addr);
+         rc = GNTST_general_error;
+         goto unlock_and_out;
+     }
+@@ -4254,9 +4282,11 @@ static int replace_grant_va_mapping(
+ }
+ 
+ static int destroy_grant_va_mapping(
+-    unsigned long addr, unsigned long frame, struct vcpu *v)
++    unsigned long addr, unsigned long frame, unsigned int grant_pte_flags,
++    struct vcpu *v)
+ {
+-    return replace_grant_va_mapping(addr, frame, l1e_empty(), v);
++    return replace_grant_va_mapping(addr, frame, grant_pte_flags,
++                                    l1e_empty(), v);
+ }
+ 
+ static int create_grant_p2m_mapping(uint64_t addr, unsigned long frame,
+@@ -4351,20 +4381,39 @@ int replace_grant_host_mapping(
+     unsigned long gl1mfn;
+     struct page_info *l1pg;
+     int rc;
++    unsigned int grant_pte_flags;
+     
+     if ( paging_mode_external(current->domain) )
+         return replace_grant_p2m_mapping(addr, frame, new_addr, flags);
+ 
++    grant_pte_flags =
++        _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_GNTTAB | _PAGE_NX;
++
++    if ( flags & GNTMAP_application_map )
++        grant_pte_flags |= _PAGE_USER;
++    if ( !(flags & GNTMAP_readonly) )
++        grant_pte_flags |= _PAGE_RW;
++    /*
++     * On top of the explicit settings done by create_grant_host_mapping()
++     * also open-code relevant parts of adjust_guest_l1e(). Don't mirror
++     * available and cachability flags, though.
++     */
++    if ( !is_pv_32bit_domain(curr->domain) )
++        grant_pte_flags |= (grant_pte_flags & _PAGE_USER)
++                           ? _PAGE_GLOBAL
++                           : _PAGE_GUEST_KERNEL | _PAGE_USER;
++
+     if ( flags & GNTMAP_contains_pte )
+     {
+         if ( !new_addr )
+-            return destroy_grant_pte_mapping(addr, frame, curr->domain);
++            return destroy_grant_pte_mapping(addr, frame, grant_pte_flags,
++                                             curr->domain);
+         
+         return GNTST_general_error;
+     }
+ 
+     if ( !new_addr )
+-        return destroy_grant_va_mapping(addr, frame, curr);
++        return destroy_grant_va_mapping(addr, frame, grant_pte_flags, curr);
+ 
+     pl1e = guest_map_l1e(new_addr, &gl1mfn);
+     if ( !pl1e )
+@@ -4412,7 +4461,7 @@ int replace_grant_host_mapping(
+     put_page(l1pg);
+     guest_unmap_l1e(pl1e);
+ 
+-    rc = replace_grant_va_mapping(addr, frame, ol1e, curr);
++    rc = replace_grant_va_mapping(addr, frame, grant_pte_flags, ol1e, curr);
+     if ( rc && !paging_mode_refcounts(curr->domain) )
+         put_page_from_l1e(ol1e, curr->domain);
+ 
diff --git a/system/xen/xsa/xsa235-4.9.patch b/system/xen/xsa/xsa235-4.9.patch
new file mode 100644
index 0000000000000..25dd650755f99
--- /dev/null
+++ b/system/xen/xsa/xsa235-4.9.patch
@@ -0,0 +1,49 @@
+From: Jan Beulich <jbeulich@suse.com>
+Subject: arm/mm: release grant lock on xenmem_add_to_physmap_one() error paths
+
+Commit 55021ff9ab ("xen/arm: add_to_physmap_one: Avoid to map mfn 0 if
+an error occurs") introduced error paths not releasing the grant table
+lock. Replace them by a suitable check after the lock was dropped.
+
+This is XSA-235.
+
+Reported-by: Wei Liu <wei.liu2@citrix.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Reviewed-by: Julien Grall <julien.grall@arm.com>
+
+--- a/xen/arch/arm/mm.c
++++ b/xen/arch/arm/mm.c
+@@ -1164,7 +1164,7 @@ int xenmem_add_to_physmap_one(
+             if ( idx < nr_status_frames(d->grant_table) )
+                 mfn = virt_to_mfn(d->grant_table->status[idx]);
+             else
+-                return -EINVAL;
++                mfn = mfn_x(INVALID_MFN);
+         }
+         else
+         {
+@@ -1175,14 +1175,21 @@ int xenmem_add_to_physmap_one(
+             if ( idx < nr_grant_frames(d->grant_table) )
+                 mfn = virt_to_mfn(d->grant_table->shared_raw[idx]);
+             else
+-                return -EINVAL;
++                mfn = mfn_x(INVALID_MFN);
+         }
+ 
+-        d->arch.grant_table_gfn[idx] = gfn;
++        if ( mfn != mfn_x(INVALID_MFN) )
++        {
++            d->arch.grant_table_gfn[idx] = gfn;
+ 
+-        t = p2m_ram_rw;
++            t = p2m_ram_rw;
++        }
+ 
+         grant_write_unlock(d->grant_table);
++
++        if ( mfn == mfn_x(INVALID_MFN) )
++            return -EINVAL;
++
+         break;
+     case XENMAPSPACE_shared_info:
+         if ( idx != 0 )
-- 
cgit v1.2.3