Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP2:GA
xen.6712
xsa231.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File xsa231.patch of Package xen.6712
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. 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> Index: xen-4.5.5-testing/xen/common/memory.c =================================================================== --- xen-4.5.5-testing.orig/xen/common/memory.c +++ xen-4.5.5-testing/xen/common/memory.c @@ -384,6 +384,30 @@ static void decrease_reservation(struct a->nr_done = i; } +static bool_t propagate_node(unsigned int xmf, unsigned int *memflags) +{ + const struct domain *currd = current->domain; + + BUILD_BUG_ON(XENMEMF_get_node(0) != NUMA_NO_NODE); + + if ( XENMEMF_get_node(xmf) == NUMA_NO_NODE ) + return 1; + + if ( is_hardware_domain(currd) || is_control_domain(currd) ) + { + if ( XENMEMF_get_node(xmf) >= MAX_NUMNODES ) + return 0; + + *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 0; + + return 1; +} + static long memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) arg) { struct xen_memory_exchange exch; @@ -456,6 +480,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 ) { @@ -474,7 +504,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); @@ -818,9 +847,8 @@ long do_memory_op(unsigned long cmd, XEN args.memflags = MEMF_bits(address_bits); } - args.memflags |= MEMF_node(XENMEMF_get_node(reservation.mem_flags)); - if ( reservation.mem_flags & XENMEMF_exact_node_request ) - args.memflags |= MEMF_exact_node; + if ( unlikely(!propagate_node(reservation.mem_flags, &args.memflags)) ) + return -EINVAL; if ( op == XENMEM_populate_physmap && (reservation.mem_flags & XENMEMF_populate_on_demand) ) Index: xen-4.5.5-testing/xen/common/page_alloc.c =================================================================== --- xen-4.5.5-testing.orig/xen/common/page_alloc.c +++ xen-4.5.5-testing/xen/common/page_alloc.c @@ -610,9 +610,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 >= 0); ASSERT(zone_lo <= zone_hi); ASSERT(zone_hi < NR_ZONES);
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor