从LKM

时间:2016-06-02 20:45:38

标签: hyperlink arm cpu-registers

我想从linux内核模块中读取存储在链接寄存器或帧指针中的值,我不确定要使用的语法。对于上下文,我编译了Android goldfish 3.4内核,并使用insmod将我的模块加载到内核中。

2 个答案:

答案 0 :(得分:0)

我对这个领域的了解完全是业余爱好者,其他人可能知道一些非常时尚的东西,可以避免这种危险和恶意的方法。

作为一个哲学问题,内核并没有篡改用户模式操作作为其正常职责的一部分。这意味着您将不得不篡改内核的直接操作,并可能导致崩溃,损坏和其他有问题的c-words。

有两种方法可以做到这一点。您可以通过syscall进入/退出机制:将单个运行的线程从运行用户模式代码切换到该线程上下文中运行的内核代码,同时在它再次返回之前狡猾地替换它的存储寄存器。第二个是上下文切换机制本身,它在内核模式下切换,在一个线程的上下文中运行,再次替换相关的存储寄存器材料。

所有这些背后的操作理论是每个用户线程都有用户模式堆栈和内核模式堆栈。当一个线程进入内核时,用户模式堆栈和指令指针的当前值被保存到线程的内核模式堆栈中,并且CPU切换到内核模式堆栈。然后,剩余的寄存器值和标志也会保存到内核堆栈中。

在此阶段,您可以在从流程队列返回流程之前直接读取和修改这些值。在此之后,当您的线程从内核返回到用户模式时,将从内核模式堆栈中弹出寄存器值和标志,然后从内核模式上的修改值恢复用户模式堆栈和指令指针值叠加。

计划有一个内部机制,可以选择下一个要运行的进程,调用switch_to()。顾名思义,这个函数本质上只是切换内核堆栈 - 它将堆栈指针的当前值保存到当前线程的TCB中(在Linux中称为struct task_struct),并从中加载先前保存的堆栈指针下一个线程的TCB。您可以使用它来计算有问题的用户模式进程(可能需要现有内核模式进程结构的交叉引用)

答案 1 :(得分:0)

从内核端查看当前用户空间进程状态的方法是current_pt_regs()(对于特定任务,参见task_pt_regs())。这将为您提供指向struct pt_regs的指针,这与您在信号处理程序中的mcontext_t中找到的内容相同(至少在ARM上)。内核甚至提供了很好的访问宏来使整个caboodle相当文明 - 阅读源代码中的现有用法应该能够很好地理解如何做到这一点,但为了完整起见,这里有一个简单的例子 *功能

#include <asm/ptrace.h>

void func()
{
    struct pt_regs *regs = current_pt_regs();

    pr_info("User LR was %p\n", (void *)regs->ARM_lr);
}

您必须知道用户空间二进制文件的ABI详细信息才能知道哪个(如果有)寄存器被用作帧指针,但是如果有的话,它通常在r11或r7中。

*代码在深夜直接输入浏览器,通常免责声明适用等。