diff --git a/mm/vma.c b/mm/vma.c index 88ef92ab24ec..0325b3979313 100644 --- a/mm/vma.c +++ b/mm/vma.c @@ -538,6 +538,7 @@ __split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma, return err; } + vma_start_write(vma); new = vm_area_dup(vma); if (!new) return -ENOMEM; @@ -568,7 +569,6 @@ __split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma, if (new->vm_ops && new->vm_ops->open) new->vm_ops->open(new); - vma_start_write(vma); vma_start_write(new); init_vma_prep(&vp, vma); diff --git a/mm/vma_init.c b/mm/vma_init.c index baa7e82f47e3..d661f229a734 100644 --- a/mm/vma_init.c +++ b/mm/vma_init.c @@ -127,6 +127,9 @@ struct vm_area_struct *vm_area_dup(struct vm_area_struct *orig) { struct vm_area_struct *new = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); + /* Must hold a write lock to stabilise atomic VMA flags. */ + vma_assert_write_locked(orig); + if (!new) return NULL;