-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
mm/page_alloc.c: fix freeing non-compound pages
Here is a very rare race which leaks memory: Page P0 is allocated to the page cache. Page P1 is free. Thread A Thread B Thread C find_get_entry(): xas_load() returns P0 Removes P0 from page cache P0 finds its buddy P1 alloc_pages(GFP_KERNEL, 1) returns P0 P0 has refcount 1 page_cache_get_speculative(P0) P0 has refcount 2 __free_pages(P0) P0 has refcount 1 put_page(P0) P1 is not freed Fix this by freeing all the pages in __free_pages() that won't be freed by the call to put_page(). It's usually not a good idea to split a page, but this is a very unlikely scenario. Fixes: e286781 ("mm: speculative page references") Signed-off-by: Matthew Wilcox (Oracle) <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Acked-by: Mike Rapoport <[email protected]> Cc: Nick Piggin <[email protected]> Cc: Hugh Dickins <[email protected]> Cc: Peter Zijlstra <[email protected]> Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Linus Torvalds <[email protected]>
- Loading branch information
Showing
4 changed files
with
55 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// SPDX-License-Identifier: GPL-2.0+ | ||
/* | ||
* test_free_pages.c: Check that free_pages() doesn't leak memory | ||
* Copyright (c) 2020 Oracle | ||
* Author: Matthew Wilcox <[email protected]> | ||
*/ | ||
|
||
#include <linux/gfp.h> | ||
#include <linux/mm.h> | ||
#include <linux/module.h> | ||
|
||
static void test_free_pages(gfp_t gfp) | ||
{ | ||
unsigned int i; | ||
|
||
for (i = 0; i < 1000 * 1000; i++) { | ||
unsigned long addr = __get_free_pages(gfp, 3); | ||
struct page *page = virt_to_page(addr); | ||
|
||
/* Simulate page cache getting a speculative reference */ | ||
get_page(page); | ||
free_pages(addr, 3); | ||
put_page(page); | ||
} | ||
} | ||
|
||
static int m_in(void) | ||
{ | ||
test_free_pages(GFP_KERNEL); | ||
test_free_pages(GFP_KERNEL | __GFP_COMP); | ||
|
||
return 0; | ||
} | ||
|
||
static void m_ex(void) | ||
{ | ||
} | ||
|
||
module_init(m_in); | ||
module_exit(m_ex); | ||
MODULE_AUTHOR("Matthew Wilcox <[email protected]>"); | ||
MODULE_LICENSE("GPL"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters