1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/kernel.h> 3 #include <linux/string.h> 4 #include <linux/mm.h> 5 #include <linux/highmem.h> 6 #include <linux/page_ext.h> 7 #include <linux/poison.h> 8 #include <linux/ratelimit.h> 9 10 static bool want_page_poisoning __read_mostly; 11 12 static int __init early_page_poison_param(char *buf) 13 { 14 if (!buf) 15 return -EINVAL; 16 return strtobool(buf, &want_page_poisoning); 17 } 18 early_param("page_poison", early_page_poison_param); 19 20 /** 21 * page_poisoning_enabled - check if page poisoning is enabled 22 * 23 * Return true if page poisoning is enabled, or false if not. 24 */ 25 bool page_poisoning_enabled(void) 26 { 27 /* 28 * Assumes that debug_pagealloc_enabled is set before 29 * memblock_free_all. 30 * Page poisoning is debug page alloc for some arches. If 31 * either of those options are enabled, enable poisoning. 32 */ 33 return (want_page_poisoning || 34 (!IS_ENABLED(CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC) && 35 debug_pagealloc_enabled())); 36 } 37 EXPORT_SYMBOL_GPL(page_poisoning_enabled); 38 39 static void poison_page(struct page *page) 40 { 41 void *addr = kmap_atomic(page); 42 43 memset(addr, PAGE_POISON, PAGE_SIZE); 44 kunmap_atomic(addr); 45 } 46 47 static void poison_pages(struct page *page, int n) 48 { 49 int i; 50 51 for (i = 0; i < n; i++) 52 poison_page(page + i); 53 } 54 55 static bool single_bit_flip(unsigned char a, unsigned char b) 56 { 57 unsigned char error = a ^ b; 58 59 return error && !(error & (error - 1)); 60 } 61 62 static void check_poison_mem(unsigned char *mem, size_t bytes) 63 { 64 static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 10); 65 unsigned char *start; 66 unsigned char *end; 67 68 if (IS_ENABLED(CONFIG_PAGE_POISONING_NO_SANITY)) 69 return; 70 71 start = memchr_inv(mem, PAGE_POISON, bytes); 72 if (!start) 73 return; 74 75 for (end = mem + bytes - 1; end > start; end--) { 76 if (*end != PAGE_POISON) 77 break; 78 } 79 80 if (!__ratelimit(&ratelimit)) 81 return; 82 else if (start == end && single_bit_flip(*start, PAGE_POISON)) 83 pr_err("pagealloc: single bit error\n"); 84 else 85 pr_err("pagealloc: memory corruption\n"); 86 87 print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1, start, 88 end - start + 1, 1); 89 dump_stack(); 90 } 91 92 static void unpoison_page(struct page *page) 93 { 94 void *addr; 95 96 addr = kmap_atomic(page); 97 /* 98 * Page poisoning when enabled poisons each and every page 99 * that is freed to buddy. Thus no extra check is done to 100 * see if a page was posioned. 101 */ 102 check_poison_mem(addr, PAGE_SIZE); 103 kunmap_atomic(addr); 104 } 105 106 static void unpoison_pages(struct page *page, int n) 107 { 108 int i; 109 110 for (i = 0; i < n; i++) 111 unpoison_page(page + i); 112 } 113 114 void kernel_poison_pages(struct page *page, int numpages, int enable) 115 { 116 if (!page_poisoning_enabled()) 117 return; 118 119 if (enable) 120 unpoison_pages(page, numpages); 121 else 122 poison_pages(page, numpages); 123 } 124 125 #ifndef CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC 126 void __kernel_map_pages(struct page *page, int numpages, int enable) 127 { 128 /* This function does nothing, all work is done via poison pages */ 129 } 130 #endif 131