sweep through entire page table to free up intermediate tables
authorLunaixsky <lunaixsky@qq.com>
Sat, 8 Feb 2025 05:11:28 +0000 (05:11 +0000)
committerLunaixsky <lunaixsky@qq.com>
Sat, 8 Feb 2025 05:11:28 +0000 (05:11 +0000)
* fix the page leakage issues due to some intermediate page tables
  being left-over

lunaix-os/arch/generic/procvm.c
lunaix-os/includes/lunaix/mm/procvm.h
lunaix-os/kernel/mm/procvm.c

index 91c4845c5bf5e9495035e57df706017633346a9e..ec288d3f6d84d8253cae011b926ccba728ccf89b 100644 (file)
@@ -30,7 +30,22 @@ procvm_link_kernel(ptr_t dest_mnt)
 }
 
 _default void
-procvm_unlink_kernel()
+procvm_unlink_kernel(ptr_t dest_mnt)
 {
-    // nothing to do here.
+    pte_t *ptep_smx, *src_smx;
+    unsigned int i;
+    
+    i = va_level_index(KERNEL_RESIDENT, L0T_SIZE);
+    ptep_smx = mkl1tep_va(VMS_SELF, dest_mnt);
+    src_smx  = mkl0tep_va(VMS_SELF, 0);
+
+    for (; i < LEVEL_SIZE; i++)
+    {
+        pte_t* ptep = &ptep_smx[i];
+        if (lntep_implie_vmnts(ptep, L0T_SIZE)) {
+            continue;
+        }
+
+        set_pte(ptep, null_pte);
+    }
 }
\ No newline at end of file
index 8eb81ddc4260fd26759d3ad4e91c4cdc10024f97..f75cb965a07600d1a8de9ddb56d01f588eeba298 100644 (file)
@@ -119,6 +119,6 @@ void
 procvm_link_kernel(ptr_t dest_mnt);
 
 void
-procvm_unlink_kernel();
+procvm_unlink_kernel(ptr_t dest_mnt);
 
 #endif /* __LUNAIX_PROCVM_H */
index 88f512cc1b32ed92d0058b6cd4cd5056164ac7ef..8081971eeb4442fd09a05d15b69eafefb83c1e7a 100644 (file)
@@ -69,34 +69,6 @@ __descend(ptr_t dest_mnt, ptr_t src_mnt, ptr_t va, bool alloc)
     return i;
 }
 
-static void
-__free_hierarchy(ptr_t mnt, ptr_t va, int level)
-{
-    pte_t pte, *ptep, *ptep_next;
-
-    if (pt_last_level(level)) {
-        return;
-    }
-
-    __free_hierarchy(mnt, va, level + 1);
-
-    ptep = mklntep_va(level, mnt, va);
-    pte = pte_at(ptep);
-    if (pte_isnull(pte)) {
-        return;
-    }
-
-    ptep_next = ptep_step_into(ptep);
-    for (unsigned i = 0; i < LEVEL_SIZE; i++, ptep_next++)
-    {
-        if (!pte_isnull(pte_at(ptep_next))) {
-            return;
-        }
-    }
-    
-    free_pagetable_trace(ptep, pte, level);
-}
-
 static inline void
 copy_leaf(pte_t* dest, pte_t* src, pte_t pte, int level)
 {
@@ -173,12 +145,6 @@ vmrcpy(ptr_t dest_mnt, ptr_t src_mnt, struct mm_region* region)
     }
 }
 
-static inline void
-vmrfree_hierachy(ptr_t vm_mnt, struct mm_region* region)
-{
-    __free_hierarchy(vm_mnt, region->start, 0);
-}
-
 static void
 vmrfree(ptr_t vm_mnt, struct mm_region* region)
 {
@@ -302,6 +268,37 @@ done:;
     dest_mm->vmroot = pte_paddr(pte_sms);
 }
 
+static void
+__purge_vms_residual(struct proc_mm* mm, int level, ptr_t va)
+{
+    pte_t *ptep, pte;
+    ptr_t _va;
+
+    if (level >= MAX_LEVEL) {
+        return;
+    }
+
+    ptep = mklntep_va(level, mm->vm_mnt, va);
+
+    for (unsigned i = 0; i < LEVEL_SIZE; i++, ptep++) 
+    {
+        pte = pte_at(ptep);
+        if (pte_isnull(pte) || !pte_isloaded(pte)) {
+            continue;
+        }
+
+        if (lntep_implie_vmnts(ptep, lnt_page_size(level))) {
+            continue;
+        }
+
+        _va = va + (i * lnt_page_size(level));
+        __purge_vms_residual(mm, level + 1, _va);
+        
+        set_pte(ptep, null_pte);
+        leaflet_return(pte_leaflet_aligned(pte));
+    }
+}
+
 static void
 vmsfree(struct proc_mm* mm)
 {
@@ -311,7 +308,7 @@ vmsfree(struct proc_mm* mm)
     pte_t* ptep_self;
     
     vm_mnt    = mm->vm_mnt;
-    ptep_self = mkl0tep(mkptep_va(vm_mnt, VMS_SELF));
+    ptep_self = mkl0tep_va(vm_mnt, VMS_SELF);
 
     // first pass: free region mappings
     llist_for_each(pos, n, &mm->regions, head)
@@ -319,13 +316,10 @@ vmsfree(struct proc_mm* mm)
         vmrfree(vm_mnt, pos);
     }
 
-    // second pass: free the hierarchical 
-    llist_for_each(pos, n, &mm->regions, head)
-    {
-        vmrfree_hierachy(vm_mnt, pos);
-    }
+    procvm_unlink_kernel(vm_mnt);
 
-    procvm_unlink_kernel();
+    // free up all allocated tables on intermediate levels
+    __purge_vms_residual(mm, 0, 0);
 
     free_pagetable_trace(ptep_self, pte_at(ptep_self), 0);
 }
@@ -354,7 +348,6 @@ void
 procvm_prune_vmr(ptr_t vm_mnt, struct mm_region* region)
 {
     vmrfree(vm_mnt, region);
-    vmrfree_hierachy(vm_mnt, region);
 }
 
 void