c - 在 x64 Ubuntu 14.04 上用另一个页表条目覆盖页表条目

标签 c linux-kernel operating-system ubuntu-14.04 virtual-memory

我制作了一个内核模块,它获取两个变量的虚拟地址,将它们称为foobar,并遍历页表直到它们的物理地址。

我想修改foo的页表条目,使其与bar的页表条目相同,从而使其成为foo bar 位于同一页框架中。你能帮我实现这个目标吗?

下面是我编写的用于遍历页表的代码。

pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *ptep, pte;

pgd = pgd_offset(mm, address);
if (pgd_none(*pgd) || pgd_bad(*pgd))
    return -EINVAL;

pud = pud_offset(pgd, address);
if (pud_none(*pud) || pud_bad(*pud))
    return -EINVAL;   

pmd = pmd_offset(pud, address);
if (pmd_none(*pmd) || pmd_bad(*pmd))
    return -EINVAL;

ptep = pte_offset(pmd, address);
if (!ptep)
    return -EINVAL;
pte = *ptep;

我确信我需要刷新 TLB,也许还需要修改一些标志才能实现我想要的目标,但我缺乏所需的知识。

非常感谢任何帮助!

最佳答案

我写这个答案是希望这对将来的人有用。

我已经成功修改了两个变量foobar的虚拟地址的页表,这样mm就会将它们视为驻留在同一物理页中。

执行此操作的代码如下:

#include <linux/module.h>                                                                                                                                                                                      
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/thread_info.h>
#include <linux/spinlock.h>
#include <asm/io.h>
#include <asm/tlbflush.h>
#include <asm/page.h>
#include <asm/pgtable.h>

pgd_t *foo_pgd, *bar_pgd;
pud_t *foo_pud, *bar_pud;
pmd_t *foo_pmd, *bar_pmd;
pte_t *foo_ptep, *bar_ptep, foo_pte, bar_pte;

/* We will step through the page tables until we reach the
 * PTE for both foo and bar */

/* Get PGD */
foo_pgd = pgd_offset(current->mm, foo_address);
if (pgd_none(*foo_pgd) || pgd_bad(*foo_pgd))
    return -EINVAL;

bar_pgd = pgd_offset(current->mm, bar_address);
    if (pgd_none(*bar_pgd) || pgd_bad(*bar_pgd))
        return -EINVAL;

/* Get PUD */
foo_pud = pud_offset(foo_pgd, foo_address);
if (pud_none(*foo_pud) || pud_bad(*foo_pud))
    return -EINVAL;

bar_pud = pud_offset(bar_pgd, bar_address);
if (pud_none(*bar_pud) || pud_bad(*bar_pud))
    return -EINVAL;   

/* Get PMD */
foo_pmd = pmd_offset(foo_pud, foo_address);
if (pmd_none(*foo_pmd) || pmd_bad(*foo_pmd))
    return -EINVAL;

bar_pmd = pmd_offset(bar_pud, bar_address);
if (pmd_none(*bar_pmd) || pmd_bad(*bar_pmd))
    return -EINVAL;

/* Get PTE */
spin_lock(current->mm->page_table_lock);    
foo_ptep = pte_offset_map(foo_pmd, foo_address);
if (!pte_present(*foo_ptep))
    return -EINVAL;

bar_ptep = pte_offset_map(bar_pmd, bar_address);
if (!pte_present(*bar_ptep))
    return -EINVAL;

/* Trick foo into thinking he resides in the same page as bar */
*foo_ptep = *bar_ptep;

spin_unlock(current->mm->page_table_lock);

/* We need to flush the tlb afterwards */
__native_flush_tlb();

这可能不像@GilHamilton 想象的那么强大,但这为我完成了工作。

我希望这会很有用!

爱德华

关于c - 在 x64 Ubuntu 14.04 上用另一个页表条目覆盖页表条目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34983626/

相关文章:

连续可变有序列表

bash - 从 vmlinuz 或 bzImage 中提取 vmlinux

linux - 错误 : [scripts/Makefile. modinst :33: arch/x86/crypto/aegis128-aesni. ko]

c - 丢包率超过 65% 的 Echo 客户端

c - send() 和 receive() 使用一个套接字?

c - 全局使用WH_MOUSE,无需DLL

c - 如何处理来自 copy_from_user() 的页面错误?

linux - 如何确定 BPF_PROG_TYPE_SK_SKB 判定程序中数据包的方向?

assembly - 基本操作系统启动问题

c - 到达时间的 SJF 算法无法正常工作