• Andy Lutomirski's avatar
    x86_64, traps: Rework bad_iret · 0f90e981
    Andy Lutomirski authored
    commit b645af2d upstream.
    
    It's possible for iretq to userspace to fail.  This can happen because
    of a bad CS, SS, or RIP.
    
    Historically, we've handled it by fixing up an exception from iretq to
    land at bad_iret, which pretends that the failed iret frame was really
    the hardware part of #GP(0) from userspace.  To make this work, there's
    an extra fixup to fudge the gs base into a usable state.
    
    This is suboptimal because it loses the original exception.  It's also
    buggy because there's no guarantee that we were on the kernel stack to
    begin with.  For example, if the failing iret happened on return from an
    NMI, then we'll end up executing general_protection on the NMI stack.
    This is bad for several reasons, the most immediate of which is that
    general_protection, as a non-paranoid idtentry, will try to deliver
    signals and/or schedule from the wrong stack.
    
    This patch throws out bad_iret entirely.  As a replacement, it augments
    the existing swapgs fudge into a full-blown iret fixup, mostly written
    in C.  It's should be clearer and more correct.
    Signed-off-by: default avatarAndy Lutomirski <luto@amacapital.net>
    Reviewed-by: default avatarThomas Gleixner <tglx@linutronix.de>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    [bwh: Backported to 3.2:
     - We didn't use the _ASM_EXTABLE macro
     - Don't use __visible]
    Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
    0f90e981
entry_64.S 37.8 KB