Re: [Bug 210023] New: Crash when allocating > 2 TB memory

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



(switched to email.  Please respond via emailed reply-to-all, not via the
bugzilla web interface).

On Tue, 03 Nov 2020 18:50:07 +0000 bugzilla-daemon@xxxxxxxxxxxxxxxxxxx wrote:

> https://bugzilla.kernel.org/show_bug.cgi?id=210023
> 
>             Bug ID: 210023
>            Summary: Crash when allocating > 2 TB memory
>            Product: Memory Management
>            Version: 2.5
>     Kernel Version: 3.10.0-957.27.2.el7.x86_64
>           Hardware: All
>                 OS: Linux
>               Tree: Mainline
>             Status: NEW
>           Severity: blocking
>           Priority: P1
>          Component: Slab Allocator
>           Assignee: akpm@xxxxxxxxxxxxxxxxxxxx
>           Reporter: hsinhuiwu@xxxxxxxxx
>         Regression: No
> 
> With a machine with 3 TB (more than 2 TB memory). If you use vmalloc to
> allocate > 2 TB memory, the array_size below will be overflowed.

How was this observed?

Is there any know userspace operation which causes the kernel to try to
vmalloc such a large hunk of memory?

> The array_size is an unsigned int and can only be used to allocate less than 2
> TB memory. If you pass 2*1028*1028*1024*1024 = 2 * 2^40 in the argument of
> vmalloc. The array_size will become 2*2^31 = 2^32. The 2^32 cannot be store
> with a 32 bit integer.
> 
> The fix is to change the type of array_size to unsigned long.
> 
> vmalloc.c
> 
> 1762 void *vmalloc(unsigned long size)
> 1763 {
> 1764     return __vmalloc_node_flags(size, NUMA_NO_NODE,
> 1765                     GFP_KERNEL | __GFP_HIGHMEM);
> 1766 }

OK, thanks.  Against current mainline your proposed change would look
like this, yes?

--- a/mm/vmalloc.c~a
+++ a/mm/vmalloc.c
@@ -2461,9 +2461,11 @@ static void *__vmalloc_area_node(struct
 {
 	const gfp_t nested_gfp = (gfp_mask & GFP_RECLAIM_MASK) | __GFP_ZERO;
 	unsigned int nr_pages = get_vm_area_size(area) >> PAGE_SHIFT;
-	unsigned int array_size = nr_pages * sizeof(struct page *), i;
+	unsigned long array_size
+	unsigned int i;
 	struct page **pages;
 
+	array_size = (unsigned long)nr_pages * sizeof(struct page *);
 	gfp_mask |= __GFP_NOWARN;
 	if (!(gfp_mask & (GFP_DMA | GFP_DMA32)))
 		gfp_mask |= __GFP_HIGHMEM;
_





[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux