]> xenbits.xensource.com Git - people/dariof/xen.git/commitdiff
xmalloc: guard against integer overflow
authorJan Beulich <jbeulich@suse.com>
Thu, 6 Feb 2020 08:53:12 +0000 (09:53 +0100)
committerJan Beulich <jbeulich@suse.com>
Thu, 6 Feb 2020 08:53:12 +0000 (09:53 +0100)
There are hypercall handling paths (EFI ones are what this was found
with) needing to allocate buffers of a caller specified size. This is
generally fine, as our page allocator enforces an upper bound on all
allocations. However, certain extremely large sizes could, when adding
in allocator overhead, result in an apparently tiny allocation size,
which would typically result in either a successful allocation, but a
severe buffer overrun when using that memory block, or in a crash right
in the allocator code.

Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
xen/common/xmalloc_tlsf.c

index 0b92a7a7a35bd2ddb98af3ad29e7319930c4efe6..e3f6886e6b6228b1fb4e01dcf524cf56b34a118b 100644 (file)
@@ -378,7 +378,17 @@ void *xmem_pool_alloc(unsigned long size, struct xmem_pool *pool)
     int fl, sl;
     unsigned long tmp_size;
 
-    size = (size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE : ROUNDUP_SIZE(size);
+    if ( size < MIN_BLOCK_SIZE )
+        size = MIN_BLOCK_SIZE;
+    else
+    {
+        tmp_size = ROUNDUP_SIZE(size);
+        /* Guard against overflow. */
+        if ( tmp_size < size )
+            return NULL;
+        size = tmp_size;
+    }
+
     /* Rounding up the requested size and calculating fl and sl */
 
     spin_lock(&pool->lock);
@@ -594,6 +604,10 @@ void *_xmalloc(unsigned long size, unsigned long align)
         align = MEM_ALIGN;
     size += align - MEM_ALIGN;
 
+    /* Guard against overflow. */
+    if ( size < align - MEM_ALIGN )
+        return NULL;
+
     if ( !xenpool )
         tlsf_init();
 
@@ -646,6 +660,10 @@ void *_xrealloc(void *ptr, unsigned long size, unsigned long align)
         unsigned long tmp_size = size + align - MEM_ALIGN;
         const struct bhdr *b;
 
+        /* Guard against overflow. */
+        if ( tmp_size < size )
+            return NULL;
+
         if ( tmp_size < PAGE_SIZE )
             tmp_size = (tmp_size < MIN_BLOCK_SIZE) ? MIN_BLOCK_SIZE :
                 ROUNDUP_SIZE(tmp_size);