Messages in this thread Patch in this message | | | From | Siddhesh Poyarekar <> | Subject | [PATCH] Fix overflow in vma length when copying mmap on clone | Date | Tue, 24 Apr 2012 23:20:53 +0530 |
| |
The vma length in dup_mmap is calculated and stored in a unsigned int, which is insufficient and hence overflows for very large maps (beyond 16TB). The following program demonstrates this:
\#include <stdio.h> \#include <unistd.h> \#include <sys/mman.h>
\#define GIG 1024 * 1024 * 1024L \#define EXTENT 16393
int main(void) { int i, r; void *m; char buf[1024];
for (i = 0; i < EXTENT; i++) { m = mmap(NULL, (size_t) 1 * 1024 * 1024 * 1024L, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
if (m == (void *)-1) printf("MMAP Failed: %d\n", m); else printf("%d : MMAP returned %p\n", i, m);
r = fork();
if (r == 0) { printf("%d: successed\n", i); return 0; } else if (r < 0) printf("FORK Failed: %d\n", r); else if (r > 0) wait(NULL); } return 0; }
This trivial patch increases the storage size of the result to unsigned long, which should be sufficient for storing the difference between addresses.
Signed-off-by: Siddhesh Poyarekar <siddhesh.poyarekar@gmail.com> --- kernel/fork.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/kernel/fork.c b/kernel/fork.c index b9372a0..7acaee1 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -355,7 +355,8 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) } charge = 0; if (mpnt->vm_flags & VM_ACCOUNT) { - unsigned int len = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; + unsigned long len; + len = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; if (security_vm_enough_memory_mm(oldmm, len)) /* sic */ goto fail_nomem; charge = len; -- 1.7.7.6
| |