summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSuren Baghdasaryan <surenb@google.com>2023-01-09 09:56:50 -0800
committerSuren Baghdasaryan <surenb@google.com>2023-01-10 19:00:47 +0000
commite717e149a36da7598fadee967f81e2c941255c7c (patch)
tree48bbf99844992afddda7a80857bb12f415797086
parentc9b27cac74adb563548f4adf94cc5a2a72e9be48 (diff)
downloadcommon-deprecated/android13-5.15-2022-07.tar.gz
ANDROID: mm: fix vma refcounting for SPF in vm_area_dupandroid13-5.15-2022-07_r9deprecated/android13-5.15-2022-07android13-5.15-2022-07
vm_area_dup() should reset the vma refcount to avoid leaking the newly created vma in case the original vma being copies has an elevated refcount due to concurrent page fault. Fixes: d9d7f843da68 ("ANDROID: mm: introduce vma refcounting to protect vma during SPF") Bug: 253557903 Bug: 264935773 Change-Id: I11324ac5661823e9c97b71afe6a894a094439960 Signed-off-by: Suren Baghdasaryan <surenb@google.com> (cherry picked from commit c24377e58ac888484c9a613074b2ea0c76ee7e95)
-rw-r--r--include/linux/mm.h15
-rw-r--r--kernel/fork.c2
2 files changed, 11 insertions, 6 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 6a5ba79d2abc..80b60b652394 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -679,6 +679,15 @@ struct vm_operations_struct {
ANDROID_KABI_RESERVE(4);
};
+static inline void INIT_VMA(struct vm_area_struct *vma)
+{
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+ /* Start from 0 to use atomic_inc_unless_negative() in get_vma() */
+ atomic_set(&vma->file_ref_count, 0);
+#endif
+ INIT_LIST_HEAD(&vma->anon_vma_chain);
+}
+
static inline void vma_init(struct vm_area_struct *vma, struct mm_struct *mm)
{
static const struct vm_operations_struct dummy_vm_ops = {};
@@ -686,11 +695,7 @@ static inline void vma_init(struct vm_area_struct *vma, struct mm_struct *mm)
memset(vma, 0, sizeof(*vma));
vma->vm_mm = mm;
vma->vm_ops = &dummy_vm_ops;
-#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
- /* Start from 0 to use atomic_inc_unless_negative() in get_vma() */
- atomic_set(&vma->file_ref_count, 0);
-#endif
- INIT_LIST_HEAD(&vma->anon_vma_chain);
+ INIT_VMA(vma);
}
static inline void vma_set_anonymous(struct vm_area_struct *vma)
diff --git a/kernel/fork.c b/kernel/fork.c
index f1322d80bb33..6baf0a9a1d36 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -374,7 +374,7 @@ struct vm_area_struct *vm_area_dup(struct vm_area_struct *orig)
* will be reinitialized.
*/
*new = data_race(*orig);
- INIT_LIST_HEAD(&new->anon_vma_chain);
+ INIT_VMA(new);
new->vm_next = new->vm_prev = NULL;
dup_anon_vma_name(orig, new);
}