anolis: mm: pgtable_share: check pte for rare page_vma_mapped_walk() caller

ANBZ: #6632

page_mapped_in_vma() will check whether the page has
been mapped into ptes by calling page_vma_mapped_walk().

The new flag PVMW_SHARED_PGTABLE_CHECK marked to tell
page_vma_mapped_walk() check to pte level, and return
right value. The normal VMAs does not need this flag.
(NOTE: page_mapped_in_vma() only be called on anonymous
VMAs, but we need this patch for security).

Signed-off-by: Rongwei Wang <rongwei.wang@linux.alibaba.com>
Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
Reviewed-by: Xu Yu <xuyu@linux.alibaba.com>
Link: https://gitee.com/anolis/cloud-kernel/pulls/2550
This commit is contained in:
Rongwei Wang 2023-11-16 19:23:10 +08:00 committed by 小龙
parent 7b5dcb167d
commit 3298aba75d
2 changed files with 21 additions and 1 deletions

View File

@ -215,6 +215,7 @@ void try_to_unmap_zeropage(struct page *page, enum ttu_flags flags);
#ifdef CONFIG_PAGETABLE_SHARE
/* Avoid unnecessary page walk for shared pgtable */
#define PVMW_SHARED_PGTABLE (1 << 3)
#define PVMW_SHARED_PGTABLE_CHECK (1 << 4)
#endif
struct page_vma_mapped_walk {

View File

@ -166,7 +166,7 @@ bool page_vma_mapped_walk(struct page_vma_mapped_walk *pvmw)
#ifdef CONFIG_PAGETABLE_SHARE
if ((vma_is_pgtable_shared(pvmw->vma) || vma_is_pgtable_shadow(pvmw->vma)) &&
!(pvmw->flags & PVMW_SHARED_PGTABLE))
!(pvmw->flags & (PVMW_SHARED_PGTABLE | PVMW_SHARED_PGTABLE_CHECK)))
return not_found(pvmw);
#endif
@ -228,6 +228,19 @@ restart:
if (vma_is_pgtable_shared(pvmw->vma)) {
pvmw->ptl = pmd_lock(mm, pvmw->pmd);
if (!pmd_none(pmde)) {
if (pvmw->flags & PVMW_SHARED_PGTABLE_CHECK) {
pte_t *ptep, pte;
ptep = pte_offset_map(pvmw->pmd, pvmw->address);
pte = READ_ONCE(*ptep);
if (!pte_present(pte) ||
!pfn_is_match(pvmw->page, pte_pfn(pte))) {
pte_unmap(ptep);
return false;
}
pte_unmap(ptep);
}
pvmw->pte = (pte_t *)pvmw->pmd;
pvmw->pmd = NULL;
return true;
@ -335,6 +348,12 @@ int page_mapped_in_vma(struct page *page, struct vm_area_struct *vma)
pvmw.address = vma_address(page, vma);
if (pvmw.address == -EFAULT)
return 0;
#ifdef CONFIG_PAGETABLE_SHARE
if (vma_is_pgtable_shared(vma) || vma_is_pgtable_shadow(vma))
pvmw.flags |= PVMW_SHARED_PGTABLE_CHECK;
#endif
if (!page_vma_mapped_walk(&pvmw))
return 0;
page_vma_mapped_walk_done(&pvmw);