mm: security: introduce init_on_alloc=1 and init_on_free=1 boot options · torvalds/linux@6471384
@@ -135,6 +135,55 @@ unsigned long totalcma_pages __read_mostly;
135135136136int percpu_pagelist_fraction;
137137gfp_t gfp_allowed_mask __read_mostly = GFP_BOOT_MASK;
138+#ifdef CONFIG_INIT_ON_ALLOC_DEFAULT_ON
139+DEFINE_STATIC_KEY_TRUE(init_on_alloc);
140+#else
141+DEFINE_STATIC_KEY_FALSE(init_on_alloc);
142+#endif
143+EXPORT_SYMBOL(init_on_alloc);
144+145+#ifdef CONFIG_INIT_ON_FREE_DEFAULT_ON
146+DEFINE_STATIC_KEY_TRUE(init_on_free);
147+#else
148+DEFINE_STATIC_KEY_FALSE(init_on_free);
149+#endif
150+EXPORT_SYMBOL(init_on_free);
151+152+static int __init early_init_on_alloc(char *buf)
153+{
154+int ret;
155+bool bool_result;
156+157+if (!buf)
158+return -EINVAL;
159+ret = kstrtobool(buf, &bool_result);
160+if (bool_result && page_poisoning_enabled())
161+pr_info("mem auto-init: CONFIG_PAGE_POISONING is on, will take precedence over init_on_alloc\n");
162+if (bool_result)
163+static_branch_enable(&init_on_alloc);
164+else
165+static_branch_disable(&init_on_alloc);
166+return ret;
167+}
168+early_param("init_on_alloc", early_init_on_alloc);
169+170+static int __init early_init_on_free(char *buf)
171+{
172+int ret;
173+bool bool_result;
174+175+if (!buf)
176+return -EINVAL;
177+ret = kstrtobool(buf, &bool_result);
178+if (bool_result && page_poisoning_enabled())
179+pr_info("mem auto-init: CONFIG_PAGE_POISONING is on, will take precedence over init_on_free\n");
180+if (bool_result)
181+static_branch_enable(&init_on_free);
182+else
183+static_branch_disable(&init_on_free);
184+return ret;
185+}
186+early_param("init_on_free", early_init_on_free);
138187139188/*
140189 * A cached value of the page's pageblock's migratetype, used when the page is
@@ -1067,6 +1116,14 @@ static int free_tail_pages_check(struct page *head_page, struct page *page)
10671116return ret;
10681117}
106911181119+static void kernel_init_free_pages(struct page *page, int numpages)
1120+{
1121+int i;
1122+1123+for (i = 0; i < numpages; i++)
1124+clear_highpage(page + i);
1125+}
1126+10701127static __always_inline bool free_pages_prepare(struct page *page,
10711128unsigned int order, bool check_free)
10721129{
@@ -1118,6 +1175,9 @@ static __always_inline bool free_pages_prepare(struct page *page,
11181175PAGE_SIZE << order);
11191176 }
11201177arch_free_page(page, order);
1178+if (want_init_on_free())
1179+kernel_init_free_pages(page, 1 << order);
1180+11211181kernel_poison_pages(page, 1 << order, 0);
11221182if (debug_pagealloc_enabled())
11231183kernel_map_pages(page, 1 << order, 0);
@@ -2019,8 +2079,8 @@ static inline int check_new_page(struct page *page)
2019207920202080static inline bool free_pages_prezeroed(void)
20212081{
2022-return IS_ENABLED(CONFIG_PAGE_POISONING_ZERO) &&
2023-page_poisoning_enabled();
2082+return (IS_ENABLED(CONFIG_PAGE_POISONING_ZERO) &&
2083+page_poisoning_enabled()) || want_init_on_free();
20242084}
2025208520262086#ifdef CONFIG_DEBUG_VM
@@ -2090,13 +2150,10 @@ inline void post_alloc_hook(struct page *page, unsigned int order,
20902150static void prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags,
20912151unsigned int alloc_flags)
20922152{
2093-int i;
2094-20952153post_alloc_hook(page, order, gfp_flags);
209621542097-if (!free_pages_prezeroed() && (gfp_flags & __GFP_ZERO))
2098-for (i = 0; i < (1 << order); i++)
2099-clear_highpage(page + i);
2155+if (!free_pages_prezeroed() && want_init_on_alloc(gfp_flags))
2156+kernel_init_free_pages(page, 1 << order);
2100215721012158if (order && (gfp_flags & __GFP_COMP))
21022159prep_compound_page(page, order);