aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxc/xc_dom_core.c
diff options
context:
space:
mode:
authorIan Jackson <ian.jackson@eu.citrix.com>2013-06-14 16:39:34 +0100
committerIan Jackson <Ian.Jackson@eu.citrix.com>2013-06-14 16:39:34 +0100
commitb5a869209998fedadfe205d37addbd50a802998b (patch)
tree4999ff71260c57b36a0d60ee86f7c2e3e05bab63 /tools/libxc/xc_dom_core.c
parent53bfcf585b09eb4ac2240f89d1ade77421cd2451 (diff)
downloadxen-b5a869209998fedadfe205d37addbd50a802998b.tar.gz
xen-b5a869209998fedadfe205d37addbd50a802998b.tar.bz2
xen-b5a869209998fedadfe205d37addbd50a802998b.zip
libxc: Fix range checking in xc_dom_pfn_to_ptr etc.
* Ensure that xc_dom_pfn_to_ptr (when called with count==0) does not return a previously-allocated block which is entirely before the requested pfn (!) * Provide a version of xc_dom_pfn_to_ptr, xc_dom_pfn_to_ptr_retcount, which provides the length of the mapped region via an out parameter. * Change xc_dom_vaddr_to_ptr to always provide the length of the mapped region and change the call site in xc_dom_binloader.c to check it. The call site in xc_dom_load_elf_symtab will be corrected in a forthcoming patch, and for now ignores the returned length. This is part of the fix to a security issue, XSA-55. Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> v5: This patch is new in v5 of the series.
Diffstat (limited to 'tools/libxc/xc_dom_core.c')
-rw-r--r--tools/libxc/xc_dom_core.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c
index b92e4a9405..cf96bfa99b 100644
--- a/tools/libxc/xc_dom_core.c
+++ b/tools/libxc/xc_dom_core.c
@@ -351,11 +351,20 @@ int xc_dom_try_gunzip(struct xc_dom_image *dom, void **blob, size_t * size)
void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
xen_pfn_t count)
{
+ xen_pfn_t count_out_dummy;
+ return xc_dom_pfn_to_ptr_retcount(dom, pfn, count, &count_out_dummy);
+}
+
+void *xc_dom_pfn_to_ptr_retcount(struct xc_dom_image *dom, xen_pfn_t pfn,
+ xen_pfn_t count, xen_pfn_t *count_out)
+{
struct xc_dom_phys *phys;
xen_pfn_t offset;
unsigned int page_shift = XC_DOM_PAGE_SHIFT(dom);
char *mode = "unset";
+ *count_out = 0;
+
offset = pfn - dom->rambase_pfn;
if ( offset > dom->total_pages || /* multiple checks to avoid overflows */
count > dom->total_pages ||
@@ -386,6 +395,7 @@ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
phys->count);
return NULL;
}
+ *count_out = count;
}
else
{
@@ -393,6 +403,9 @@ void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn,
just hand out a pointer to it */
if ( pfn < phys->first )
continue;
+ if ( pfn >= phys->first + phys->count )
+ continue;
+ *count_out = phys->count - (pfn - phys->first);
}
return phys->ptr + ((pfn - phys->first) << page_shift);
}