From: Julien Grall <jgr...@amazon.com> Currently perform_gunzip() can only be called once because the the internal state (e.g allocate) is not fully re-initialized.
This works fine if you are only booting dom0. But this will break when booting multiple using the dom0less that uses compressed kernel images. This can be resolved by re-initializing bytes_out, malloc_ptr, malloc_count every time perform_gunzip() is called. Note the latter is only re-initialized for hardening purpose as there is no guarantee that every malloc() are followed by free() (It should in theory!). Take the opportunity to check the return of alloc_heap_pages() to return an error rather than dereferencing a NULL pointer later on failure. Reported-by: Charles Chiou <cch...@ambarella.com> Signed-off-by: Julien Grall <jgr...@amazon.com> --- xen/common/gunzip.c | 5 +++++ xen/common/inflate.c | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/xen/common/gunzip.c b/xen/common/gunzip.c index db4efcd34b77..425d64e904d8 100644 --- a/xen/common/gunzip.c +++ b/xen/common/gunzip.c @@ -114,11 +114,16 @@ __init int perform_gunzip(char *output, char *image, unsigned long image_len) window = (unsigned char *)output; free_mem_ptr = (unsigned long)alloc_xenheap_pages(HEAPORDER, 0); + if ( !free_mem_ptr ) + return -ENOMEM; + free_mem_end_ptr = free_mem_ptr + (PAGE_SIZE << HEAPORDER); + init_allocator(); inbuf = (unsigned char *)image; insize = image_len; inptr = 0; + bytes_out = 0; makecrc(); diff --git a/xen/common/inflate.c b/xen/common/inflate.c index f99c985d6135..d8c28a3e9593 100644 --- a/xen/common/inflate.c +++ b/xen/common/inflate.c @@ -238,6 +238,12 @@ STATIC const ush mask_bits[] = { static unsigned long INITDATA malloc_ptr; static int INITDATA malloc_count; +static void init_allocator(void) +{ + malloc_ptr = free_mem_ptr; + malloc_count = 0; +} + static void *INIT malloc(int size) { void *p; -- 2.17.1