summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mm/mmap.c15
1 files changed, 8 insertions, 7 deletions
diff --git a/mm/mmap.c b/mm/mmap.c
index dff37a686230..6182c8a4ea38 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1368,7 +1368,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
struct vm_area_struct *vma;
unsigned long start_addr;
- if (len > TASK_SIZE)
+ if (len > TASK_SIZE - mmap_min_addr)
return -ENOMEM;
if (flags & MAP_FIXED)
@@ -1377,7 +1377,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
if (addr) {
addr = PAGE_ALIGN(addr);
vma = find_vma(mm, addr);
- if (TASK_SIZE - len >= addr &&
+ if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
(!vma || addr + len <= vma->vm_start))
return addr;
}
@@ -1442,9 +1442,10 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
struct vm_area_struct *vma;
struct mm_struct *mm = current->mm;
unsigned long addr = addr0;
+ unsigned long low_limit = max(PAGE_SIZE, mmap_min_addr);
/* requested length too big for entire address space */
- if (len > TASK_SIZE)
+ if (len > TASK_SIZE - mmap_min_addr)
return -ENOMEM;
if (flags & MAP_FIXED)
@@ -1454,7 +1455,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
if (addr) {
addr = PAGE_ALIGN(addr);
vma = find_vma(mm, addr);
- if (TASK_SIZE - len >= addr &&
+ if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
(!vma || addr + len <= vma->vm_start))
return addr;
}
@@ -1469,14 +1470,14 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
addr = mm->free_area_cache;
/* make sure it can fit in the remaining address space */
- if (addr > len) {
+ if (addr >= low_limit + len) {
vma = find_vma(mm, addr-len);
if (!vma || addr <= vma->vm_start)
/* remember the address as a hint for next time */
return (mm->free_area_cache = addr-len);
}
- if (mm->mmap_base < len)
+ if (mm->mmap_base < low_limit + len)
goto bottomup;
addr = mm->mmap_base-len;
@@ -1498,7 +1499,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
/* try just below the current vma->vm_start */
addr = vma->vm_start-len;
- } while (len < vma->vm_start);
+ } while (vma->vm_start >= low_limit + len);
bottomup:
/*