summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@osdl.org>2007-01-04 23:23:27 +0100
committerAdrian Bunk <bunk@stusta.de>2007-01-04 23:23:27 +0100
commit09d9056ce65466da2a4634c62fcfecfa70fc9605 (patch)
treefe562e70b2fa660de32148a7a981843130025bee
parentbb3e712f45f05c380ee6efed0afd588ed3ce18fb (diff)
downloadlwn-09d9056ce65466da2a4634c62fcfecfa70fc9605.tar.gz
lwn-09d9056ce65466da2a4634c62fcfecfa70fc9605.zip
i386: save/restore eflags in context switch (CVE-2006-5173)
(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>
-rw-r--r--arch/i386/kernel/entry.S2
-rw-r--r--include/asm-i386/system.h8
2 files changed, 9 insertions, 1 deletions
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index 4d704724b2f5..a14218c9ec6c 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -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
/*
diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h
index 399145a247f2..ec36513239bd 100644
--- a/include/asm-i386/system.h
+++ b/include/asm-i386/system.h
@@ -12,9 +12,14 @@
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), \