diff options
author | Alexander Gordeev <agordeev@linux.ibm.com> | 2020-05-14 13:41:04 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2020-05-14 20:12:30 +1000 |
commit | 672e180473d27c241f33c3740809bce292771a39 (patch) | |
tree | 18f226d16eb565a50f3588f2ddd121ccbe4721f6 | |
parent | 3b01cce1abe2e78c4c5bb2ee39e5c3a412dae5d4 (diff) | |
download | linux-672e180473d27c241f33c3740809bce292771a39.tar.gz linux-672e180473d27c241f33c3740809bce292771a39.tar.xz |
mm/mmap.c: do not allow mappings outside of allowed limits
One can set a lowest possible address in /proc/sys/vm/mmap_min_addr
and mmap below that bound nevertheless.
It is possible to request a fixed mapping address below mmap_min_addr and
succeed. This update adds early checks of mmap_min_addr and mmap_end
boundaries and fixes the above issue.
Apart from it is wrong I am not aware of any existing issue.
Link: http://lkml.kernel.org/r/d6da1319114a331095052638f0ffa3ccb0be58f1.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.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/mm/mmap.c b/mm/mmap.c index 854aefd90cd9..fae283e3c6fa 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -62,6 +62,14 @@ #define arch_mmap_check(addr, len, flags) (0) #endif +#ifndef arch_get_mmap_end +#define arch_get_mmap_end(addr) (TASK_SIZE) +#endif + +#ifndef arch_get_mmap_base +#define arch_get_mmap_base(addr, base) (base) +#endif + #ifdef CONFIG_HAVE_ARCH_MMAP_RND_BITS const int mmap_rnd_bits_min = CONFIG_ARCH_MMAP_RND_BITS_MIN; const int mmap_rnd_bits_max = CONFIG_ARCH_MMAP_RND_BITS_MAX; @@ -1369,6 +1377,7 @@ unsigned long do_mmap(struct file *file, unsigned long addr, unsigned long pgoff, unsigned long *populate, struct list_head *uf) { + const unsigned long mmap_end = arch_get_mmap_end(addr); struct mm_struct *mm = current->mm; int pkey = 0; @@ -1391,8 +1400,12 @@ unsigned long do_mmap(struct file *file, unsigned long addr, if (flags & MAP_FIXED_NOREPLACE) flags |= MAP_FIXED; - if (!(flags & MAP_FIXED)) + if (flags & MAP_FIXED) { + if ((addr < mmap_min_addr) || (addr > mmap_end)) + return -ENOMEM; + } else { addr = round_hint_to_min(addr); + } /* Careful about overflows.. */ len = PAGE_ALIGN(len); @@ -2089,14 +2102,6 @@ unsigned long vm_unmapped_area(struct vm_unmapped_area_info *info) return addr; } -#ifndef arch_get_mmap_end -#define arch_get_mmap_end(addr) (TASK_SIZE) -#endif - -#ifndef arch_get_mmap_base -#define arch_get_mmap_base(addr, base) (base) -#endif - /* Get an address range which is currently unmapped. * For shmat() with addr=0. * |