summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Gordeev <agordeev@linux.ibm.com>2020-05-14 13:41:03 +1000
committerStephen Rothwell <sfr@canb.auug.org.au>2020-05-14 20:12:30 +1000
commit3b01cce1abe2e78c4c5bb2ee39e5c3a412dae5d4 (patch)
tree3c713bfd7ad3ca22e08316250a98cc9dcdd89a55
parent376b9fe72ee6e9415441e3350762c6dbd03e6cf6 (diff)
downloadlinux-3b01cce1abe2e78c4c5bb2ee39e5c3a412dae5d4.tar.gz
linux-3b01cce1abe2e78c4c5bb2ee39e5c3a412dae5d4.tar.xz
mm/mmap.c: add more sanity checks to get_unmapped_area()
Generic get_unmapped_area() function does sanity checks of address and length of the area to be mapped. Yet, it lacks checking against mmap_min_addr and mmap_end limits. At the same time the default implementation of functions arch_get_unmapped_area[_topdown]() and some architecture callbacks do mmap_min_addr and mmap_end checks on their own. Put additional checks into the generic code and do not let architecture callbacks to get away with a possible area outside of the allowed limits. That could also relieve arch_get_unmapped_area[_topdown]() callbacks of own address and length sanity checks. Link: http://lkml.kernel.org/r/d14f2cff3c891ef2c4b0337d737c6f04beacb124.1584958099.git.agordeev@linux.ibm.com Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
-rw-r--r--mm/mmap.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/mm/mmap.c b/mm/mmap.c
index 82c381fd8daa..854aefd90cd9 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2208,12 +2208,13 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
unsigned long (*get_area)(struct file *, unsigned long,
unsigned long, unsigned long, unsigned long);
+ const unsigned long mmap_end = arch_get_mmap_end(addr);
unsigned long error = arch_mmap_check(addr, len, flags);
if (error)
return error;
/* Careful about overflows.. */
- if (len > TASK_SIZE)
+ if (len > mmap_end - mmap_min_addr)
return -ENOMEM;
get_area = current->mm->get_unmapped_area;
@@ -2234,7 +2235,7 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
if (IS_ERR_VALUE(addr))
return addr;
- if (addr > TASK_SIZE - len)
+ if ((addr < mmap_min_addr) || (addr > mmap_end - len))
return -ENOMEM;
if (offset_in_page(addr))
return -EINVAL;