From 102a0743326a03cd1a1202ceda21e175b7d3575c Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Tue, 20 Feb 2024 01:20:52 +0000 Subject: [PATCH] add new system file --- kernel/mm/memory.c | 38 ++++++++++++++++++++++++++------------ 1 files changed, 26 insertions(+), 12 deletions(-) diff --git a/kernel/mm/memory.c b/kernel/mm/memory.c index 834078a..857cfc9 100644 --- a/kernel/mm/memory.c +++ b/kernel/mm/memory.c @@ -246,6 +246,16 @@ unsigned long addr) { pgtable_t token = pmd_pgtable(*pmd); +#ifdef CONFIG_SPECULATIVE_PAGE_FAULT + /* + * Ensure page table destruction is blocked if __pte_map_lock managed + * to take this lock. Without this barrier tlb_remove_table_rcu can + * destroy ptl after __pte_map_lock locked it and during unlock would + * cause a use-after-free. + */ + spinlock_t *ptl = pmd_lock(tlb->mm, pmd); + spin_unlock(ptl); +#endif pmd_clear(pmd); pte_free_tlb(tlb, token, addr); mm_dec_nr_ptes(tlb->mm); @@ -2627,9 +2637,7 @@ static bool pte_spinlock(struct vm_fault *vmf) { bool ret = false; -#ifdef CONFIG_TRANSPARENT_HUGEPAGE pmd_t pmdval; -#endif /* Check if vma is still valid */ if (!(vmf->flags & FAULT_FLAG_SPECULATIVE)) { @@ -2644,24 +2652,28 @@ goto out; } -#ifdef CONFIG_TRANSPARENT_HUGEPAGE /* * We check if the pmd value is still the same to ensure that there * is not a huge collapse operation in progress in our back. + * It also ensures that pmd was not cleared by pmd_clear in + * free_pte_range and ptl is still valid. */ pmdval = READ_ONCE(*vmf->pmd); if (!pmd_same(pmdval, vmf->orig_pmd)) { trace_spf_pmd_changed(_RET_IP_, vmf->vma, vmf->address); goto out; } -#endif - vmf->ptl = pte_lockptr(vmf->vma->vm_mm, vmf->pmd); + vmf->ptl = pte_lockptr(vmf->vma->vm_mm, &pmdval); if (unlikely(!spin_trylock(vmf->ptl))) { trace_spf_pte_lock(_RET_IP_, vmf->vma, vmf->address); goto out; } + /* + * The check below will fail if pte_spinlock passed its ptl barrier + * before we took the ptl lock. + */ if (vma_has_changed(vmf)) { spin_unlock(vmf->ptl); trace_spf_vma_changed(_RET_IP_, vmf->vma, vmf->address); @@ -2679,9 +2691,7 @@ bool ret = false; pte_t *pte; spinlock_t *ptl; -#ifdef CONFIG_TRANSPARENT_HUGEPAGE pmd_t pmdval; -#endif /* * The first vma_has_changed() guarantees the page-tables are still @@ -2696,7 +2706,6 @@ goto out; } -#ifdef CONFIG_TRANSPARENT_HUGEPAGE /* * We check if the pmd value is still the same to ensure that there * is not a huge collapse operation in progress in our back. @@ -2706,7 +2715,6 @@ trace_spf_pmd_changed(_RET_IP_, vmf->vma, addr); goto out; } -#endif /* * Same as pte_offset_map_lock() except that we call @@ -2715,14 +2723,18 @@ * to invalidate TLB but this CPU has irq disabled. * Since we are in a speculative patch, accept it could fail */ - ptl = pte_lockptr(vmf->vma->vm_mm, vmf->pmd); - pte = pte_offset_map(vmf->pmd, addr); + ptl = pte_lockptr(vmf->vma->vm_mm, &pmdval); + pte = pte_offset_map(&pmdval, addr); if (unlikely(!spin_trylock(ptl))) { pte_unmap(pte); trace_spf_pte_lock(_RET_IP_, vmf->vma, addr); goto out; } + /* + * The check below will fail if __pte_map_lock_speculative passed its ptl + * barrier before we took the ptl lock. + */ if (vma_has_changed(vmf)) { pte_unmap_unlock(pte, ptl); trace_spf_vma_changed(_RET_IP_, vmf->vma, addr); @@ -3651,8 +3663,10 @@ if (!page) { struct swap_info_struct *si = swp_swap_info(entry); + bool skip_swapcache = false; - if (data_race(si->flags & SWP_SYNCHRONOUS_IO) && + trace_android_vh_skip_swapcache(entry, &skip_swapcache); + if ((data_race(si->flags & SWP_SYNCHRONOUS_IO) || skip_swapcache) && __swap_count(entry) == 1) { /* skip swapcache */ gfp_t flags = GFP_HIGHUSER_MOVABLE; -- Gitblit v1.6.2