[PATCH OLK-6.6] mm: fix bad page state in remap_try_huge_pmd() on non-empty PMD entry
remap_try_huge_pmd() called pmd_free_pte_page() to free an existing PTE page table when the PMD entry was present. However, pmd_free_pte_page() uses the kernel page-table free path, which is not appropriate for user mappings. When the PMD entry is non-empty, this results in the underlying page being freed through the kernel page-table free path (__pmd_free_pte_page -> __free_pages -> free_unref_page), corrupting page state and triggering: BUG: Bad page state in process drv_hlt_dsmi_te pfn:809a2b04 page: refcount:0 mapcount:0 ... page_type: 0xfffffdff(table) page dumped because: nonzero mapcount Call trace: bad_page+0xa0/0x1f8 free_unref_page+0xb58/0x1050 __pmd_free_pte_page.part.0+0x10c/0x1f8 pmd_free_pte_page+0x4c/0x78 remap_try_huge_pmd+0x134/0x468 remap_pfn_range_internal+0x334/0x690 remap_pfn_range_try_pmd+0xb4/0x138 When the PMD entry is non-empty, fall back to 4K granularity mapping instead of attempting to free the page table. Rather than simply switching to the user page table free path, the original logic is dropped entirely because it assumes the PTE table is empty without actually checking. If a driver maps the same range repeatedly, the PTE table may still contain valid entries, and freeing it would silently destroy existing mappings without any error. Falling back to 4K granularity avoids both the wrong free path and the risk of silently corrupting existing mappings. Fixes: 923e224a1246 ("mm: introduce remap_pfn_range_try_pmd() for PMD-level hugepage mapping") --- mm/memory.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index f98116b7b23e..7fc3eebcf1ea 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2605,18 +2605,24 @@ static int remap_try_huge_pmd(struct mm_struct *mm, pmd_t *pmd, if (!IS_ALIGNED(pfn, HPAGE_PMD_NR)) return 0; - if (pmd_present(*pmd) && !pmd_free_pte_page(pmd, addr)) + if (!pmd_none(*pmd)) return 0; pgtable = pte_alloc_one(mm); if (unlikely(!pgtable)) return 0; - mm_inc_nr_ptes(mm); ptl = pmd_lock(mm, pmd); + if (!pmd_none(*pmd)) { + spin_unlock(ptl); + pte_free(mm, pgtable); + return 0; + } + set_pmd_at(mm, addr, pmd, pmd_mkspecial(pmd_mkhuge(pfn_pmd(pfn, prot)))); pgtable_trans_huge_deposit(mm, pmd, pgtable); spin_unlock(ptl); + mm_inc_nr_ptes(mm); return 1; } -- 2.43.0
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/28629 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/KS6... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://atomgit.com/openeuler/kernel/merge_requests/28629 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/KS6...
participants (2)
-
Jinjiang Tu -
patchwork bot