Messages in this thread Patches in this message | | | Date | Wed, 15 Jan 2003 18:48:45 +0100 (CET) | From | Gabriel Paubert <> | Subject | [PATCH] Cleanup of the lcall7/lcall27 entry path. |
| |
Hi,
I have more carefully tested the last patch I proposed in: http://www.ussg.indiana.edu/hypermail/linux/kernel/0301.1/0917.html
The question I wanted to answer is: is it necessary to clear NT in the sysenter entry path as implemented for lcall7/lcall27 or is it possible to remove the flag manipulation from do_lcall?
Doing it only for one and not the other looks wrong since several return paths are shared, especially the ones which end up in iret, the only instruction which is affected by the NT flag.
The conclusion is that 2.5 is NT safe (had to dig out an old P5-133 which I could crash without fear of data loss, so I have only tested on 1 machine). The reason this cleanup works is that now (since Jan 5th) flags are saved and restored in switch_to() to keep IOPL private to a process even when using sysenter/sysexit.
The side effect of that patch is that NT becomes also process-private instead of infecting all processes and triggering a killfest of all user mode processes, including init (AFAICT kernel threads survived, but I did not have any debug tools enabled in the kernel).
Ok, here is the patch, the only addition to the preceding version is that interrupts are reenabled in the iret fixup path because it seems that do_exit() might otherwise spend quite some time with interrupts disabled.
===== arch/i386/kernel/entry.S 1.52 vs edited ===== --- 1.52/arch/i386/kernel/entry.S Fri Jan 10 02:12:00 2003 +++ edited/arch/i386/kernel/entry.S Wed Jan 15 15:50:14 2003 @@ -126,7 +126,8 @@ addl $4, %esp; \ 1: iret; \ .section .fixup,"ax"; \ -2: movl $(__USER_DS), %edx; \ +2: sti; \ + movl $(__USER_DS), %edx; \ movl %edx, %ds; \ movl %edx, %es; \ pushl $11; \ @@ -154,17 +155,6 @@ movl %eax,EFLAGS(%ebp) # movl %edx,EIP(%ebp) # Now we move them to their "normal" places movl %ecx,CS(%ebp) # - - # - # Call gates don't clear TF and NT in eflags like - # traps do, so we need to do it ourselves. - # %eax already contains eflags (but it may have - # DF set, clear that also) - # - andl $~(DF_MASK | TF_MASK | NT_MASK),%eax - pushl %eax - popfl - andl $-8192, %ebp # GET_THREAD_INFO movl TI_EXEC_DOMAIN(%ebp), %edx # Get the execution domain call *4(%edx) # Call the lcall7 handler for the domain
To convince myself that my patch is correct, I have also tested 2.4 with the attached patch, and it also becomes immune to the attack published in: http://www.ussg.indiana.edu/hypermail/linux/kernel/0211.1/0988.html
Regards, Gabriel. ===== arch/i386/kernel/entry.S 1.16 vs edited ===== --- 1.16/arch/i386/kernel/entry.S Wed Nov 13 21:40:19 2002 +++ edited/arch/i386/kernel/entry.S Wed Jan 15 15:05:08 2003 @@ -116,7 +116,8 @@ jmp 1b; \ 5: movl $0,(%esp); \ jmp 2b; \ -6: pushl %ss; \ +6: sti; \ + pushl %ss; \ popl %ds; \ pushl %ss; \ popl %es; \ @@ -142,9 +143,6 @@ movl CS(%esp),%edx # this is eip.. movl EFLAGS(%esp),%ecx # and this is cs.. movl %eax,EFLAGS(%esp) # - andl $~(NT_MASK|TF_MASK|DF_MASK), %eax - pushl %eax - popfl movl %edx,EIP(%esp) # Now we move them to their "normal" places movl %ecx,CS(%esp) # movl %esp,%ebx @@ -166,9 +164,6 @@ movl CS(%esp),%edx # this is eip.. movl EFLAGS(%esp),%ecx # and this is cs.. movl %eax,EFLAGS(%esp) # - andl $~(NT_MASK|TF_MASK|DF_MASK), %eax - pushl %eax - popfl movl %edx,EIP(%esp) # Now we move them to their "normal" places movl %ecx,CS(%esp) # movl %esp,%ebx ===== include/asm-i386/system.h 1.13 vs edited ===== --- 1.13/include/asm-i386/system.h Sun Dec 8 23:09:09 2002 +++ edited/include/asm-i386/system.h Wed Jan 15 14:50:39 2003 @@ -14,7 +14,8 @@ #define prepare_to_switch() do { } while(0) #define switch_to(prev,next,last) do { \ - asm volatile("pushl %%esi\n\t" \ + asm volatile("pushfl\n\t" \ + "pushl %%esi\n\t" \ "pushl %%edi\n\t" \ "pushl %%ebp\n\t" \ "movl %%esp,%0\n\t" /* save ESP */ \ @@ -26,6 +27,7 @@ "popl %%ebp\n\t" \ "popl %%edi\n\t" \ "popl %%esi\n\t" \ + "popfl\n\t" \ :"=m" (prev->thread.esp),"=m" (prev->thread.eip), \ "=b" (last) \ :"m" (next->thread.esp),"m" (next->thread.eip), \
| |