Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mm: fix overflow in vm_map_ram()

When remapping pages accounting for 4G or more memory space, the
operation 'count << PAGE_SHIFT' overflows as it is performed on an
integer. Solution: cast before doing the bitshift.

[akpm@linux-foundation.org: fix vm_unmap_ram() also]
[akpm@linux-foundation.org: fix vmap() as well, per Guillermo]
Link: http://lkml.kernel.org/r/etPan.57175fb3.7a271c6b.2bd@naudit.es
Signed-off-by: Guillermo Julián Moreno <guillermo.julian@naudit.es>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Guillermo Julián Moreno and committed by
Linus Torvalds
65ee03c4 4340fa55

+5 -4
+5 -4
mm/vmalloc.c
··· 1105 1105 */ 1106 1106 void vm_unmap_ram(const void *mem, unsigned int count) 1107 1107 { 1108 - unsigned long size = count << PAGE_SHIFT; 1108 + unsigned long size = (unsigned long)count << PAGE_SHIFT; 1109 1109 unsigned long addr = (unsigned long)mem; 1110 1110 1111 1111 BUG_ON(!addr); ··· 1140 1140 */ 1141 1141 void *vm_map_ram(struct page **pages, unsigned int count, int node, pgprot_t prot) 1142 1142 { 1143 - unsigned long size = count << PAGE_SHIFT; 1143 + unsigned long size = (unsigned long)count << PAGE_SHIFT; 1144 1144 unsigned long addr; 1145 1145 void *mem; 1146 1146 ··· 1574 1574 unsigned long flags, pgprot_t prot) 1575 1575 { 1576 1576 struct vm_struct *area; 1577 + unsigned long size; /* In bytes */ 1577 1578 1578 1579 might_sleep(); 1579 1580 1580 1581 if (count > totalram_pages) 1581 1582 return NULL; 1582 1583 1583 - area = get_vm_area_caller((count << PAGE_SHIFT), flags, 1584 - __builtin_return_address(0)); 1584 + size = (unsigned long)count << PAGE_SHIFT; 1585 + area = get_vm_area_caller(size, flags, __builtin_return_address(0)); 1585 1586 if (!area) 1586 1587 return NULL; 1587 1588