为什么linux在异常处理程序的序言中将数据段设置为__USER_DS

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.

我检查了其他版本的代码,他们在这个地方也做了同样的事情.

wal*_*lyk 3

如果异常处理程序是通过数据段输入dses已设置为数据段,则除了可能有一微秒的延迟之外,没有任何区别。异常处理程序通常不需要很快。

但是什么可能导致进入异常处理程序呢?难道是因为一个错误的值被加载到段寄存器中然后被引用?在这种情况下,为代码建立一个安全的环境非常重要。 cs由异常调用设置。要想防弹,ssesp应该设置一下。


跟进:

查看 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,几乎不需要加载段寄存器。