From: David Rientjes <rientjes@xxxxxxxxxx> Subject: mm, page_alloc: make first_page visible before PageTail Commit bf6bddf1924e ("mm: introduce compaction and migration for ballooned pages") introduces page_count(page) into memory compaction which dereferences page->first_page if PageTail(page). This results in a very rare NULL pointer dereference on the aforementioned page_count(page). Indeed, anything that does compound_head(), including page_count() is susceptible to racing with prep_compound_page() and seeing a NULL or dangling page->first_page pointer. This patch uses Andrea's implementation of compound_trans_head() that deals with such a race and makes it the default compound_head() implementation. This includes a read memory barrier that ensures that if PageTail(head) is true that we return a head page that is neither NULL nor dangling. The patch then adds a store memory barrier to prep_compound_page() to ensure page->first_page is set. Hugetlbfs is the exception, we don't enforce a store memory barrier Signed-off-by: David Rientjes <rientjes@xxxxxxxxxx> Reported-by: Holger Kiehl <Holger.Kiehl@xxxxxx> Cc: Holger Kiehl <Holger.Kiehl@xxxxxx> Cc: Christoph Lameter <cl@xxxxxxxxx> Cc: Rafael Aquini <aquini@xxxxxxxxxx> Cc: Vlastimil Babka <vbabka@xxxxxxx> Cc: Michal Hocko <mhocko@xxxxxxx> Cc: Mel Gorman <mgorman@xxxxxxx> Cc: Andrea Arcangeli <aarcange@xxxxxxxxxx> Cc: Rik van Riel <riel@xxxxxxxxxx> Cc: "Kirill A. Shutemov" <kirill.shutemov@xxxxxxxxxxxxxxx> Cc: <stable@xxxxxxxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- mm/page_alloc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff -puN mm/page_alloc.c~mm-page_alloc-make-first_page-visible-before-pagetail mm/page_alloc.c --- a/mm/page_alloc.c~mm-page_alloc-make-first_page-visible-before-pagetail +++ a/mm/page_alloc.c @@ -369,9 +369,11 @@ void prep_compound_page(struct page *pag __SetPageHead(page); for (i = 1; i < nr_pages; i++) { struct page *p = page + i; - __SetPageTail(p); set_page_count(p, 0); p->first_page = page; + /* Make sure p->first_page is always valid for PageTail() */ + smp_wmb(); + __SetPageTail(p); } } _ -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html