ANDROID: mm: preserve vma->anon_vma after MREMAP_DONTUNMAP for SPF
The optimizations [1] and [2] to reset vma->anon_vma during MREMAP_DONTUNMAP can affect speculative page fault handler. If vma->anon_vma reset happens after do_anonymous_page verified no changes to the vma and obtained the ptl lock but before it calls page_add_new_anon_rmap() then __page_set_anon_rmap() will stumble on BUG_ON(!anon_vma). Disable these optimizations if SPF is enabled to avoid such situations. As a result the reverse map walk will consider the old VMA as it did before these optimizations were introduced. [1]1583aa278f("mm: mremap: unlink anon_vmas when mremap with MREMAP_DONTUNMAP success") [2]ee8ab1903e("mm: rmap: explicitly reset vma->anon_vma in unlink_anon_vmas()") Bug: 257443051 Change-Id: I4e7611137f4a49c94bfe73532b4b06cbb0d2405b Signed-off-by: Suren Baghdasaryan <surenb@google.com>
This commit is contained in:
@@ -683,6 +683,7 @@ static unsigned long move_vma(struct vm_area_struct *vma,
|
|||||||
/* We always clear VM_LOCKED[ONFAULT] on the old vma */
|
/* We always clear VM_LOCKED[ONFAULT] on the old vma */
|
||||||
vma->vm_flags &= VM_LOCKED_CLEAR_MASK;
|
vma->vm_flags &= VM_LOCKED_CLEAR_MASK;
|
||||||
|
|
||||||
|
#ifndef CONFIG_SPECULATIVE_PAGE_FAULT
|
||||||
/*
|
/*
|
||||||
* anon_vma links of the old vma is no longer needed after its page
|
* anon_vma links of the old vma is no longer needed after its page
|
||||||
* table has been moved.
|
* table has been moved.
|
||||||
@@ -690,6 +691,7 @@ static unsigned long move_vma(struct vm_area_struct *vma,
|
|||||||
if (new_vma != vma && vma->vm_start == old_addr &&
|
if (new_vma != vma && vma->vm_start == old_addr &&
|
||||||
vma->vm_end == (old_addr + old_len))
|
vma->vm_end == (old_addr + old_len))
|
||||||
unlink_anon_vmas(vma);
|
unlink_anon_vmas(vma);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Because we won't unmap we don't need to touch locked_vm */
|
/* Because we won't unmap we don't need to touch locked_vm */
|
||||||
return new_addr;
|
return new_addr;
|
||||||
|
|||||||
@@ -422,11 +422,13 @@ void unlink_anon_vmas(struct vm_area_struct *vma)
|
|||||||
if (vma->anon_vma) {
|
if (vma->anon_vma) {
|
||||||
vma->anon_vma->num_active_vmas--;
|
vma->anon_vma->num_active_vmas--;
|
||||||
|
|
||||||
|
#ifndef CONFIG_SPECULATIVE_PAGE_FAULT
|
||||||
/*
|
/*
|
||||||
* vma would still be needed after unlink, and anon_vma will be prepared
|
* vma would still be needed after unlink, and anon_vma will be prepared
|
||||||
* when handle fault.
|
* when handle fault.
|
||||||
*/
|
*/
|
||||||
vma->anon_vma = NULL;
|
vma->anon_vma = NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
unlock_anon_vma_root(root);
|
unlock_anon_vma_root(root);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user