diff --git a/mm/mprotect.c b/mm/mprotect.c index a2a62d62a8b5..380be7b59a0f 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -47,6 +47,8 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, bool prot_numa = cp_flags & MM_CP_PROT_NUMA; bool uffd_wp = cp_flags & MM_CP_UFFD_WP; bool uffd_wp_resolve = cp_flags & MM_CP_UFFD_WP_RESOLVE; + bool anon_writable = + vma_is_anonymous(vma) && (vma->vm_flags & VM_WRITE); /* * Can be called with only the mmap_lock for reading by @@ -136,7 +138,11 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, (pte_soft_dirty(ptent) || !(vma->vm_flags & VM_SOFTDIRTY))) { ptent = pte_mkwrite(ptent); + } else if (anon_writable && + page_mapcount(pte_page(ptent)) == 1) { + ptent = pte_mkwrite(ptent); } + ptep_modify_prot_commit(vma, addr, pte, oldpte, ptent); pages++; } else if (is_swap_pte(oldpte)) {