]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
i386: save/restore eflags in context switch (CVE-2006-5173)
authorLinus Torvalds <torvalds@osdl.org>
Thu, 4 Jan 2007 22:23:27 +0000 (23:23 +0100)
committerAdrian Bunk <bunk@stusta.de>
Thu, 4 Jan 2007 22:23:27 +0000 (23:23 +0100)
(And reset it on new thread creation)

It turns out that eflags is important to save and restore not just
because of iopl, but due to the magic bits like the NT bit, which we
don't want leaking between different threads.

Backported to 2.6.16 by Chuck Ebbert <76306.1226@compuserve.com>
[Backport consisted of removing the CFI annotations.]

Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Adrian Bunk <bunk@stusta.de>
arch/i386/kernel/entry.S
include/asm-i386/system.h

index 4d704724b2f5bfeb00f72e23735d0e8290893e8e..a14218c9ec6cf208d78fb9e1f15c877c5a84d8df 100644 (file)
@@ -128,6 +128,8 @@ ENTRY(ret_from_fork)
        call schedule_tail
        GET_THREAD_INFO(%ebp)
        popl %eax
+       pushl $0x0202                   # Reset kernel eflags
+       popfl
        jmp syscall_exit
 
 /*
index 399145a247f290580c53576a81c0f7ba94ee61e8..ec36513239bd89a9f3309f251c80a2a62fd7407e 100644 (file)
 struct task_struct;    /* one of the stranger aspects of C forward declarations.. */
 extern struct task_struct * FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next));
 
+/*
+ * Saving eflags is important. It switches not only IOPL between tasks,
+ * it also protects other tasks from NT leaking through sysenter etc.
+ */
 #define switch_to(prev,next,last) do {                                 \
        unsigned long esi,edi;                                          \
-       asm volatile("pushl %%ebp\n\t"                                  \
+       asm volatile("pushfl\n\t"               /* Save flags */        \
+                    "pushl %%ebp\n\t"                                  \
                     "movl %%esp,%0\n\t"        /* save ESP */          \
                     "movl %5,%%esp\n\t"        /* restore ESP */       \
                     "movl $1f,%1\n\t"          /* save EIP */          \
@@ -22,6 +27,7 @@ extern struct task_struct * FASTCALL(__switch_to(struct task_struct *prev, struc
                     "jmp __switch_to\n"                                \
                     "1:\t"                                             \
                     "popl %%ebp\n\t"                                   \
+                    "popfl"                                            \
                     :"=m" (prev->thread.esp),"=m" (prev->thread.eip),  \
                      "=a" (last),"=S" (esi),"=D" (edi)                 \
                     :"m" (next->thread.esp),"m" (next->thread.eip),    \