| From a7306c3436e9c8e584a4b9fad5f3dc91be2a6076 Mon Sep 17 00:00:00 2001 |
| From: Andrea Arcangeli <aarcange@redhat.com> |
| Date: Fri, 2 Jun 2017 14:46:11 -0700 |
| Subject: ksm: prevent crash after write_protect_page fails |
| |
| From: Andrea Arcangeli <aarcange@redhat.com> |
| |
| commit a7306c3436e9c8e584a4b9fad5f3dc91be2a6076 upstream. |
| |
| "err" needs to be left set to -EFAULT if split_huge_page succeeds. |
| Otherwise if "err" gets clobbered with zero and write_protect_page |
| fails, try_to_merge_one_page() will succeed instead of returning -EFAULT |
| and then try_to_merge_with_ksm_page() will continue thinking kpage is a |
| PageKsm when in fact it's still an anonymous page. Eventually it'll |
| crash in page_add_anon_rmap. |
| |
| This has been reproduced on Fedora25 kernel but I can reproduce with |
| upstream too. |
| |
| The bug was introduced in commit f765f540598a ("ksm: prepare to new THP |
| semantics") introduced in v4.5. |
| |
| page:fffff67546ce1cc0 count:4 mapcount:2 mapping:ffffa094551e36e1 index:0x7f0f46673 |
| flags: 0x2ffffc0004007c(referenced|uptodate|dirty|lru|active|swapbacked) |
| page dumped because: VM_BUG_ON_PAGE(!PageLocked(page)) |
| page->mem_cgroup:ffffa09674bf0000 |
| ------------[ cut here ]------------ |
| kernel BUG at mm/rmap.c:1222! |
| CPU: 1 PID: 76 Comm: ksmd Not tainted 4.9.3-200.fc25.x86_64 #1 |
| RIP: do_page_add_anon_rmap+0x1c4/0x240 |
| Call Trace: |
| page_add_anon_rmap+0x18/0x20 |
| try_to_merge_with_ksm_page+0x50b/0x780 |
| ksm_scan_thread+0x1211/0x1410 |
| ? prepare_to_wait_event+0x100/0x100 |
| ? try_to_merge_with_ksm_page+0x780/0x780 |
| kthread+0xd9/0xf0 |
| ? kthread_park+0x60/0x60 |
| ret_from_fork+0x25/0x30 |
| |
| Fixes: f765f54059 ("ksm: prepare to new THP semantics") |
| Link: http://lkml.kernel.org/r/20170513131040.21732-1-aarcange@redhat.com |
| Signed-off-by: Andrea Arcangeli <aarcange@redhat.com> |
| Reported-by: Federico Simoncelli <fsimonce@redhat.com> |
| Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> |
| Cc: Hugh Dickins <hughd@google.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| mm/ksm.c | 3 +-- |
| 1 file changed, 1 insertion(+), 2 deletions(-) |
| |
| --- a/mm/ksm.c |
| +++ b/mm/ksm.c |
| @@ -1002,8 +1002,7 @@ static int try_to_merge_one_page(struct |
| goto out; |
| |
| if (PageTransCompound(page)) { |
| - err = split_huge_page(page); |
| - if (err) |
| + if (split_huge_page(page)) |
| goto out_unlock; |
| } |
| |