static int relocate_restore_code(void) { pgd_t *pgd; pud_t *pud; relocated_restore_code = get_safe_page(GFP_ATOMIC); if (!relocated_restore_code) return -ENOMEM; memcpy((void *)relocated_restore_code, &core_restore_code, PAGE_SIZE); /* Make the page containing the relocated code executable */ pgd = (pgd_t *)__va(read_cr3()) + pgd_index(relocated_restore_code); pud = pud_offset(pgd, relocated_restore_code); if (pud_large(*pud)) { set_pud(pud, __pud(pud_val(*pud) & ~_PAGE_NX)); } else { pmd_t *pmd = pmd_offset(pud, relocated_restore_code); if (pmd_large(*pmd)) { set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_NX)); } else { pte_t *pte = pte_offset_kernel(pmd, relocated_restore_code); set_pte(pte, __pte(pte_val(*pte) & ~_PAGE_NX)); } } __flush_tlb_all(); return 0; }
static void __init kasan_populate_p4d(p4d_t *p4d, unsigned long addr, unsigned long end, int nid) { pud_t *pud; unsigned long next; if (p4d_none(*p4d)) { void *p = early_alloc(PAGE_SIZE, nid, true); p4d_populate(&init_mm, p4d, p); } pud = pud_offset(p4d, addr); do { next = pud_addr_end(addr, end); if (!pud_large(*pud)) kasan_populate_pud(pud, addr, next, nid); } while (pud++, addr = next, addr != end); }
//walk_page_table modified static pte_t *walk_page_table(unsigned long addr) { pgd_t *pgdp; pud_t *pudp; pmd_t *pmdp; pte_t *ptep; pgdp = pgd_offset_k(addr); if (pgd_none(*pgdp)) return NULL; pudp = pud_offset(pgdp,addr); if (pud_none(*pudp) || pud_large(*pudp)) return NULL; pmdp = pmd_offset(pudp, addr); if (pmd_none(*pmdp) || pmd_large(*pmdp)) return NULL; ptep = pte_offset_kernel(pmdp, addr); if (pte_none(*ptep)) return NULL; return ptep; }
static void walk_pud_level(struct seq_file *m, struct pg_state *st, pgd_t addr, unsigned long P) { int i; pud_t *start; start = (pud_t *) pgd_page_vaddr(addr); for (i = 0; i < PTRS_PER_PUD; i++) { st->current_address = normalize_addr(P + i * PUD_LEVEL_MULT); if (!pud_none(*start)) { pgprotval_t prot = pud_val(*start) & PTE_FLAGS_MASK; if (pud_large(*start) || !pud_present(*start)) note_page(m, st, __pgprot(prot), 2); else walk_pmd_level(m, st, *start, P + i * PUD_LEVEL_MULT); } else note_page(m, st, __pgprot(0), 2); start++; } }
/* * map any virtual address of the current process to its * physical one. */ static unsigned long long any_v2p(unsigned long long vaddr) { pgd_t *pgd = pgd_offset(current->mm, vaddr); #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) p4d_t *p4d; #endif pud_t *pud; pmd_t *pmd; pte_t *pte; /* to lock the page */ struct page *pg; unsigned long long paddr; if (bad_address(pgd)) { printk(KERN_ALERT "[nskk] Alert: bad address of pgd %p\n", pgd); goto bad; } if (!pgd_present(*pgd)) { printk(KERN_ALERT "[nskk] Alert: pgd not present %lu\n", *pgd); goto out; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) p4d = p4d_offset(pgd, vaddr); if (p4d_none(*p4d)) return 0; pud = pud_offset(p4d, vaddr); #else pud = pud_offset(pgd, vaddr); #endif if (bad_address(pud)) { printk(KERN_ALERT "[nskk] Alert: bad address of pud %p\n", pud); goto bad; } if (!pud_present(*pud) || pud_large(*pud)) { printk(KERN_ALERT "[nskk] Alert: pud not present %lu\n", *pud); goto out; } pmd = pmd_offset(pud, vaddr); if (bad_address(pmd)) { printk(KERN_ALERT "[nskk] Alert: bad address of pmd %p\n", pmd); goto bad; } if (!pmd_present(*pmd) || pmd_large(*pmd)) { printk(KERN_ALERT "[nskk] Alert: pmd not present %lu\n", *pmd); goto out; } pte = pte_offset_kernel(pmd, vaddr); if (bad_address(pte)) { printk(KERN_ALERT "[nskk] Alert: bad address of pte %p\n", pte); goto bad; } if (!pte_present(*pte)) { printk(KERN_ALERT "[nskk] Alert: pte not present %lu\n", *pte); goto out; } pg = pte_page(*pte); #if 1 paddr = (pte_val(*pte) & PHYSICAL_PAGE_MASK) | (vaddr&(PAGE_SIZE-1)); #else pte->pte |= _PAGE_RW; // | _PAGE_USER; paddr = pte_val(*pte); #endif out: return paddr; bad: printk(KERN_ALERT "[nskk] Alert: Bad address\n"); return 0; }