On Thu, Sep 01, 2022 at 09:22:30PM +0200, Jann Horn wrote: > commit 2555283eb40df89945557273121e9393ef9b542b upstream. > > anon_vma->degree tracks the combined number of child anon_vmas and VMAs > that use the anon_vma as their ->anon_vma. > > anon_vma_clone() then assumes that for any anon_vma attached to > src->anon_vma_chain other than src->anon_vma, it is impossible for it to > be a leaf node of the VMA tree, meaning that for such VMAs ->degree is > elevated by 1 because of a child anon_vma, meaning that if ->degree > equals 1 there are no VMAs that use the anon_vma as their ->anon_vma. > > This assumption is wrong because the ->degree optimization leads to leaf > nodes being abandoned on anon_vma_clone() - an existing anon_vma is > reused and no new parent-child relationship is created. So it is > possible to reuse an anon_vma for one VMA while it is still tied to > another VMA. > > This is an issue because is_mergeable_anon_vma() and its callers assume > that if two VMAs have the same ->anon_vma, the list of anon_vmas > attached to the VMAs is guaranteed to be the same. When this assumption > is violated, vma_merge() can merge pages into a VMA that is not attached > to the corresponding anon_vma, leading to dangling page->mapping > pointers that will be dereferenced during rmap walks. > > Fix it by separately tracking the number of child anon_vmas and the > number of VMAs using the anon_vma as their ->anon_vma. > > Fixes: 7a3ef208e662 ("mm: prevent endless growth of anon_vma hierarchy") > Cc: stable@xxxxxxxxxx > Acked-by: Michal Hocko <mhocko@xxxxxxxx> > Acked-by: Vlastimil Babka <vbabka@xxxxxxx> > Signed-off-by: Jann Horn <jannh@xxxxxxxxxx> > Signed-off-by: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> > [manually fixed up different indentation in stable] Thanks, now queued up. greg k-h