Hol*_*mes 5 linux data-segment exceptionhandler
我正在尝试阅读Linux源代码(2.6.11)
在异常处理程序中,在entry.s,error_code:
movl $(__USER_DS), %ecx
movl %ecx, %ds
movl %ecx, %es
Run Code Online (Sandbox Code Playgroud)
我不知道为什么在这里加载用户数据段.由于它应该进入在内核模式下运行的异常处理程序代码,因此选择器应该是__KERNEL_DS.
我检查了其他版本的代码,他们在这个地方也做了同样的事情.
如果异常处理程序是通过数据段输入ds
并es
已设置为数据段,则除了可能有一微秒的延迟之外,没有任何区别。异常处理程序通常不需要很快。
但是什么可能导致进入异常处理程序呢?难道是因为一个错误的值被加载到段寄存器中然后被引用?在这种情况下,为代码建立一个安全的环境非常重要。 cs
由异常调用设置。要想防弹,ss
也esp
应该设置一下。
跟进:
查看 i386 的 2-6.22.18 内核,我没有完全看到这一点:
error_code: /* the function address is in %fs's slot on the stack */
pushl %es
... pushes %ds, %eax, %ebp, %edi, %esi, %edx, %ecx, %ebx, %fs
... along with pseudo-ops to manage stack frame layout
movl $(__KERNEL_PERCPU), %ecx
movl %ecx, %fs
popl %ecx // retrieves saved %fs
... sets up registers for the exception function
Run Code Online (Sandbox Code Playgroud)
该符号是为非 SMP 机器和SMP__KERNEL_PERCPU
定义的宏(在 中include/asm-i386/segment.h
) 。8 是 GDT 条目大小(我认为),与每个 CPU GDT 中的条目相关。它的值是注释指出的“默认用户DS”,所以实际上是同一件事。0
(GDT_ENTRY_PERCPU * 8)
GDT_ENTRY_PERCPU
<base> + 15
fs
内核数据段通过和访问ss
。许多内核数据访问都在堆栈上。通过保持通过访问用户模式描述符ds
,几乎不需要加载段寄存器。