2009-11-20 44 views
8

我想用默认的代码和数据用户和内核段进行一些实验。我希望通过使用本地描述符表和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; 

赛格故障发生在这最后的指令。

回答

6

我只能猜测,因为我没有可用的组件。

我猜,在你得到一个segfault线被编译成这样的:

mov ds:[offset mx], 0x407cafe 

offset mx是在程序的数据段偏移mx(如果它是一个静态变量)或在堆栈中(如果它是一个自动变量)。无论哪种方式,这个偏移量都是在编译时计算出来的,不管DS指向什么都会使用这个偏移量。

现在你所做的是创建一个新的细分市场,其基础是在mx地址,其限制或者是0x40x4fff(取决于你没有指定G-bit)。

如果G-bit为0,则限制为0x4,并且由于它是极不可能的mx位于地址0x0和原DS0x4之间,当你访问偏移mx你穿越新段内极限。如果G-bit为1,则限制为0x4fff。现在只有当原始mx位于0x4fff之上时才会出现段错误。

考虑到新的细分市场的基础是mx,您可以通过访问mx

mov ds:[0], 0x407cafe 

我不知道我怎么会去写,在C,虽然。

+0

这是正确的。 'mx' *的地址相对于新的'DS' *现在是'0'。您不应将您的新段描述符加载到DS中,而应将其加载到ES中并使用段覆盖来访问它(加载DS会影响C代码中的所有数据访问)。 – caf

+0

这是我所得到的,当我拆开ELF与o​​bjdump的: 8048a48:C7 05 8C 9E 04 08 FE MOVL $ 0x3424cafe,0x8049e8c 8048a4f:CA 24 34 这对我来说相当新的题材,所以我不确定哪些字节是用于段寄存器覆盖修饰符的字节。另外,汇编代码中显示的地址是否偏移到默认数据段中?如果是这种情况,我是否需要更改变量初始化的地址? – Brian

+0

这是故障:'c7'是'MOV r/m32,imm32'的操作码。 '05'是MOD/RM字节,它表示内存操作数只能通过位移寻址。位移在以下四个字节中:'0x08049e8c'。接下来的四个字节是直接的'0x3424cafe'。这意味着默认数据段内'mx'的偏移量是'0x08049e8c',这就是您正在访问的新DS中的偏移量。 –