From f5364ba0272142dc8c23b737713bb003d41a513f Mon Sep 17 00:00:00 2001 From: Yuanhe Shu Date: Thu, 27 Aug 2026 22:02:33 +0800 Subject: [PATCH] anolis: mm/madvise: fix use-after-free of vma in madvise_vma_behavior() ANBZ: #44821 The anolis backport of "mm: thp: remove vm_flags parameter from khugepaged_enter_vma()" (commit 9f7312507fd0) moved the khugepaged registration for MADV_HUGEPAGE from hugepage_madvise() to after the madvise_update_vma() call in madvise_vma_behavior(): error = madvise_update_vma(vma, prev, start, end, new_flags, anon_name); ... if (!error && new_flags & VM_HUGEPAGE) khugepaged_enter_mm(vma->vm_mm); On the v6.6 code base, madvise_update_vma() may merge the vma into its predecessor via vma_merge() -> vma_complete(), which unlinks the vma and frees it through vm_area_free() -> call_rcu(). The caller's vma pointer then dangles, and reading vma->vm_mm afterwards is a use-after-free: BUG: KASAN: slab-use-after-free in madvise_vma_behavior+0xa84/0xee0 Read of size 8 at ... by task transhuge-stress Freed by task 0: kmem_cache_free <- rcu_do_batch <- rcu_core Last potentially related work creation: __call_rcu_common <- vma_complete <- vma_merge <- madvise_update_vma The upstream version of this change is safe because mainline's madvise_update_vma() updates madv_behavior->vma to the surviving vma, which v6.6's signature cannot do. Fix it by capturing mm before madvise_update_vma(); the mm_struct is guaranteed to be alive while mmap_lock is held by the caller. [backport note] Verified on x86_64 with a KASAN+debug kernel (preempt=full, rcu_expedited=1, 32 madvise-hammering processes pinned on 8 CPUs): the unpatched kernel hits the above KASAN report within ~21s while the patched kernel survives two full 150s rounds with zero reports. Fixes: 9f7312507fd0 ("mm: thp: remove vm_flags parameter from khugepaged_enter_vma()") Signed-off-by: Yuanhe Shu --- mm/madvise.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mm/madvise.c b/mm/madvise.c index 1acfdcd8ea44..455cbe7e17a3 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -1042,6 +1042,7 @@ static int madvise_vma_behavior(struct vm_area_struct *vma, int error; struct anon_vma_name *anon_name; unsigned long new_flags = vma->vm_flags; + struct mm_struct *mm = vma->vm_mm; async_fork_fixup_vma(vma); @@ -1123,7 +1124,7 @@ static int madvise_vma_behavior(struct vm_area_struct *vma, * may not happen any time soon. */ if (!error && new_flags & VM_HUGEPAGE) - khugepaged_enter_mm(vma->vm_mm); + khugepaged_enter_mm(mm); out: /* * madvise() returns EAGAIN if kernel resources, such as -- Gitee