| From 34f20027171bc4b26592a689f8793f3a4eaa96a0 Mon Sep 17 00:00:00 2001 |
| From: Johannes Weiner <hannes@cmpxchg.org> |
| Date: Mon, 12 Dec 2016 16:43:32 -0800 |
| Subject: [PATCH] mm: khugepaged: close use-after-free race during shmem |
| collapsing |
| |
| commit 91a45f71078a6569ec3ca5bef74e1ab58121d80e upstream. |
| |
| Patch series "mm: workingset: radix tree subtleties & single-page file |
| refaults", v3. |
| |
| This is another revision of the radix tree / workingset patches based on |
| feedback from Jan and Kirill. |
| |
| This is a follow-up to d3798ae8c6f3 ("mm: filemap: don't plant shadow |
| entries without radix tree node"). That patch fixed an issue that was |
| caused mainly by the page cache sneaking special shadow page entries |
| into the radix tree and relying on subtleties in the radix tree code to |
| make that work. The fix also had to stop tracking refaults for |
| single-page files because shadow pages stored as direct pointers in |
| radix_tree_root->rnode weren't properly handled during tree extension. |
| |
| These patches make the radix tree code explicitely support and track |
| such special entries, to eliminate the subtleties and to restore the |
| thrash detection for single-page files. |
| |
| This patch (of 9): |
| |
| When a radix tree iteration drops the tree lock, another thread might |
| swoop in and free the node holding the current slot. The iteration |
| needs to do another tree lookup from the current index to continue. |
| |
| [kirill.shutemov@linux.intel.com: re-lookup for replacement] |
| Fixes: f3f0e1d2150b ("khugepaged: add support of collapse for tmpfs/shmem pages") |
| Link: http://lkml.kernel.org/r/20161117191138.22769-2-hannes@cmpxchg.org |
| Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> |
| Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> |
| Reviewed-by: Jan Kara <jack@suse.cz> |
| Cc: Hugh Dickins <hughd@google.com> |
| Cc: Matthew Wilcox <mawilcox@linuxonhyperv.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/mm/khugepaged.c b/mm/khugepaged.c |
| index 87e1a7ca3846..2779c63bdea0 100644 |
| --- a/mm/khugepaged.c |
| +++ b/mm/khugepaged.c |
| @@ -1403,6 +1403,9 @@ static void collapse_shmem(struct mm_struct *mm, |
| |
| spin_lock_irq(&mapping->tree_lock); |
| |
| + slot = radix_tree_lookup_slot(&mapping->page_tree, index); |
| + VM_BUG_ON_PAGE(page != radix_tree_deref_slot_protected(slot, |
| + &mapping->tree_lock), page); |
| VM_BUG_ON_PAGE(page_mapped(page), page); |
| |
| /* |
| @@ -1426,6 +1429,7 @@ static void collapse_shmem(struct mm_struct *mm, |
| radix_tree_replace_slot(slot, |
| new_page + (index % HPAGE_PMD_NR)); |
| |
| + slot = radix_tree_iter_next(&iter); |
| index++; |
| continue; |
| out_lru: |
| @@ -1537,6 +1541,7 @@ tree_unlocked: |
| putback_lru_page(page); |
| unlock_page(page); |
| spin_lock_irq(&mapping->tree_lock); |
| + slot = radix_tree_iter_next(&iter); |
| } |
| VM_BUG_ON(nr_none); |
| spin_unlock_irq(&mapping->tree_lock); |
| -- |
| 2.10.1 |
| |