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.h | |
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.h')
-rw-r--r-- | tools/libxc/xc_dom.h | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/tools/libxc/xc_dom.h b/tools/libxc/xc_dom.h index 316c5cbefc..ad6fdd49e2 100644 --- a/tools/libxc/xc_dom.h +++ b/tools/libxc/xc_dom.h @@ -291,6 +291,8 @@ int xc_dom_alloc_segment(struct xc_dom_image *dom, void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t first, xen_pfn_t count); +void *xc_dom_pfn_to_ptr_retcount(struct xc_dom_image *dom, xen_pfn_t first, + xen_pfn_t count, xen_pfn_t *count_out); void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn); void xc_dom_unmap_all(struct xc_dom_image *dom); @@ -318,13 +320,21 @@ static inline void *xc_dom_seg_to_ptr(struct xc_dom_image *dom, } static inline void *xc_dom_vaddr_to_ptr(struct xc_dom_image *dom, - xen_vaddr_t vaddr) + xen_vaddr_t vaddr, + size_t *safe_region_out) { unsigned int page_size = XC_DOM_PAGE_SIZE(dom); xen_pfn_t page = (vaddr - dom->parms.virt_base) / page_size; unsigned int offset = (vaddr - dom->parms.virt_base) % page_size; - void *ptr = xc_dom_pfn_to_ptr(dom, page, 0); - return (ptr ? (ptr + offset) : NULL); + xen_pfn_t safe_region_count; + void *ptr; + + *safe_region_out = 0; + ptr = xc_dom_pfn_to_ptr_retcount(dom, page, 0, &safe_region_count); + if ( ptr == NULL ) + return ptr; + *safe_region_out = (safe_region_count << XC_DOM_PAGE_SHIFT(dom)) - offset; + return ptr; } static inline xen_pfn_t xc_dom_p2m_host(struct xc_dom_image *dom, xen_pfn_t pfn) |