Why linux sets the data segment to __USER_DS in the exception handler prolog

I am trying to read Linux source code (2.6.11)

In the exception handler, in entry.s, error_code:

movl $(__USER_DS), %ecx movl %ecx, %ds movl %ecx, %es 

I do not know why the user data segment is loaded here. Since it is assumed that it introduces an exception handler code that runs in kernel mode, the selector must be __KERNEL_DS.

I checked the other versions of the code, they do the same thing in this place.

+4
source share
2 answers

If an exception handler is introduced with ds and es already installed in the data segment, it does not matter, except maybe a microsecond of delay. Exception handlers usually do not have to be fast.

But what can cause an exception handler to be called? Maybe this is because a bad value was loaded into the segment register and then indicated? In such cases, it is important for the code to create a safe environment. cs is set by calling an exception. To be bulletproof, you must also configure ss and esp .


Followup:

Looking at the kernel 2-6.22.18 for i386, I do not see exactly this:

 error_code: /* the function address is in %fs 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 

The __KERNEL_PERCPU is a macro defined (in include/asm-i386/segment.h ) as 0 for machines without SMP and (GDT_ENTRY_PERCPU * 8) for SMP. 8 for the size of the GDT record (I think), and GDT_ENTRY_PERCPU refers to the records in the GDT for each processor. Its value is <base> + 15 , which the comments indicate is "user default DS", so this is actually the same.

Access to the kernel data segment is via fs and ss . There are many data access resources on the stack. While maintaining access to user-mode descriptors through ds , a very small load of segment registers is required.

+3
source

In the entry.s file:

 #define RESTORE_ALL RESTORE_REGS addl $4, %esp; 1: iret; .section .fixup,"ax"; 2: sti; movl $(__USER_DS), %edx; movl %edx, %ds; movl %edx, %es; movl $11,%eax; call do_exit; .previous; .section __ex_table,"a"; .align 4; .long 1b,2b; .previous 

This macro will be called at the end of the exception / interrupt / syscalls. The ds & es patch code for USER_DS, which indicates that iiret will throw an exception if ds & es DPL is not 3 (user privilege).

So linux sets ds & es to USER_DS at the very beginning of the exception / interrupt / syscalls to avoid this exception.

0
source

Source: https://habr.com/ru/post/1497729/


All Articles