write_cr0(read_cr0() | 0x10000) 是做什么的?

What does write_cr0(read_cr0() | 0x10000) do?

我在网上搜索了很多,但没有找到关于 write_cr0(read_cr0() | 0x10000) 真正作用的简短解释。它与 Linux 内核有关,我对开发 LKM 感到好奇。我想知道这到底是做什么用的,有什么安全问题。

它用于移除系统调用的写保护table。 但它究竟是如何运作的呢?这一行中的每一件事是什么?

CR0 是 x86 CPUs 上可用的 控制寄存器 之一,它包含控制与内存保护、多任务处理、分页相关的 CPU 功能的标志等。您可以在 Intel's Software Developer's Manual 的第 3 卷第 2.5 节中找到完整描述。

这些寄存器由编译器通常不会生成的特殊指令访问,因此 read_cr0() 是一个函数,它执行读取该寄存器的指令(通过内联汇编)和 returns导致 general-purpose 寄存器。同样,write_cr0() 写入该寄存器。

函数调用很可能是内联的,因此生成的代码类似于

mov eax, cr0
or eax, 0x10000
mov cr0, eax

OR 与 0x10000 设置位 16,写保护位。在早期的 32 位 x86 CPUs 上,主管级别(如内核)的代码 运行 始终允许写入所有虚拟内存,无论页面是否标记为 read-only。该位使其成为可选的,因此当它被设置时,此类访问将导致页面错误。这行代码可能跟在前面的一行代码之后,该行暂时清除了该位。