write_cr0read_cr0| 0x10000有什么作用?

问题描述

我在网络上进行了很多搜索,但没有找到关于write_cr0(read_cr0() | 0x10000)实际功能的简短说明。它与Linux内核有关,我对开发LKM感兴趣。我想知道这实际上是做什么的,与此有关的安全问题是什么。

它曾经用于删除syscall表上的写保护。 但是它如何真正起作用?以及这行中的每件事是什么?

解决方法

CR0是x86 CPU上可用的控制寄存器之一,它包含用于控制与内存保护,多任务处理,页面调度等有关的CPU功能的标志。有关详细信息,请参见第3卷第2节。 Intel's Software Developer's Manual中的2.5。

这些寄存器由编译器通常不会生成的特殊指令访问,因此read_cr0()是执行指令以读取该寄存器(通过内联汇编)并以通用形式返回结果的函数寄存器。同样,write_cr0()写入该寄存器。

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

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

0x10000的OR将第16位(写保护位)置1。在早期的32位x86 CPU上,始终允许在主管级别运行的代码(如内核)写入所有虚拟内存,而不管该页面是否被标记为只读。该位使该选项变为可选,以便在设置该位时,此类访问将导致页面错误。这行代码可能跟先前的行暂时清除了该位。