[PATCH 1/1] mm/ksm: validate KSM rmap items before hwpoison kill
Longlong Xia <[email protected]> Mon, 3 Aug 2026 23:11:51 +0800
| Newsgroups | org.kvack.linux-mm,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
From: Longlong Xia <[email protected]> collect_procs_ksm() walks the stable-node rmap list and queues an early kill for every task whose mm appears on the anon_vma chain. That rmap item can be stale by the time memory failure handles the poisoned KSM page. A VMA may have been split, unmapped or remapped after the rmap item was recorded, so matching only vma->vm_mm can send SIGBUS with an address that no longer maps the poisoned page. Check that the saved address still belongs to the VMA and that page_vma_mapped_walk() still finds the poisoned page there before adding the task to the kill list. Fixes: 4248d0083ec5 ("mm: ksm: support hwpoison for ksm page") Signed-off-by: Longlong Xia <[email protected]> --- mm/ksm.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/mm/ksm.c b/mm/ksm.c index 7d5b76478f0b..bc4b2dd894d8 100644 --- a/mm/ksm.c +++ b/mm/ksm.c @@ -3222,6 +3222,27 @@ void rmap_walk_ksm(struct folio *folio, struct rmap_walk_control *rwc) } #ifdef CONFIG_MEMORY_FAILURE +static bool ksm_rmap_item_mapped(const struct page *page, + struct vm_area_struct *vma, + unsigned long addr) +{ + struct page_vma_mapped_walk pvmw = { + .pfn = page_to_pfn(page), + .nr_pages = 1, + .vma = vma, + .address = addr, + .flags = PVMW_SYNC, + }; + + if (addr < vma->vm_start || addr >= vma->vm_end) + return false; + if (!page_vma_mapped_walk(&pvmw)) + return false; + page_vma_mapped_walk_done(&pvmw); + + return true; +} + /* * Collect processes when the error hit an ksm page. */ @@ -3237,13 +3258,13 @@ void collect_procs_ksm(const struct folio *folio, const struct page *page, if (!stable_node) return; hlist_for_each_entry(rmap_item, &stable_node->hlist, hlist) { + unsigned long addr = rmap_item->address & PAGE_MASK; struct anon_vma *av = rmap_item->anon_vma; anon_vma_lock_read(av); rcu_read_lock(); for_each_process(tsk) { struct anon_vma_chain *vmac; - unsigned long addr; struct task_struct *t = task_early_kill(tsk, force_early); if (!t) @@ -3253,7 +3274,9 @@ void collect_procs_ksm(const struct folio *folio, const struct page *page, { vma = vmac->vma; if (vma->vm_mm == t->mm) { - addr = rmap_item->address & PAGE_MASK; + if (!ksm_rmap_item_mapped(page, vma, + addr)) + continue; add_to_kill_ksm(t, page, vma, to_kill, addr); } -- 2.43.0