aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mm/mmap.c4
-rw-r--r--mm/rmap.c7
2 files changed, 8 insertions, 3 deletions
diff --git a/mm/mmap.c b/mm/mmap.c
index 48f6efd..94f4e34 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -541,10 +541,8 @@ again: remove_next = 1 + (end > next->vm_end);
importer->anon_vma = exporter->anon_vma;
error = anon_vma_clone(importer, exporter);
- if (error) {
- importer->anon_vma = NULL;
+ if (error)
return error;
- }
}
}
diff --git a/mm/rmap.c b/mm/rmap.c
index 2c4ee3e..98f0bf7 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -295,6 +295,13 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
return 0;
enomem_failure:
+ /*
+ * dst->anon_vma is dropped here otherwise its degree can be incorrectly
+ * decremented in unlink_anon_vmas().
+ * We can safely do this because callers of anon_vma_clone() don't care
+ * about dst->anon_vma if anon_vma_clone() failed.
+ */
+ dst->anon_vma = NULL;
unlink_anon_vmas(dst);
return -ENOMEM;
}