diff options
author | Guillermo Julián Moreno <guillermo.julian@naudit.es> | 2016-06-03 17:55:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-06-03 18:06:22 -0400 |
commit | 65ee03c4b9f89e1b088defd97273be6da169d798 (patch) | |
tree | ca5bd05b3bc29cf2a5a07f083fd80221049aa06e /mm | |
parent | 4340fa55298d17049e71c7a34e04647379c269f3 (diff) |
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>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/vmalloc.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index cf7ad1a53be0..e11475cdeb7a 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c | |||
@@ -1105,7 +1105,7 @@ EXPORT_SYMBOL_GPL(vm_unmap_aliases); | |||
1105 | */ | 1105 | */ |
1106 | void vm_unmap_ram(const void *mem, unsigned int count) | 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 | unsigned long addr = (unsigned long)mem; | 1109 | unsigned long addr = (unsigned long)mem; |
1110 | 1110 | ||
1111 | BUG_ON(!addr); | 1111 | BUG_ON(!addr); |
@@ -1140,7 +1140,7 @@ EXPORT_SYMBOL(vm_unmap_ram); | |||
1140 | */ | 1140 | */ |
1141 | void *vm_map_ram(struct page **pages, unsigned int count, int node, pgprot_t prot) | 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 | unsigned long addr; | 1144 | unsigned long addr; |
1145 | void *mem; | 1145 | void *mem; |
1146 | 1146 | ||
@@ -1574,14 +1574,15 @@ void *vmap(struct page **pages, unsigned int count, | |||
1574 | unsigned long flags, pgprot_t prot) | 1574 | unsigned long flags, pgprot_t prot) |
1575 | { | 1575 | { |
1576 | struct vm_struct *area; | 1576 | struct vm_struct *area; |
1577 | unsigned long size; /* In bytes */ | ||
1577 | 1578 | ||
1578 | might_sleep(); | 1579 | might_sleep(); |
1579 | 1580 | ||
1580 | if (count > totalram_pages) | 1581 | if (count > totalram_pages) |
1581 | return NULL; | 1582 | return NULL; |
1582 | 1583 | ||
1583 | area = get_vm_area_caller((count << PAGE_SHIFT), flags, | 1584 | size = (unsigned long)count << PAGE_SHIFT; |
1584 | __builtin_return_address(0)); | 1585 | area = get_vm_area_caller(size, flags, __builtin_return_address(0)); |
1585 | if (!area) | 1586 | if (!area) |
1586 | return NULL; | 1587 | return NULL; |
1587 | 1588 | ||