x86: use the right protections for split-up pagetables

Steven Rostedt found a bug in where in his modified kernel
ftrace was unable to modify the kernel text, due to the PMD
itself having been marked read-only as well in
split_large_page().

The fix, suggested by Linus, is to not try to 'clone' the
reference protection of a huge-page, but to use the standard
(and permissive) page protection bits of KERNPG_TABLE.

The 'cloning' makes sense for the ptes but it's a confused and
incorrect concept at the page table level - because the
pagetable entry is a set of all ptes and hence cannot
'clone' any single protection attribute - the ptes can be any
mixture of protections.

With the permissive KERNPG_TABLE, even if the pte protections
get changed after this point (due to ftrace doing code-patching
or other similar activities like kprobes), the resulting combined
protections will still be correct and the pte's restrictive
(or permissive) protections will control it.

Also update the comment.

This bug was there for a long time but has not caused visible
problems before as it needs a rather large read-only area to
trigger. Steve possibly hacked his kernel with some really
large arrays or so. Anyway, the bug is definitely worth fixing.

[ Huang Ying also experienced problems in this area when writing
the EFI code, but the real bug in split_large_page() was not
realized back then. ]

Reported-by: Steven Rostedt <rostedt@goodmis.org>
Reported-by: Huang Ying <ying.huang@intel.com>
Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

+5 -10
+5 -10
arch/x86/mm/pageattr.c
··· 508 #endif 509 510 /* 511 - * Install the new, split up pagetable. Important details here: 512 * 513 - * On Intel the NX bit of all levels must be cleared to make a 514 - * page executable. See section 4.13.2 of Intel 64 and IA-32 515 - * Architectures Software Developer's Manual). 516 - * 517 - * Mark the entry present. The current mapping might be 518 - * set to not present, which we preserved above. 519 */ 520 - ref_prot = pte_pgprot(pte_mkexec(pte_clrhuge(*kpte))); 521 - pgprot_val(ref_prot) |= _PAGE_PRESENT; 522 - __set_pmd_pte(kpte, address, mk_pte(base, ref_prot)); 523 base = NULL; 524 525 out_unlock:
··· 508 #endif 509 510 /* 511 + * Install the new, split up pagetable. 512 * 513 + * We use the standard kernel pagetable protections for the new 514 + * pagetable protections, the actual ptes set above control the 515 + * primary protection behavior: 516 */ 517 + __set_pmd_pte(kpte, address, mk_pte(base, __pgprot(_KERNPG_TABLE))); 518 base = NULL; 519 520 out_unlock: