• Andy Lutomirski's avatar
    x86/asm/entry/64: Disable opportunistic SYSRET if regs->flags has TF set · 7ea24169
    Andy Lutomirski authored
    When I wrote the opportunistic SYSRET code, I missed an important difference
    between SYSRET and IRET.
    
    Both instructions are capable of setting EFLAGS.TF, but they behave differently
    when doing so:
    
     - IRET will not issue a #DB trap after execution when it sets TF.
       This is critical -- otherwise you'd never be able to make forward progress when
       returning to userspace.
    
     - SYSRET, on the other hand, will trap with #DB immediately after
       returning to CPL3, and the next instruction will never execute.
    
    This breaks anything that opportunistically SYSRETs to a user
    context with TF set.  For example, running this code with TF set
    and a SIGTRAP handler loaded never gets past 'post_nop':
    
    	extern unsigned char post_nop[];
    	asm volatile ("pushfq\n\t"
    		      "popq %%r11\n\t"
    		      "nop\n\t"
    		      "post_nop:"
    		      : : "c" (post_nop) : "r11");
    
    In my defense, I can't find this documented in the AMD or Intel manual.
    
    Fix it by using IRET to restore TF.
    Signed-off-by: default avatarAndy Lutomirski <luto@kernel.org>
    Cc: Borislav Petkov <bp@alien8.de>
    Cc: Borislav Petkov <bp@suse.de>
    Cc: Brian Gerst <brgerst@gmail.com>
    Cc: Denys Vlasenko <dvlasenk@redhat.com>
    Cc: H. Peter Anvin <hpa@zytor.com>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Fixes: 2a23c6b8 ("x86_64, entry: Use sysret to return to userspace when possible")
    Link: http://lkml.kernel.org/r/9472f1ca4c19a38ecda45bba9c91b7168135fcfa.1427923514.git.luto@kernel.orgSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
    7ea24169
entry_64.S 43.5 KB