SIDT指令在Linux用户空间进程中返回错误的基地址



我制作了以下x86-64程序来查看中断描述符表的基址起始位置:

#include <stdio.h>
#include <inttypes.h>
typedef struct __attribute__((packed)) {
uint16_t limit;
uint64_t base;
}idt_data_t;
static inline void store_idt(idt_data_t *idt_data)
{
asm volatile("sidt %0":"=m" (*idt_data));
}
int main(void)
{
idt_data_t idt_data;
store_idt(&idt_data);
printf("IDT Limit : 0x%Xn", idt_data.limit);
printf("IDT Base  : 0x%lXn", idt_data.base);
return 0;
}

它打印以下内容:

IDT Limit : 0xFFF
IDT Base  : 0xFFFFFE0000000000

基本地址似乎不正确,因为地址应该始终是物理地址,对吗?

此外,我也不确定,但这个限制似乎太高了。我做错了什么?

这是一个线性地址,不一定是物理地址。换句话说,它和大多数其他地址一样受页面表的约束。它必须位于从未被分页到磁盘的页面中——如果没有,它将无法处理页面错误——但它可以位于物理上与虚拟上不同的地址中。

在x86-64上,IDT的每个条目都有16个字节长。有256个中断矢量。256*16=4096=0x1000。IDTR极限是一个";小于或等于";检查,因此通常使用0xFFF。

如果操作系统启用某个功能,SIDT是较新CPU上的特权指令,因此建议不要在用户模式下使用它,除非您正在编写漏洞PoC或其他东西。操作系统可能在答案上撒谎,而不是抛出异常,但我不知道。

相关内容

  • 没有找到相关文章

最新更新