Skip to content

Commit 5b0caf3

Browse files
ljskernelgregkh
authored andcommitted
mm/vma: enforce VMA fork limit on unfaulted,faulted mremap merge too
[ Upstream commit 3b617fd ] The is_mergeable_anon_vma() function uses vmg->middle as the source VMA. However when merging a new VMA, this field is NULL. In all cases except mremap(), the new VMA will either be newly established and thus lack an anon_vma, or will be an expansion of an existing VMA thus we do not care about whether VMA is CoW'd or not. In the case of an mremap(), we can end up in a situation where we can accidentally allow an unfaulted/faulted merge with a VMA that has been forked, violating the general rule that we do not permit this for reasons of anon_vma lock scalability. Now we have the ability to be aware of the fact we are copying a VMA and also know which VMA that is, we can explicitly check for this, so do so. This is pertinent since commit 879bca0 ("mm/vma: fix incorrectly disallowed anonymous VMA merges"), as this patch permits unfaulted/faulted merges that were previously disallowed running afoul of this issue. While we are here, vma_had_uncowed_parents() is a confusing name, so make it simple and rename it to vma_is_fork_child(). Link: https://lkml.kernel.org/r/6e2b9b3024ae1220961c8b81d74296d4720eaf2b.1767638272.git.lorenzo.stoakes@oracle.com Fixes: 879bca0 ("mm/vma: fix incorrectly disallowed anonymous VMA merges") Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> Reviewed-by: Harry Yoo <harry.yoo@oracle.com> Reviewed-by: Jeongjun Park <aha310510@gmail.com> Acked-by: Vlastimil Babka <vbabka@suse.cz> Cc: David Hildenbrand (Red Hat) <david@kernel.org> Cc: Jann Horn <jannh@google.com> Cc: Liam Howlett <liam.howlett@oracle.com> Cc: Pedro Falcato <pfalcato@suse.de> Cc: Rik van Riel <riel@surriel.com> Cc: Yeoreum Yun <yeoreum.yun@arm.com> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> [ with upstream commit 61f67c2 backported, this simply applied correctly. Built + tested ] Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent a4d9dbf commit 5b0caf3

1 file changed

Lines changed: 15 additions & 12 deletions

File tree

mm/vma.c

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -65,18 +65,13 @@ struct mmap_state {
6565
.state = VMA_MERGE_START, \
6666
}
6767

68-
/*
69-
* If, at any point, the VMA had unCoW'd mappings from parents, it will maintain
70-
* more than one anon_vma_chain connecting it to more than one anon_vma. A merge
71-
* would mean a wider range of folios sharing the root anon_vma lock, and thus
72-
* potential lock contention, we do not wish to encourage merging such that this
73-
* scales to a problem.
74-
*/
75-
static bool vma_had_uncowed_parents(struct vm_area_struct *vma)
68+
/* Was this VMA ever forked from a parent, i.e. maybe contains CoW mappings? */
69+
static bool vma_is_fork_child(struct vm_area_struct *vma)
7670
{
7771
/*
7872
* The list_is_singular() test is to avoid merging VMA cloned from
79-
* parents. This can improve scalability caused by anon_vma lock.
73+
* parents. This can improve scalability caused by the anon_vma root
74+
* lock.
8075
*/
8176
return vma && vma->anon_vma && !list_is_singular(&vma->anon_vma_chain);
8277
}
@@ -121,11 +116,19 @@ static bool is_mergeable_anon_vma(struct vma_merge_struct *vmg, bool merge_next)
121116
VM_WARN_ON(src && src_anon != src->anon_vma);
122117

123118
/* Case 1 - we will dup_anon_vma() from src into tgt. */
124-
if (!tgt_anon && src_anon)
125-
return !vma_had_uncowed_parents(src);
119+
if (!tgt_anon && src_anon) {
120+
struct vm_area_struct *copied_from = vmg->copied_from;
121+
122+
if (vma_is_fork_child(src))
123+
return false;
124+
if (vma_is_fork_child(copied_from))
125+
return false;
126+
127+
return true;
128+
}
126129
/* Case 2 - we will simply use tgt's anon_vma. */
127130
if (tgt_anon && !src_anon)
128-
return !vma_had_uncowed_parents(tgt);
131+
return !vma_is_fork_child(tgt);
129132
/* Case 3 - the anon_vma's are already shared. */
130133
return src_anon == tgt_anon;
131134
}

0 commit comments

Comments
 (0)