diff options
author | Ian Jackson <ian.jackson@eu.citrix.com> | 2013-06-14 16:39:34 +0100 |
---|---|---|
committer | Ian Jackson <Ian.Jackson@eu.citrix.com> | 2013-06-14 16:39:34 +0100 |
commit | b5a869209998fedadfe205d37addbd50a802998b (patch) | |
tree | 4999ff71260c57b36a0d60ee86f7c2e3e05bab63 /tools/libxc/xc_dom_core.c | |
parent | 53bfcf585b09eb4ac2240f89d1ade77421cd2451 (diff) | |
download | xen-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.c | 13 |
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); } |