summaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
authorLaura Abbott <labbott@fedoraproject.org>2016-03-15 17:56:30 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-03-15 19:55:16 -0400
commit1414c7f4f7d72d138fff35f00151d15749b5beda (patch)
treee742e525f02ae4095e2a907cf8bc5fc29bfbc3dc /mm/page_alloc.c
parent8823b1dbc05fab1a8bec275eeae4709257c2661d (diff)
mm/page_poisoning.c: allow for zero poisoning
By default, page poisoning uses a poison value (0xaa) on free. If this is changed to 0, the page is not only sanitized but zeroing on alloc with __GFP_ZERO can be skipped as well. The tradeoff is that detecting corruption from the poisoning is harder to detect. This feature also cannot be used with hibernation since pages are not guaranteed to be zeroed after hibernation. Credit to Grsecurity/PaX team for inspiring this work Signed-off-by: Laura Abbott <labbott@fedoraproject.org> Acked-by: Rafael J. Wysocki <rjw@rjwysocki.net> Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: Michal Hocko <mhocko@suse.com> Cc: Kees Cook <keescook@chromium.org> Cc: Mathias Krause <minipli@googlemail.com> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Jianyu Zhan <nasa4836@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r--mm/page_alloc.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 2a08349fbab2..50897dcaefdb 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1405,15 +1405,24 @@ static inline int check_new_page(struct page *page)
1405 return 0; 1405 return 0;
1406} 1406}
1407 1407
1408static inline bool free_pages_prezeroed(bool poisoned)
1409{
1410 return IS_ENABLED(CONFIG_PAGE_POISONING_ZERO) &&
1411 page_poisoning_enabled() && poisoned;
1412}
1413
1408static int prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags, 1414static int prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags,
1409 int alloc_flags) 1415 int alloc_flags)
1410{ 1416{
1411 int i; 1417 int i;
1418 bool poisoned = true;
1412 1419
1413 for (i = 0; i < (1 << order); i++) { 1420 for (i = 0; i < (1 << order); i++) {
1414 struct page *p = page + i; 1421 struct page *p = page + i;
1415 if (unlikely(check_new_page(p))) 1422 if (unlikely(check_new_page(p)))
1416 return 1; 1423 return 1;
1424 if (poisoned)
1425 poisoned &= page_is_poisoned(p);
1417 } 1426 }
1418 1427
1419 set_page_private(page, 0); 1428 set_page_private(page, 0);
@@ -1424,7 +1433,7 @@ static int prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags,
1424 kernel_poison_pages(page, 1 << order, 1); 1433 kernel_poison_pages(page, 1 << order, 1);
1425 kasan_alloc_pages(page, order); 1434 kasan_alloc_pages(page, order);
1426 1435
1427 if (gfp_flags & __GFP_ZERO) 1436 if (!free_pages_prezeroed(poisoned) && (gfp_flags & __GFP_ZERO))
1428 for (i = 0; i < (1 << order); i++) 1437 for (i = 0; i < (1 << order); i++)
1429 clear_highpage(page + i); 1438 clear_highpage(page + i);
1430 1439