From: Greg Kroah-Hartman Date: Mon, 4 Feb 2019 09:42:58 +0000 (+0100) Subject: 3.18-stable patches X-Git-Tag: v4.20.7~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b351be8f112d65ad04eabcc91ff252d9bf2bf3b8;p=thirdparty%2Fkernel%2Fstable-queue.git 3.18-stable patches added patches: mm-migrate-don-t-rely-on-__pagemovable-of-newpage-after-unlocking-it.patch --- diff --git a/queue-3.18/mm-migrate-don-t-rely-on-__pagemovable-of-newpage-after-unlocking-it.patch b/queue-3.18/mm-migrate-don-t-rely-on-__pagemovable-of-newpage-after-unlocking-it.patch new file mode 100644 index 00000000000..dbdbc44b027 --- /dev/null +++ b/queue-3.18/mm-migrate-don-t-rely-on-__pagemovable-of-newpage-after-unlocking-it.patch @@ -0,0 +1,106 @@ +From e0a352fabce61f730341d119fbedf71ffdb8663f Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Fri, 1 Feb 2019 14:21:19 -0800 +Subject: mm: migrate: don't rely on __PageMovable() of newpage after unlocking it + +From: David Hildenbrand + +commit e0a352fabce61f730341d119fbedf71ffdb8663f upstream. + +We had a race in the old balloon compaction code before b1123ea6d3b3 +("mm: balloon: use general non-lru movable page feature") refactored it +that became visible after backporting 195a8c43e93d ("virtio-balloon: +deflate via a page list") without the refactoring. + +The bug existed from commit d6d86c0a7f8d ("mm/balloon_compaction: +redesign ballooned pages management") till b1123ea6d3b3 ("mm: balloon: +use general non-lru movable page feature"). d6d86c0a7f8d +("mm/balloon_compaction: redesign ballooned pages management") was +backported to 3.12, so the broken kernels are stable kernels [3.12 - +4.7]. + +There was a subtle race between dropping the page lock of the newpage in +__unmap_and_move() and checking for __is_movable_balloon_page(newpage). + +Just after dropping this page lock, virtio-balloon could go ahead and +deflate the newpage, effectively dequeueing it and clearing PageBalloon, +in turn making __is_movable_balloon_page(newpage) fail. + +This resulted in dropping the reference of the newpage via +putback_lru_page(newpage) instead of put_page(newpage), leading to +page->lru getting modified and a !LRU page ending up in the LRU lists. +With 195a8c43e93d ("virtio-balloon: deflate via a page list") +backported, one would suddenly get corrupted lists in +release_pages_balloon(): + +- WARNING: CPU: 13 PID: 6586 at lib/list_debug.c:59 __list_del_entry+0xa1/0xd0 +- list_del corruption. prev->next should be ffffe253961090a0, but was dead000000000100 + +Nowadays this race is no longer possible, but it is hidden behind very +ugly handling of __ClearPageMovable() and __PageMovable(). + +__ClearPageMovable() will not make __PageMovable() fail, only +PageMovable(). So the new check (__PageMovable(newpage)) will still +hold even after newpage was dequeued by virtio-balloon. + +If anybody would ever change that special handling, the BUG would be +introduced again. So instead, make it explicit and use the information +of the original isolated page before migration. + +This patch can be backported fairly easy to stable kernels (in contrast +to the refactoring). + +Link: http://lkml.kernel.org/r/20190129233217.10747-1-david@redhat.com +Fixes: d6d86c0a7f8d ("mm/balloon_compaction: redesign ballooned pages management") +Signed-off-by: David Hildenbrand +Reported-by: Vratislav Bendel +Acked-by: Michal Hocko +Acked-by: Rafael Aquini +Cc: Mel Gorman +Cc: "Kirill A. Shutemov" +Cc: Michal Hocko +Cc: Naoya Horiguchi +Cc: Jan Kara +Cc: Andrea Arcangeli +Cc: Dominik Brodowski +Cc: Matthew Wilcox +Cc: Vratislav Bendel +Cc: Rafael Aquini +Cc: Konstantin Khlebnikov +Cc: Minchan Kim +Cc: [3.12 - 4.7] +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: David Hildenbrand +Signed-off-by: Greg Kroah-Hartman +--- + mm/migrate.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/mm/migrate.c ++++ b/mm/migrate.c +@@ -943,6 +943,7 @@ static int unmap_and_move(new_page_t get + int rc = 0; + int *result = NULL; + struct page *newpage = get_new_page(page, private, &result); ++ bool is_lru = !isolated_balloon_page(page); + + if (!newpage) + return -ENOMEM; +@@ -975,12 +976,14 @@ out: + /* + * If migration was not successful and there's a freeing callback, use + * it. Otherwise, putback_lru_page() will drop the reference grabbed +- * during isolation. ++ * during isolation. Use the old state of the isolated source page to ++ * determine if we migrated a LRU page. newpage was already unlocked ++ * and possibly modified by its owner - don't rely on the page state. + */ + if (rc != MIGRATEPAGE_SUCCESS && put_new_page) { + ClearPageSwapBacked(newpage); + put_new_page(newpage, private); +- } else if (unlikely(__is_movable_balloon_page(newpage))) { ++ } else if (rc == MIGRATEPAGE_SUCCESS && unlikely(!is_lru)) { + /* drop our reference, page already in the balloon */ + put_page(newpage); + } else diff --git a/queue-3.18/series b/queue-3.18/series index 2a215435ced..cc5dc22df27 100644 --- a/queue-3.18/series +++ b/queue-3.18/series @@ -28,3 +28,4 @@ gfs2-revert-fix-loop-in-gfs2_rbm_find.patch platform-x86-asus-nb-wmi-map-0x35-to-key_screenlock.patch platform-x86-asus-nb-wmi-drop-mapping-of-0x33-and-0x.patch mm-oom-fix-use-after-free-in-oom_kill_process.patch +mm-migrate-don-t-rely-on-__pagemovable-of-newpage-after-unlocking-it.patch