diff options
-rw-r--r-- | include/linux/mm.h | 2 | ||||
-rw-r--r-- | mm/huge_memory.c | 2 | ||||
-rw-r--r-- | mm/migrate.c | 2 | ||||
-rw-r--r-- | mm/mmap.c | 16 | ||||
-rw-r--r-- | mm/mprotect.c | 2 |
5 files changed, 13 insertions, 11 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h index 3e8807e0b9d2..040a04a88996 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -1517,7 +1517,7 @@ static inline int pte_devmap(pte_t pte) | |||
1517 | } | 1517 | } |
1518 | #endif | 1518 | #endif |
1519 | 1519 | ||
1520 | int vma_wants_writenotify(struct vm_area_struct *vma); | 1520 | int vma_wants_writenotify(struct vm_area_struct *vma, pgprot_t vm_page_prot); |
1521 | 1521 | ||
1522 | extern pte_t *__get_locked_pte(struct mm_struct *mm, unsigned long addr, | 1522 | extern pte_t *__get_locked_pte(struct mm_struct *mm, unsigned long addr, |
1523 | spinlock_t **ptl); | 1523 | spinlock_t **ptl); |
diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 12b9f1a39b63..cdcd25cb30fe 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c | |||
@@ -1620,7 +1620,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd, | |||
1620 | if (soft_dirty) | 1620 | if (soft_dirty) |
1621 | entry = pte_swp_mksoft_dirty(entry); | 1621 | entry = pte_swp_mksoft_dirty(entry); |
1622 | } else { | 1622 | } else { |
1623 | entry = mk_pte(page + i, vma->vm_page_prot); | 1623 | entry = mk_pte(page + i, READ_ONCE(vma->vm_page_prot)); |
1624 | entry = maybe_mkwrite(entry, vma); | 1624 | entry = maybe_mkwrite(entry, vma); |
1625 | if (!write) | 1625 | if (!write) |
1626 | entry = pte_wrprotect(entry); | 1626 | entry = pte_wrprotect(entry); |
diff --git a/mm/migrate.c b/mm/migrate.c index f7ee04a5ae27..99250aee1ac1 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
@@ -234,7 +234,7 @@ static int remove_migration_pte(struct page *new, struct vm_area_struct *vma, | |||
234 | goto unlock; | 234 | goto unlock; |
235 | 235 | ||
236 | get_page(new); | 236 | get_page(new); |
237 | pte = pte_mkold(mk_pte(new, vma->vm_page_prot)); | 237 | pte = pte_mkold(mk_pte(new, READ_ONCE(vma->vm_page_prot))); |
238 | if (pte_swp_soft_dirty(*ptep)) | 238 | if (pte_swp_soft_dirty(*ptep)) |
239 | pte = pte_mksoft_dirty(pte); | 239 | pte = pte_mksoft_dirty(pte); |
240 | 240 | ||
@@ -116,13 +116,15 @@ static pgprot_t vm_pgprot_modify(pgprot_t oldprot, unsigned long vm_flags) | |||
116 | void vma_set_page_prot(struct vm_area_struct *vma) | 116 | void vma_set_page_prot(struct vm_area_struct *vma) |
117 | { | 117 | { |
118 | unsigned long vm_flags = vma->vm_flags; | 118 | unsigned long vm_flags = vma->vm_flags; |
119 | pgprot_t vm_page_prot; | ||
119 | 120 | ||
120 | vma->vm_page_prot = vm_pgprot_modify(vma->vm_page_prot, vm_flags); | 121 | vm_page_prot = vm_pgprot_modify(vma->vm_page_prot, vm_flags); |
121 | if (vma_wants_writenotify(vma)) { | 122 | if (vma_wants_writenotify(vma, vm_page_prot)) { |
122 | vm_flags &= ~VM_SHARED; | 123 | vm_flags &= ~VM_SHARED; |
123 | vma->vm_page_prot = vm_pgprot_modify(vma->vm_page_prot, | 124 | vm_page_prot = vm_pgprot_modify(vm_page_prot, vm_flags); |
124 | vm_flags); | ||
125 | } | 125 | } |
126 | /* remove_protection_ptes reads vma->vm_page_prot without mmap_sem */ | ||
127 | WRITE_ONCE(vma->vm_page_prot, vm_page_prot); | ||
126 | } | 128 | } |
127 | 129 | ||
128 | /* | 130 | /* |
@@ -1386,7 +1388,7 @@ SYSCALL_DEFINE1(old_mmap, struct mmap_arg_struct __user *, arg) | |||
1386 | * to the private version (using protection_map[] without the | 1388 | * to the private version (using protection_map[] without the |
1387 | * VM_SHARED bit). | 1389 | * VM_SHARED bit). |
1388 | */ | 1390 | */ |
1389 | int vma_wants_writenotify(struct vm_area_struct *vma) | 1391 | int vma_wants_writenotify(struct vm_area_struct *vma, pgprot_t vm_page_prot) |
1390 | { | 1392 | { |
1391 | vm_flags_t vm_flags = vma->vm_flags; | 1393 | vm_flags_t vm_flags = vma->vm_flags; |
1392 | const struct vm_operations_struct *vm_ops = vma->vm_ops; | 1394 | const struct vm_operations_struct *vm_ops = vma->vm_ops; |
@@ -1401,8 +1403,8 @@ int vma_wants_writenotify(struct vm_area_struct *vma) | |||
1401 | 1403 | ||
1402 | /* The open routine did something to the protections that pgprot_modify | 1404 | /* The open routine did something to the protections that pgprot_modify |
1403 | * won't preserve? */ | 1405 | * won't preserve? */ |
1404 | if (pgprot_val(vma->vm_page_prot) != | 1406 | if (pgprot_val(vm_page_prot) != |
1405 | pgprot_val(vm_pgprot_modify(vma->vm_page_prot, vm_flags))) | 1407 | pgprot_val(vm_pgprot_modify(vm_page_prot, vm_flags))) |
1406 | return 0; | 1408 | return 0; |
1407 | 1409 | ||
1408 | /* Do we need to track softdirty? */ | 1410 | /* Do we need to track softdirty? */ |
diff --git a/mm/mprotect.c b/mm/mprotect.c index a4830f0325fe..063bbed22c7b 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c | |||
@@ -327,7 +327,7 @@ success: | |||
327 | * held in write mode. | 327 | * held in write mode. |
328 | */ | 328 | */ |
329 | vma->vm_flags = newflags; | 329 | vma->vm_flags = newflags; |
330 | dirty_accountable = vma_wants_writenotify(vma); | 330 | dirty_accountable = vma_wants_writenotify(vma, vma->vm_page_prot); |
331 | vma_set_page_prot(vma); | 331 | vma_set_page_prot(vma); |
332 | 332 | ||
333 | change_protection(vma, start, end, vma->vm_page_prot, | 333 | change_protection(vma, start, end, vma->vm_page_prot, |