[PATCH v3 1/4] mm: hugetlb: disable freeing vmemmap pages when struct page crosses page boundaries

From: Muchun Song
Date: Mon Mar 07 2022 - 08:08:46 EST


If the size of "struct page" is not the power of two and this
feature is enabled, then the vmemmap pages of HugeTLB will be
corrupted after remapping (panic is about to happen in theory).
But this only exists when !CONFIG_MEMCG && !CONFIG_SLUB on
x86_64. However, it is not a conventional configuration nowadays.
So it is not a real word issue, just the result of a code review.
But we cannot prevent anyone from configuring that combined
configure. This feature should be disable in this case to fix
this issue.

Signed-off-by: Muchun Song <songmuchun@xxxxxxxxxxxxx>
---
mm/hugetlb_vmemmap.c | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/mm/hugetlb_vmemmap.c b/mm/hugetlb_vmemmap.c
index b3118dba0518..49bc7f845438 100644
--- a/mm/hugetlb_vmemmap.c
+++ b/mm/hugetlb_vmemmap.c
@@ -121,6 +121,18 @@ void __init hugetlb_vmemmap_init(struct hstate *h)
if (!hugetlb_free_vmemmap_enabled())
return;

+ if (IS_ENABLED(CONFIG_HUGETLB_PAGE_FREE_VMEMMAP_DEFAULT_ON) &&
+ !is_power_of_2(sizeof(struct page))) {
+ /*
+ * The hugetlb_free_vmemmap_enabled_key can be enabled when
+ * CONFIG_HUGETLB_PAGE_FREE_VMEMMAP_DEFAULT_ON. It should
+ * be disabled if "struct page" crosses page boundaries.
+ */
+ pr_warn_once("cannot free vmemmap pages because \"struct page\" crosses page boundaries\n");
+ static_branch_disable(&hugetlb_free_vmemmap_enabled_key);
+ return;
+ }
+
vmemmap_pages = (nr_pages * sizeof(struct page)) >> PAGE_SHIFT;
/*
* The head page is not to be freed to buddy allocator, the other tail
--
2.11.0