x86/speculation: Add LFENCE to RSB fill sequence
authorPawan Gupta <pawan.kumar.gupta@linux.intel.com>
Tue, 2 Aug 2022 22:47:02 +0000 (15:47 -0700)
committerBorislav Petkov <bp@suse.de>
Wed, 3 Aug 2022 12:12:18 +0000 (14:12 +0200)
RSB fill sequence does not have any protection for miss-prediction of
conditional branch at the end of the sequence. CPU can speculatively
execute code immediately after the sequence, while RSB filling hasn't
completed yet.

  #define __FILL_RETURN_BUFFER(reg, nr, sp)       \
          mov     $(nr/2), reg;                   \
  771:                                            \
          ANNOTATE_INTRA_FUNCTION_CALL;           \
          call    772f;                           \
  773:    /* speculation trap */                  \
          UNWIND_HINT_EMPTY;                      \
          pause;                                  \
          lfence;                                 \
          jmp     773b;                           \
  772:                                            \
          ANNOTATE_INTRA_FUNCTION_CALL;           \
          call    774f;                           \
  775:    /* speculation trap */                  \
          UNWIND_HINT_EMPTY;                      \
          pause;                                  \
          lfence;                                 \
          jmp     775b;                           \
  774:                                            \
          add     $(BITS_PER_LONG/8) * 2, sp;     \
          dec     reg;                            \
          jnz     771b;        <----- CPU can miss-predict here.

Before RSB is filled, RETs that come in program order after this macro
can be executed speculatively, making them vulnerable to RSB-based
attacks.

Mitigate it by adding an LFENCE after the conditional branch to prevent
speculation while RSB is being filled.

Suggested-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
arch/x86/include/asm/nospec-branch.h

index 4c9ba49..d3a3cc6 100644 (file)
@@ -60,7 +60,9 @@
 774:                                           \
        add     $(BITS_PER_LONG/8) * 2, sp;     \
        dec     reg;                            \
-       jnz     771b;
+       jnz     771b;                           \
+       /* barrier for jnz misprediction */     \
+       lfence;
 
 #ifdef __ASSEMBLY__