[PATCH 1/2] x86, pti: fix boot problems from Global-bit setting

From: Dave Hansen
Date: Tue Apr 17 2018 - 17:16:49 EST



These are _very_ lightly tested. I'm throwing them out there for
folks are looking for a fix.

---

From: Dave Hansen <dave.hansen@xxxxxxxxxxxxxxx>

Part of the global bit _setting_ patches also includes clearing the
Global bit when we do not want it. That is done with
set_memory_nonglobal(), which uses change_page_attr_clear() in
pageattr.c under the covers. However, it's pretty clear that
change_page_attr_clear() has not been heavily used early in boot, or
on kernel text.

It has checks like BUG_ON(irqs_disabled()), looking for interrupt
disabling but that also trip in early boot on certain preempt
configurations. Just copy the existing BUG_ON() sequence to check for
early boot.

Signed-off-by: Dave Hansen <dave.hansen@xxxxxxxxxxxxxxx>
Fixes: 39114b7a7 (x86/pti: Never implicitly clear _PAGE_GLOBAL for kernel image)
Reported-by: Mariusz Ceier <mceier@xxxxxxxxx>
Reported-by: Aaro Koskinen <aaro.koskinen@xxxxxxxxx>
Cc: Andrea Arcangeli <aarcange@xxxxxxxxxx>
Cc: Andy Lutomirski <luto@xxxxxxxxxx>
Cc: Arjan van de Ven <arjan@xxxxxxxxxxxxxxx>
Cc: Borislav Petkov <bp@xxxxxxxxx>
Cc: Dan Williams <dan.j.williams@xxxxxxxxx>
Cc: David Woodhouse <dwmw2@xxxxxxxxxxxxx>
Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
Cc: Hugh Dickins <hughd@xxxxxxxxxx>
Cc: Josh Poimboeuf <jpoimboe@xxxxxxxxxx>
Cc: Juergen Gross <jgross@xxxxxxxx>
Cc: Kees Cook <keescook@xxxxxxxxxx>
Cc: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
Cc: Nadav Amit <namit@xxxxxxxxxx>
Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
Cc: linux-mm@xxxxxxxxx
---

b/arch/x86/mm/pageattr.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff -puN arch/x86/mm/pageattr.c~pti-glb-boot-problem-fix arch/x86/mm/pageattr.c
--- a/arch/x86/mm/pageattr.c~pti-glb-boot-problem-fix 2018-04-17 14:10:13.553395577 -0700
+++ b/arch/x86/mm/pageattr.c 2018-04-17 14:10:13.559395577 -0700
@@ -172,7 +172,7 @@ static void __cpa_flush_all(void *arg)

static void cpa_flush_all(unsigned long cache)
{
- BUG_ON(irqs_disabled());
+ BUG_ON(irqs_disabled() && !early_boot_irqs_disabled);

on_each_cpu(__cpa_flush_all, (void *) cache, 1);
}
@@ -236,7 +236,7 @@ static void cpa_flush_array(unsigned lon
unsigned long do_wbinvd = cache && numpages >= 1024; /* 4M threshold */
#endif

- BUG_ON(irqs_disabled());
+ BUG_ON(irqs_disabled() && !early_boot_irqs_disabled);

on_each_cpu(__cpa_flush_all, (void *) do_wbinvd, 1);

_