我想用默认的代码和数据用户和内核段进行一些实验。我希望通过使用本地描述符表和modify_ldt系统调用来实现这一点。通过系统调用,我在LDT中创建了一个新条目,它是一个段描述符,其基址为全局变量,我想要“隔离”并限制为4个字节。利用LDT(局部描述符表)
我尝试通过内联汇编在C程序中加载数据段寄存器与我的自定义LDT条目的段选择器,但是当我尝试访问变量时收到段分割错误。
我的怀疑是我的全局变量的偏移量存在问题,并且在计算地址时,它超出了我的自定义段的限制,因此导致了段错误。
有没有人知道这种情况的工作?
哦,顺便说一句,这是在Linux的x86架构上。这是我第一次在论坛上提出这样的问题,所以如果有其他可以证明有用的信息,请告诉我。
预先感谢您。
编辑:我意识到,我也许应该包括源代码:)
struct user_desc* table_entry_ptr = NULL;
/* Allocates memory for a user_desc struct */
table_entry_ptr = (struct user_desc*)malloc(sizeof(struct user_desc));
/* Fills the user_desc struct which represents the segment for mx */
table_entry_ptr->entry_number = 0;
table_entry_ptr->base_addr = ((unsigned long)&mx);
table_entry_ptr->limit = 0x4;
table_entry_ptr->seg_32bit = 0x1;
table_entry_ptr->contents = 0x0;
table_entry_ptr->read_exec_only = 0x0;
table_entry_ptr->limit_in_pages = 0x0;
table_entry_ptr->seg_not_present = 0x0;
table_entry_ptr->useable = 0x1;
/* Writes a user_desc struct to the ldt */
num_bytes = syscall(__NR_modify_ldt,
LDT_WRITE, // 1
table_entry_ptr,
sizeof(struct user_desc)
);
asm("pushl %eax");
asm("movl $0x7, %eax"); /* 0111: 0-Index 1-Using the LDT table 11-RPL of 3 */
asm("movl %eax, %ds");
asm("popl %eax");
mx = 0x407CAFE;
赛格故障发生在这最后的指令。
这是正确的。 'mx' *的地址相对于新的'DS' *现在是'0'。您不应将您的新段描述符加载到DS中,而应将其加载到ES中并使用段覆盖来访问它(加载DS会影响C代码中的所有数据访问)。 – caf
这是我所得到的,当我拆开ELF与objdump的: 8048a48:C7 05 8C 9E 04 08 FE MOVL $ 0x3424cafe,0x8049e8c 8048a4f:CA 24 34 这对我来说相当新的题材,所以我不确定哪些字节是用于段寄存器覆盖修饰符的字节。另外,汇编代码中显示的地址是否偏移到默认数据段中?如果是这种情况,我是否需要更改变量初始化的地址? – Brian
这是故障:'c7'是'MOV r/m32,imm32'的操作码。 '05'是MOD/RM字节,它表示内存操作数只能通过位移寻址。位移在以下四个字节中:'0x08049e8c'。接下来的四个字节是直接的'0x3424cafe'。这意味着默认数据段内'mx'的偏移量是'0x08049e8c',这就是您正在访问的新DS中的偏移量。 –