From 151fecfb72a0d602dfe79790602ef64b4e241574 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 19 Feb 2024 01:51:07 +0000
Subject: [PATCH] export RK_PA3
---
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