system/xen: XSA 231-235 update.
Signed-off-by: Mario Preksavec <mario@slackware.hr>
This commit is contained in:
parent
c9bcfd5b7d
commit
0738227939
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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);
|
||||
|
|
@ -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;
|
|
@ -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)
|
|
@ -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);
|
||||
|
|
@ -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 )
|
Loading…
Reference in New Issue