From 215efe779ca0711ff26194c8ea243cf6eb0f4aff Mon Sep 17 00:00:00 2001 From: Laura Abbott Date: Thu, 25 Feb 2016 12:59:28 +1100 Subject: [PATCH] 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 Mathias Krause and grsecurity for original work Signed-off-by: Laura Abbott Cc: "Kirill A. Shutemov" Cc: Vlastimil Babka Cc: Michal Hocko Cc: Kees Cook Cc: Mathias Krause Cc: Dave Hansen Cc: Jianyu Zhan Signed-off-by: Andrew Morton --- include/linux/poison.h | 4 ++++ mm/Kconfig.debug | 13 +++++++++++++ mm/page_alloc.c | 8 +++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/include/linux/poison.h b/include/linux/poison.h index 4a27153574e283..51334edec50681 100644 --- a/include/linux/poison.h +++ b/include/linux/poison.h @@ -30,7 +30,11 @@ #define TIMER_ENTRY_STATIC ((void *) 0x300 + POISON_POINTER_DELTA) /********** mm/debug-pagealloc.c **********/ +#ifdef CONFIG_PAGE_POISONING_ZERO +#define PAGE_POISON 0x00 +#else #define PAGE_POISON 0xaa +#endif /********** mm/page_alloc.c ************/ diff --git a/mm/Kconfig.debug b/mm/Kconfig.debug index ddf71d7cb6ba8d..20973e865fb46c 100644 --- a/mm/Kconfig.debug +++ b/mm/Kconfig.debug @@ -62,3 +62,16 @@ config PAGE_POISONING_NO_SANITY If you are only interested in sanitization, say Y. Otherwise say N. + +config PAGE_POISONING_ZERO + bool "Use zero for poisoning instead of random data" + depends on !HIBERNATION + depends on PAGE_POISONING + ---help--- + Instead of using the existing poison value, fill the pages with + zeros. This makes it harder to detect when errors are occuring + due to sanitization but the zeroing at free means that it is + no longer necessary to write zeros when GFP_ZERO is used on + allocation. + + If unsure, say N diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 8987902186b842..ada80bb7a65915 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1387,6 +1387,12 @@ static inline int check_new_page(struct page *page) return 0; } +static inline bool should_zero(void) +{ + return !IS_ENABLED(CONFIG_PAGE_POISONING_ZERO) || + !page_poisoning_enabled(); +} + static int prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags, int alloc_flags) { @@ -1406,7 +1412,7 @@ static int prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags, kernel_map_pages(page, 1 << order, 1); kasan_alloc_pages(page, order); - if (gfp_flags & __GFP_ZERO) + if (should_zero() && gfp_flags & __GFP_ZERO) for (i = 0; i < (1 << order); i++) clear_highpage(page + i);