Skip to contentSkip to conversation

x86, pti: fix boot problems from Global-bit setting

PATCH In review Dave Hansen 4 participants 7 messages Apr 17, 2018 – Apr 20, 2018

Subsystems (3)
lore
Share & tools
lore

Dave Hansen

author maintainer
#0 lore raw

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

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

---

From: Dave Hansen <[email protected]>

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.

Fixes 39114b7a7 (x86/pti: Never implicitly clear _PAGE_GLOBAL for kernel image)
Cc Andrea Arcangeli <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arjan van de Ven <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dan Williams <[email protected]>
Cc David Woodhouse <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Hugh Dickins <[email protected]>
Cc Josh Poimboeuf <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Kees Cook <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Nadav Amit <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>

---

 b/arch/x86/mm/pageattr.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/mm/pageattr.c renamed from arch/x86/mm/pageattr.c~pti-glb-boot-problem-fix +2 -2
diff -puN arch/x86/mm/pageattr.c~pti-glb-boot-problem-fix arch/x86/mm/pageattr.c
@@ -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);
 

_

author maintainer
#1 lore raw

PATCH 2/2 x86, pti: fix boot warning from Global-bit setting

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

---

From: Dave Hansen <[email protected]>

pageattr.c is not friendly when it encounters empty (zero) PTEs. The kernel linear map is exempt from these checks, but kernel text is not. This patch adds the code to also exempt kernel text from these checks. The proximate cause of these warnings was most likely an __init area that spanned a 2MB page boundary that resulted in a "zero" PMD.

Fixes 39114b7a7 (x86/pti: Never implicitly clear _PAGE_GLOBAL for kernel image)
Cc Andrea Arcangeli <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arjan van de Ven <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dan Williams <[email protected]>
Cc David Woodhouse <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Hugh Dickins <[email protected]>
Cc Josh Poimboeuf <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Kees Cook <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Nadav Amit <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>

---

 b/arch/x86/mm/pageattr.c |   17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)
arch/x86/mm/pageattr.c renamed from arch/x86/mm/pageattr.c~pti-glb-warning-inpageattr +15 -2
diff -puN arch/x86/mm/pageattr.c~pti-glb-warning-inpageattr arch/x86/mm/pageattr.c
@@ -1151,6 +1151,16 @@ static int populate_pgd(struct cpa_data
 	return 0;
 }
 
