GDTR 的读取值



我发现可能是通过SGDT汇编命令读取GDTR。在我的 C 代码中插入这段程序集,我得到Error: operand type mismatch for 'sgdt'

unsigned long j;
asm("sgdt %0" : "=r"(j));

sgdt只能采用内存操作数,而不能采用寄存器,因此必须"=m"。 操作数大小为 2+8 字节(对于 x86-64;限制然后按该顺序地址),因此您需要一个结构;使用long将导致存储在对象外部。

阅读手册! https://www.felixcloutier.com/x86/sgdt

<小时 />

其他注意事项:

UMIP(用户模式指令防护)允许内核阻止用户空间
  • (权限级别 3)运行此指令,因为它只能帮助用户空间击败内核 ASLR 或其他漏洞;用户空间对此地址没有合法用途。 在像 Linux 这样的普通内核下,用户空间不能取消引用它从中获得的虚拟地址。 因此,如果硬件(Zen 2,Cannon Lake,Goldmont Plus)支持Linux,则可以启用UMIP。

  • Linux 内核有一个宏:store_gdt(dtr),它使用
    asm volatile("sgdt %0":"=m" (*dtr));struct desc_ptr *dtr


在带有Skylake CPU(不支持UMIP)的Linux 5.18系统上,我将sgdt [rsp](NASM语法)放入静态可执行文件中,以便我可以使用GDB(starti/stepi)单步执行。 在该指令之后:

  • x /1hx $rsp显示限制是0x007f(以 2 个字节存储,GDB 称之为半字,英特尔称之为字)。
  • x /1gx $rsp+2显示 qword 地址恰好是0xfffffe00000ed000,这是一个有效的内核地址(48 位符号扩展,但离地址空间规范范围上半部分的最顶端相当远)。 根据docs/x86/x86-64/mm.txt,从fffffe0000000000开始的0.5TB包含cpu_entry_area映射,因此找到GDT以及其他内核内容(其地址暴露在用户空间中(在没有UMIP的CPU上)并且必须始终映射,即使在具有Meltdown的CPU上也是如此。

顺便说一下,在 Linux 内核中,也可以通过已经定义的宏执行相同的操作store_gdt(dtr).它包含相同的内联汇编代码。宏的标头asm/desc.h

相关内容

  • 没有找到相关文章

最新更新