x86/entry/64: Add missing irqflags tracing to native_load_gs_index()

Running this code with IRQs enabled (where dummy_lock is a spinlock):

static void check_load_gs_index(void)
{
/* This will fail. */
load_gs_index(0xffff);

spin_lock(&dummy_lock);
spin_unlock(&dummy_lock);
}

Will generate a lockdep warning. The issue is that the actual write
to %gs would cause an exception with IRQs disabled, and the exception
handler would, as an inadvertent side effect, update irqflag tracing
to reflect the IRQs-off status. native_load_gs_index() would then
turn IRQs back on and return with irqflag tracing still thinking that
IRQs were off. The dummy lock-and-unlock causes lockdep to notice the
error and warn.

Fix it by adding the missing tracing.

Apparently nothing did this in a context where it mattered. I haven't
tried to find a code path that would actually exhibit the warning if
appropriately nasty user code were running.

I suspect that the security impact of this bug is very, very low --
production systems don't run with lockdep enabled, and the warning is
mostly harmless anyway.

Found during a quick audit of the entry code to try to track down an
unrelated bug that Ingo found in some still-in-development code.

Signed-off-by: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bpetkov@suse.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: stable@vger.kernel.org
Link: http://lkml.kernel.org/r/e1aeb0e6ba8dd430ec36c8a35e63b429698b4132.1511411918.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>

authored by Andy Lutomirski and committed by Ingo Molnar ca37e57b f68d62a5

+8 -2
+8 -2
arch/x86/entry/entry_64.S
··· 51 51 END(native_usergs_sysret64) 52 52 #endif /* CONFIG_PARAVIRT */ 53 53 54 - .macro TRACE_IRQS_IRETQ 54 + .macro TRACE_IRQS_FLAGS flags:req 55 55 #ifdef CONFIG_TRACE_IRQFLAGS 56 - bt $9, EFLAGS(%rsp) /* interrupts off? */ 56 + bt $9, \flags /* interrupts off? */ 57 57 jnc 1f 58 58 TRACE_IRQS_ON 59 59 1: 60 60 #endif 61 + .endm 62 + 63 + .macro TRACE_IRQS_IRETQ 64 + TRACE_IRQS_FLAGS EFLAGS(%rsp) 61 65 .endm 62 66 63 67 /* ··· 947 943 FRAME_BEGIN 948 944 pushfq 949 945 DISABLE_INTERRUPTS(CLBR_ANY & ~CLBR_RDI) 946 + TRACE_IRQS_OFF 950 947 SWAPGS 951 948 .Lgs_change: 952 949 movl %edi, %gs 953 950 2: ALTERNATIVE "", "mfence", X86_BUG_SWAPGS_FENCE 954 951 SWAPGS 952 + TRACE_IRQS_FLAGS (%rsp) 955 953 popfq 956 954 FRAME_END 957 955 ret