From e717e149a36da7598fadee967f81e2c941255c7c Mon Sep 17 00:00:00 2001 From: Suren Baghdasaryan Date: Mon, 9 Jan 2023 09:56:50 -0800 Subject: ANDROID: mm: fix vma refcounting for SPF in vm_area_dup 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 (cherry picked from commit c24377e58ac888484c9a613074b2ea0c76ee7e95) --- include/linux/mm.h | 15 ++++++++++----- kernel/fork.c | 2 +- 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); } -- cgit v1.2.3