+bool __cpa_pfn_in_highmap(unsigned long pfn)
+{
+	/*
+	 * Kernel text has an alias mapping at a high address, known
+	 * here as "highmap".
+	 */
+	return within_inclusive(pfn, highmap_start_pfn(),
+			highmap_end_pfn());
+}
+
 static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr,
 			       int primary)
 {
@@ -1183,6 +1193,10 @@ static int __cpa_process_fault(struct cp
 		cpa->numpages = 1;
 		cpa->pfn = __pa(vaddr) >> PAGE_SHIFT;
 		return 0;
+
+	} else if (__cpa_pfn_in_highmap(cpa->pfn)) {
+		/* Faults in the highmap are OK, so do not warn: */
+		return -EFAULT;
 	} else {
 		WARN(1, KERN_WARNING "CPA: called for zero pte. "
 			"vaddr = %lx cpa->vaddr = %lx\n", vaddr,
@@ -1335,8 +1349,7 @@ static int cpa_process_alias(struct cpa_
 	 * to touch the high mapped kernel as well:
 	 */
 	if (!within(vaddr, (unsigned long)_text, _brk_end) &&
-	    within_inclusive(cpa->pfn, highmap_start_pfn(),
-			     highmap_end_pfn())) {
+	    __cpa_pfn_in_highmap(cpa->pfn)) {
 		unsigned long temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) +
 					       __START_KERNEL_map - phys_base;
 		alias_cpa = *cpa;

_

#2 lore raw

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

Quoted 80 lines · Dave Hansen

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

---

From: Dave Hansen <[email protected]>

pageattr.c is not friendly when it encounters empty (zero) PTEs. The kernel linear map is exempt from these checks, but kernel text is not. This patch adds the code to also exempt kernel text from these checks. The proximate cause of these warnings was most likely an __init area that spanned a 2MB page boundary that resulted in a "zero" PMD.

Fixes 39114b7a7 (x86/pti: Never implicitly clear _PAGE_GLOBAL for kernel image)
Cc Andrea Arcangeli <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arjan van de Ven <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Dan Williams <[email protected]>
Cc David Woodhouse <[email protected]>
Cc Greg Kroah-Hartman <[email protected]>
Cc Hugh Dickins <[email protected]>
Cc Josh Poimboeuf <[email protected]>
Cc Juergen Gross <[email protected]>
Cc Kees Cook <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Nadav Amit <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>

---

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

diff -puN arch/x86/mm/pageattr.c~pti-glb-warning-inpageattr arch/x86/mm/pageattr.c

arch/x86/mm/pageattr.c 2018-04-17 14:10:22.721395554 -0700 renamed from arch/x86/mm/pageattr.c~pti-glb-warning-inpageattr 2018-04-17 14:10:22.695395554 -0700 +15 -2
@@ -1151,6 +1151,16 @@ static int populate_pgd(struct cpa_data
        return 0;
 }
 
+bool __cpa_pfn_in_highmap(unsigned long pfn)
+{
+       /*
+        * Kernel text has an alias mapping at a high address, known
+        * here as "highmap".
+        */
+       return within_inclusive(pfn, highmap_start_pfn(),
+                       highmap_end_pfn());
+}
+
 static int __cpa_process_fault(struct cpa_data *cpa, unsigned long vaddr,
                               int primary)
 {
@@ -1183,6 +1193,10 @@ static int __cpa_process_fault(struct cp
                cpa->numpages = 1;
                cpa->pfn = __pa(vaddr) >> PAGE_SHIFT;
                return 0;
+
+       } else if (__cpa_pfn_in_highmap(cpa->pfn)) {
+               /* Faults in the highmap are OK, so do not warn: */
+               return -EFAULT;
        } else {
                WARN(1, KERN_WARNING "CPA: called for zero pte. "
                        "vaddr = %lx cpa->vaddr = %lx\n", vaddr,
@@ -1335,8 +1349,7 @@ static int cpa_process_alias(struct cpa_
         * to touch the high mapped kernel as well:
         */
        if (!within(vaddr, (unsigned long)_text, _brk_end) &&
-           within_inclusive(cpa->pfn, highmap_start_pfn(),
-                            highmap_end_pfn())) {
+           __cpa_pfn_in_highmap(cpa->pfn)) {
                unsigned long temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) +
                                               __START_KERNEL_map - phys_base;
                alias_cpa = *cpa;
Quoted 1 line

_

I confirm that these 2 patches fix the BUG for me in kernel 4.17.0-rc1.

Thanks

#3 lore raw

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

In reply to Dave Hansen
Thank you for the patch! Yet something to improve:

Hi Dave,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on tip/x86/core]
[also build test ERROR on v4.17-rc1 next-20180418]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Dave-Hansen/x86-pti-fix-boot-problems-from-Global-bit-setting/20180418-181719
config: i386-randconfig-x000-201815 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-16) 7.3.0 reproduce:

        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

arch/x86/mm/pageattr.c: In function '__cpa_pfn_in_highmap':

>> arch/x86/mm/pageattr.c:1161:31: error: implicit declaration of function 'highmap_start_pfn'; did you mean 'node_start_pfn'? [-Werror=implicit-function-declaration]
     return within_inclusive(pfn, highmap_start_pfn(),
                                  ^~~~~~~~~~~~~~~~~
                                  node_start_pfn
>> arch/x86/mm/pageattr.c:1162:4: error: implicit declaration of function 'highmap_end_pfn'; did you mean 'pgdat_end_pfn'? [-Werror=implicit-function-declaration]
       highmap_end_pfn());
       ^~~~~~~~~~~~~~~
       pgdat_end_pfn

cc1: some warnings being treated as errors

vim +1161 arch/x86/mm/pageattr.c

1154
1155 bool __cpa_pfn_in_highmap(unsigned long pfn)
1156 {
1157 /*
1158 * Kernel text has an alias mapping at a high address, known
1159 * here as "highmap".
1160 */

> 1161		return within_inclusive(pfn, highmap_start_pfn(),
> 1162				highmap_end_pfn());

1163 }
1164

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

#4 lore raw

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

In reply to Dave Hansen
Thank you for the patch! Yet something to improve:

Hi Dave,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on tip/x86/core]
[also build test ERROR on v4.17-rc1 next-20180418]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Dave-Hansen/x86-pti-fix-boot-problems-from-Global-bit-setting/20180418-181719
config: i386-randconfig-a0-201815 (attached as .config)
compiler: gcc-4.9 (Debian 4.9.4-2) 4.9.4 reproduce:

        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

arch/x86/mm/pageattr.c: In function '__cpa_pfn_in_highmap':
arch/x86/mm/pageattr.c:1161:2: error: implicit declaration of function 'highmap_start_pfn' [-Werror=implicit-function-declaration]
return within_inclusive(pfn, highmap_start_pfn(),
^

>> arch/x86/mm/pageattr.c:1162:4: error: implicit declaration of function 'highmap_end_pfn' [-Werror=implicit-function-declaration]
       highmap_end_pfn());
       ^

cc1: some warnings being treated as errors

vim +/highmap_end_pfn +1162 arch/x86/mm/pageattr.c

1154
1155 bool __cpa_pfn_in_highmap(unsigned long pfn)
1156 {
1157 /*
1158 * Kernel text has an alias mapping at a high address, known
1159 * here as "highmap".
1160 */

> 1161		return within_inclusive(pfn, highmap_start_pfn(),
> 1162				highmap_end_pfn());

1163 }
1164

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation

#5 lore raw

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

In reply to Dave Hansen
Quoted 11 lines · Dave Hansen

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

---

From: Dave Hansen <[email protected]>

pageattr.c is not friendly when it encounters empty (zero) PTEs. The kernel linear map is exempt from these checks, but kernel text is not. This patch adds the code to also exempt kernel text from these checks.

Bah. Changelogs should tell the WHY and not the WHAT

Quoted 2 lines

The proximate cause of these warnings was most likely an __init area that spanned a 2MB page boundary that resulted in a "zero" PMD.

This doesn't make any sense at all.

Thanks,

tglx

author maintainer
#6 lore raw

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

Quoted 8 lines · Thomas Gleixner
Quoted 3 lines

pageattr.c is not friendly when it encounters empty (zero) PTEs. The kernel linear map is exempt from these checks, but kernel text is not. This patch adds the code to also exempt kernel text from these checks.

Bah. Changelogs should tell the WHY and not the WHAT

Quoted 2 lines

The proximate cause of these warnings was most likely an __init area that spanned a 2MB page boundary that resulted in a "zero" PMD.

This doesn't make any sense at all.

I've rewritten these changelogs and added some more fixes for this set. I'll be sending it shortly.