From: Sasha Levin Date: Thu, 15 Nov 2018 17:35:57 +0000 (-0500) Subject: queue mm-do-not-bug_on-on-incorrect-length-in-__mm_populat.patch for 4.9 X-Git-Tag: v4.19.3~37 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4801e86a459a35fe26d12986035a6e560bbe34b6;p=thirdparty%2Fkernel%2Fstable-queue.git queue mm-do-not-bug_on-on-incorrect-length-in-__mm_populat.patch for 4.9 Signed-off-by: Sasha Levin --- diff --git a/queue-4.9/mm-do-not-bug_on-on-incorrect-length-in-__mm_populat.patch b/queue-4.9/mm-do-not-bug_on-on-incorrect-length-in-__mm_populat.patch new file mode 100644 index 00000000000..9ed62463c39 --- /dev/null +++ b/queue-4.9/mm-do-not-bug_on-on-incorrect-length-in-__mm_populat.patch @@ -0,0 +1,131 @@ +From b9ef297c61321bc6c592bda54c510d0cb15974dc Mon Sep 17 00:00:00 2001 +From: Michal Hocko +Date: Tue, 13 Nov 2018 16:41:56 +0000 +Subject: mm: do not bug_on on incorrect length in __mm_populate() + +commit bb177a732c4369bb58a1fe1df8f552b6f0f7db5f upstream. + +syzbot has noticed that a specially crafted library can easily hit +VM_BUG_ON in __mm_populate + + kernel BUG at mm/gup.c:1242! + invalid opcode: 0000 [#1] SMP + CPU: 2 PID: 9667 Comm: a.out Not tainted 4.18.0-rc3 #644 + Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 05/19/2017 + RIP: 0010:__mm_populate+0x1e2/0x1f0 + Code: 55 d0 65 48 33 14 25 28 00 00 00 89 d8 75 21 48 83 c4 20 5b 41 5c 41 5d 41 5e 41 5f 5d c3 e8 75 18 f1 ff 0f 0b e8 6e 18 f1 ff <0f> 0b 31 db eb c9 e8 93 06 e0 ff 0f 1f 00 55 48 89 e5 53 48 89 fb + Call Trace: + vm_brk_flags+0xc3/0x100 + vm_brk+0x1f/0x30 + load_elf_library+0x281/0x2e0 + __ia32_sys_uselib+0x170/0x1e0 + do_fast_syscall_32+0xca/0x420 + entry_SYSENTER_compat+0x70/0x7f + +The reason is that the length of the new brk is not page aligned when we +try to populate the it. There is no reason to bug on that though. +do_brk_flags already aligns the length properly so the mapping is +expanded as it should. All we need is to tell mm_populate about it. +Besides that there is absolutely no reason to to bug_on in the first +place. The worst thing that could happen is that the last page wouldn't +get populated and that is far from putting system into an inconsistent +state. + +Fix the issue by moving the length sanitization code from do_brk_flags +up to vm_brk_flags. The only other caller of do_brk_flags is brk +syscall entry and it makes sure to provide the proper length so t here +is no need for sanitation and so we can use do_brk_flags without it. + +Also remove the bogus BUG_ONs. + +[osalvador@techadventures.net: fix up vm_brk_flags s@request@len@] +Link: http://lkml.kernel.org/r/20180706090217.GI32658@dhcp22.suse.cz +Signed-off-by: Michal Hocko +Reported-by: syzbot +Tested-by: Tetsuo Handa +Reviewed-by: Oscar Salvador +Cc: Zi Yan +Cc: "Aneesh Kumar K.V" +Cc: Dan Williams +Cc: "Kirill A. Shutemov" +Cc: Michael S. Tsirkin +Cc: Al Viro +Cc: "Huang, Ying" +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +[bwh: Backported to 4.9: + - There is no do_brk_flags() function; update do_brk() + - Adjust context] +Signed-off-by: Ben Hutchings +Signed-off-by: Sasha Levin +--- + mm/gup.c | 2 -- + mm/mmap.c | 19 ++++++++++--------- + 2 files changed, 10 insertions(+), 11 deletions(-) + +diff --git a/mm/gup.c b/mm/gup.c +index be4ccddac26f..d71da7216c6e 100644 +--- a/mm/gup.c ++++ b/mm/gup.c +@@ -1122,8 +1122,6 @@ int __mm_populate(unsigned long start, unsigned long len, int ignore_errors) + int locked = 0; + long ret = 0; + +- VM_BUG_ON(start & ~PAGE_MASK); +- VM_BUG_ON(len != PAGE_ALIGN(len)); + end = start + len; + + for (nstart = start; nstart < end; nstart = nend) { +diff --git a/mm/mmap.c b/mm/mmap.c +index aa97074a4a99..283755645d17 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -2876,21 +2876,15 @@ static inline void verify_mm_writelocked(struct mm_struct *mm) + * anonymous maps. eventually we may be able to do some + * brk-specific accounting here. + */ +-static int do_brk(unsigned long addr, unsigned long request) ++static int do_brk(unsigned long addr, unsigned long len) + { + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma, *prev; +- unsigned long flags, len; ++ unsigned long flags; + struct rb_node **rb_link, *rb_parent; + pgoff_t pgoff = addr >> PAGE_SHIFT; + int error; + +- len = PAGE_ALIGN(request); +- if (len < request) +- return -ENOMEM; +- if (!len) +- return 0; +- + flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; + + error = get_unmapped_area(NULL, addr, len, 0, MAP_FIXED); +@@ -2959,12 +2953,19 @@ static int do_brk(unsigned long addr, unsigned long request) + return 0; + } + +-int vm_brk(unsigned long addr, unsigned long len) ++int vm_brk(unsigned long addr, unsigned long request) + { + struct mm_struct *mm = current->mm; ++ unsigned long len; + int ret; + bool populate; + ++ len = PAGE_ALIGN(request); ++ if (len < request) ++ return -ENOMEM; ++ if (!len) ++ return 0; ++ + if (down_write_killable(&mm->mmap_sem)) + return -EINTR; + +-- +2.17.1 + diff --git a/queue-4.9/series b/queue-4.9/series index ad295be262a..fb7cc36bcc7 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -19,3 +19,4 @@ fuse-fix-use-after-free-in-fuse_dev_do_read.patch fuse-fix-use-after-free-in-fuse_dev_do_write.patch fuse-fix-blocked_waitq-wakeup.patch fuse-set-fr_sent-while-locked.patch +mm-do-not-bug_on-on-incorrect-length-in-__mm_populat.patch