When the kpkeys_hardened_pgtables feature is enabled, special care is required when allocating page table pages while splitting the linear map.
Indicate that such pages are being allocated by passing __GFP_PGTABLE_SPLIT and use the appropriate interface to prepare the kpkeys_hardened_pgtables allocator in split_kernel_leaf_mapping(). Signed-off-by: Kevin Brodsky <[email protected]> --- arch/arm64/mm/mmu.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index ea1cb1875257..2cee0b7f8a56 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -707,7 +707,7 @@ static int split_kernel_leaf_mapping_locked(unsigned long addr) if (!pud_present(pud)) goto out; if (pud_leaf(pud)) { - ret = split_pud(pudp, pud, GFP_PGTABLE_KERNEL, true); + ret = split_pud(pudp, pud, GFP_PGTABLE_KERNEL | __GFP_PGTABLE_SPLIT, true); if (ret) goto out; } @@ -732,7 +732,7 @@ static int split_kernel_leaf_mapping_locked(unsigned long addr) */ if (ALIGN_DOWN(addr, PMD_SIZE) == addr) goto out; - ret = split_pmd(pmdp, pmd, GFP_PGTABLE_KERNEL, true); + ret = split_pmd(pmdp, pmd, GFP_PGTABLE_KERNEL | __GFP_PGTABLE_SPLIT, true); if (ret) goto out; } @@ -800,7 +800,18 @@ int split_kernel_leaf_mapping(unsigned long start, unsigned long end) if (start != PAGE_ALIGN(start) || end != PAGE_ALIGN(end)) return -EINVAL; +kpkeys_retry: + ret = kpkeys_prepare_direct_map_split(); + if (ret) + return ret; + mutex_lock(&pgtable_split_lock); + + if (!kpkeys_ready_for_direct_map_split()) { + mutex_unlock(&pgtable_split_lock); + goto kpkeys_retry; + } + lazy_mmu_mode_enable(); /* -- 2.51.2

