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:
Suren Baghdasaryan
2022-11-21 17:53:27 -08:00
parent 5844c8e7aa
commit 50d2b75b86
2 changed files with 4 additions and 0 deletions

View File

@@ -683,6 +683,7 @@ static unsigned long move_vma(struct vm_area_struct *vma,
/* We always clear VM_LOCKED[ONFAULT] on the old vma */
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
* 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 &&
vma->vm_end == (old_addr + old_len))
unlink_anon_vmas(vma);
#endif
/* Because we won't unmap we don't need to touch locked_vm */
return new_addr;

View File

@@ -422,11 +422,13 @@ void unlink_anon_vmas(struct vm_area_struct *vma)
if (vma->anon_vma) {
vma->anon_vma->num_active_vmas--;
#ifndef CONFIG_SPECULATIVE_PAGE_FAULT
/*
* vma would still be needed after unlink, and anon_vma will be prepared
* when handle fault.
*/
vma->anon_vma = NULL;
#endif
}
unlock_anon_vma_root(root);