diff --git a/mm/mprotect.c b/mm/mprotect.c index 5c175d46d4cb..6d2568b42c1d 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -44,6 +44,8 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd, spinlock_t *ptl; unsigned long pages = 0; int target_node = NUMA_NO_NODE; + bool anon_writable = + vma_is_anonymous(vma) && (vma->vm_flags & VM_WRITE); /* * Can be called with only the mmap_sem for reading by @@ -120,7 +122,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(mm, addr, pte, ptent); pages++; } else if (IS_ENABLED(CONFIG_MIGRATION)) {