--- /dev/null
+From b9ef297c61321bc6c592bda54c510d0cb15974dc Mon Sep 17 00:00:00 2001
+From: Michal Hocko <mhocko@suse.com>
+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 <mhocko@suse.com>
+Reported-by: syzbot <syzbot+5dcb560fe12aa5091c06@syzkaller.appspotmail.com>
+Tested-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Reviewed-by: Oscar Salvador <osalvador@suse.de>
+Cc: Zi Yan <zi.yan@cs.rutgers.edu>
+Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
+Cc: Dan Williams <dan.j.williams@intel.com>
+Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
+Cc: Michael S. Tsirkin <mst@redhat.com>
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Cc: "Huang, Ying" <ying.huang@intel.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+[bwh: Backported to 4.9:
+ - There is no do_brk_flags() function; update do_brk()
+ - Adjust context]
+Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+