From: David Woodhouse <dwmw@xxxxxxxxxxxx> With PTI enabled, set_p4d() and set_pgd() will scribble over the end of the 4KiB page allocated by the ->alloc_pgt_page() callback, expecting it to have been an 8KiB allocation with the userspace version immediately after the kernel's version. So build *just* this code without PTI support. And without the PV MMU ops too, since that would redirect to the standard build of those functions which would have PTI enabled. Signed-off-by: David Woodhouse <dwmw@xxxxxxxxxxxx> --- Not sure I like this very much, but it works, and mirrors what arch/x86/boot/compressed/ident_map_64.c already does. We can't build the rest of the code in init_64.c with those config options turned off, or Xen PV doesn't boot any more. So just build it separately instead of #including it. Now kexec is a little more reliable and doesn't scribble over adjacent memory when building the page tables. arch/x86/mm/Makefile | 1 + arch/x86/mm/ident_map.c | 15 +++++++++++++++ arch/x86/mm/init_64.c | 2 -- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile index 690fbf48e853..134302863233 100644 --- a/arch/x86/mm/Makefile +++ b/arch/x86/mm/Makefile @@ -37,6 +37,7 @@ CFLAGS_mem_encrypt_identity.o := -fno-stack-protector CFLAGS_fault.o := -I $(src)/../include/asm/trace obj-$(CONFIG_X86_32) += pgtable_32.o iomap_32.o +obj-$(CONFIG_X86_64) += ident_map.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_PTDUMP_CORE) += dump_pagetables.o diff --git a/arch/x86/mm/ident_map.c b/arch/x86/mm/ident_map.c index 437e96fb4977..090240f98141 100644 --- a/arch/x86/mm/ident_map.c +++ b/arch/x86/mm/ident_map.c @@ -4,6 +4,21 @@ * included by both the compressed kernel and the regular kernel. */ +/* + * If PTI is enabled, the standard set_p4d() et al functions will assume + * that each allocation is 8KiB, with the userspace page table 4KiB above + * the kernel one. Since users of the kernel_ident_mapping_init() code all + * allocate only a 4KiB page in their ->alloc_pgt_page() callback, this + * leads to scribbling over the end of the allocation. So *just* for this + * identmap code, disable PTI and disable the paravirt MMU ops which would + * redirect to the normally-compiled version that will use PTI. + */ +#undef CONFIG_MITIGATION_PAGE_TABLE_ISOLATION +#undef CONFIG_PARAVIRT_XXL + +#include <linux/pgtable.h> +#include <asm/init.h> + static void free_pte(struct x86_mapping_info *info, pmd_t *pmd) { pte_t *pte = pte_offset_kernel(pmd, 0); diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index ff253648706f..784f8d1c9140 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -58,8 +58,6 @@ #include "mm_internal.h" -#include "ident_map.c" - #define DEFINE_POPULATE(fname, type1, type2, init) \ static inline void fname##_init(struct mm_struct *mm, \ type1##_t *arg1, type2##_t *arg2, bool init) \ -- 2.43.0
<<attachment: smime.p7s>>