diff options
author | Jan Beulich <jbeulich@suse.com> | 2012-12-04 18:38:26 +0000 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2012-12-04 18:38:26 +0000 |
commit | 8f5a6d97909777e0285dfac6f678d32649d2981b (patch) | |
tree | bc5822aeee5b5709dd2b6a85c9996577dab03aae /xen/common/memory.c | |
parent | 54c82f996207b737abb50e0889d4de1696f833c1 (diff) | |
download | xen-8f5a6d97909777e0285dfac6f678d32649d2981b.tar.gz xen-8f5a6d97909777e0285dfac6f678d32649d2981b.tar.bz2 xen-8f5a6d97909777e0285dfac6f678d32649d2981b.zip |
memop: limit guest specified extent order
Allowing unbounded order values here causes almost unbounded loops
and/or partially incomplete requests, particularly in PoD code.
The added range checks in populate_physmap(), decrease_reservation(),
and the "in" one in memory_exchange() architecturally all could use
PADDR_BITS - PAGE_SHIFT, and are being artificially constrained to
MAX_ORDER.
This is XSA-31 / CVE-2012-5515.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Tim Deegan <tim@xen.org>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson.citrix.com>
Diffstat (limited to 'xen/common/memory.c')
-rw-r--r-- | xen/common/memory.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/xen/common/memory.c b/xen/common/memory.c index bdb6ed8f35..a076f81afe 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -115,7 +115,8 @@ static void populate_physmap(struct memop_args *a) if ( a->memflags & MEMF_populate_on_demand ) { - if ( guest_physmap_mark_populate_on_demand(d, gpfn, + if ( a->extent_order > MAX_ORDER || + guest_physmap_mark_populate_on_demand(d, gpfn, a->extent_order) < 0 ) goto out; } @@ -235,7 +236,8 @@ static void decrease_reservation(struct memop_args *a) xen_pfn_t gmfn; if ( !guest_handle_subrange_okay(a->extent_list, a->nr_done, - a->nr_extents-1) ) + a->nr_extents-1) || + a->extent_order > MAX_ORDER ) return; for ( i = a->nr_done; i < a->nr_extents; i++ ) @@ -297,6 +299,9 @@ static long memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) arg) if ( (exch.nr_exchanged > exch.in.nr_extents) || /* Input and output domain identifiers match? */ (exch.in.domid != exch.out.domid) || + /* Extent orders are sensible? */ + (exch.in.extent_order > MAX_ORDER) || + (exch.out.extent_order > MAX_ORDER) || /* Sizes of input and output lists do not overflow a long? */ ((~0UL >> exch.in.extent_order) < exch.in.nr_extents) || ((~0UL >> exch.out.extent_order) < exch.out.nr_extents) || |