]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
x86_64: Don't leak NT bit into next task (CVE-2006-5755)
authorAndi Kleen <ak@suse.de>
Mon, 8 Jan 2007 21:44:07 +0000 (22:44 +0100)
committerAdrian Bunk <bunk@stusta.de>
Tue, 9 Jan 2007 02:23:30 +0000 (03:23 +0100)
SYSENTER can cause a NT to be set which might cause crashes on the IRET
in the next task.

Following similar i386 patch from Linus.

Backport to 2.6.16 by Chuck Ebbert <76306.1226@compuserve.com>
[Changed 'set_debugreg' to the older 'set_debug' in setup64.c
and added raw_local_save_flags() from 2.6.19 to system.h]

Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Adrian Bunk <bunk@stusta.de>
arch/x86_64/kernel/entry.S
arch/x86_64/kernel/setup64.c
include/asm-x86_64/system.h

index 97583bb9122d977923c5f9c46a6c2b2dbc7b58d1..9111d55c37644706e4cdebb876107634a1593f2c 100644 (file)
 /* rdi:        prev */ 
 ENTRY(ret_from_fork)
        CFI_DEFAULT_STACK
+       push kernel_eflags(%rip)
+       CFI_ADJUST_CFA_OFFSET 4
+       popf                            # reset kernel eflags
+       CFI_ADJUST_CFA_OFFSET -4
        call schedule_tail
        GET_THREAD_INFO(%rcx)
        testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),threadinfo_flags(%rcx)
index 70f1bb808a20e85a98931a2136345228a738e490..07772c80cbff47b65b05500311316bb954774101 100644 (file)
@@ -178,6 +178,8 @@ void __cpuinit check_efer(void)
         }       
 }
 
+unsigned long kernel_eflags;
+
 /*
  * cpu_init() initializes state that is per-CPU. Some data is already
  * initialized (naturally) in the bootstrap process, such as the GDT
@@ -289,4 +291,6 @@ void __cpuinit cpu_init (void)
        set_debug(0UL, 7);
 
        fpu_init(); 
+
+       raw_local_save_flags(kernel_eflags);
 }
index b7f66034ae7ac5e4d9ba115cf6db9d651bb2c41b..7b2c7aa2b06ebca03fff5961422b47ffd62a06f1 100644 (file)
 #define __RESTORE(reg,offset) "movq (14-" #offset ")*8(%%rsp),%%" #reg "\n\t"
 
 /* frame pointer must be last for get_wchan */
-#define SAVE_CONTEXT    "pushq %%rbp ; movq %%rsi,%%rbp\n\t"
-#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp\n\t"
+#define SAVE_CONTEXT    "pushf ; pushq %%rbp ; movq %%rsi,%%rbp\n\t"
+#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp ; popf\t"
 
 #define __EXTRA_CLOBBER  \
        ,"rcx","rbx","rdx","r8","r9","r10","r11","r12","r13","r14","r15"
 
+/* Save restore flags to clear handle leaking NT */
 #define switch_to(prev,next,last) \
        asm volatile(SAVE_CONTEXT                                                   \
                     "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */       \
@@ -157,6 +158,23 @@ struct alt_instr {
  */
 #define clts() __asm__ __volatile__ ("clts")
 
+static inline unsigned long __raw_local_save_flags(void)
+{
+       unsigned long flags;
+
+       __asm__ __volatile__(
+               "# __raw_save_flags\n\t"
+               "pushfq ; popq %q0"
+               : "=g" (flags)
+               : /* no input */
+               : "memory"
+       );
+
+       return flags;
+}
+#define raw_local_save_flags(flags) \
+               do { (flags) = __raw_local_save_flags(); } while (0)
+
 static inline unsigned long read_cr0(void)
 { 
        unsigned long cr0;