| From 935da9b67a16cd032cee9f77549fab943d75e15e Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 6 Aug 2021 12:55:08 +0200 |
| Subject: s390/kasan: fix large PMD pages address alignment check |
| |
| From: Alexander Gordeev <agordeev@linux.ibm.com> |
| |
| [ Upstream commit ddd63c85ef67ea9ea7282ad35eafb6568047126e ] |
| |
| It is currently possible to initialize a large PMD page when |
| the address is not aligned on page boundary. |
| |
| Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com> |
| Reviewed-by: Vasily Gorbik <gor@linux.ibm.com> |
| Signed-off-by: Vasily Gorbik <gor@linux.ibm.com> |
| Signed-off-by: Heiko Carstens <hca@linux.ibm.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| arch/s390/mm/kasan_init.c | 41 +++++++++++++++++++-------------------- |
| 1 file changed, 20 insertions(+), 21 deletions(-) |
| |
| diff --git a/arch/s390/mm/kasan_init.c b/arch/s390/mm/kasan_init.c |
| index db4d303aaaa9..d7fcfe97d168 100644 |
| --- a/arch/s390/mm/kasan_init.c |
| +++ b/arch/s390/mm/kasan_init.c |
| @@ -108,6 +108,9 @@ static void __init kasan_early_pgtable_populate(unsigned long address, |
| sgt_prot &= ~_SEGMENT_ENTRY_NOEXEC; |
| } |
| |
| + /* |
| + * The first 1MB of 1:1 mapping is mapped with 4KB pages |
| + */ |
| while (address < end) { |
| pg_dir = pgd_offset_k(address); |
| if (pgd_none(*pg_dir)) { |
| @@ -158,30 +161,26 @@ static void __init kasan_early_pgtable_populate(unsigned long address, |
| |
| pm_dir = pmd_offset(pu_dir, address); |
| if (pmd_none(*pm_dir)) { |
| - if (mode == POPULATE_ZERO_SHADOW && |
| - IS_ALIGNED(address, PMD_SIZE) && |
| + if (IS_ALIGNED(address, PMD_SIZE) && |
| end - address >= PMD_SIZE) { |
| - pmd_populate(&init_mm, pm_dir, |
| - kasan_early_shadow_pte); |
| - address = (address + PMD_SIZE) & PMD_MASK; |
| - continue; |
| - } |
| - /* the first megabyte of 1:1 is mapped with 4k pages */ |
| - if (has_edat && address && end - address >= PMD_SIZE && |
| - mode != POPULATE_ZERO_SHADOW) { |
| - void *page; |
| - |
| - if (mode == POPULATE_ONE2ONE) { |
| - page = (void *)address; |
| - } else { |
| - page = kasan_early_alloc_segment(); |
| - memset(page, 0, _SEGMENT_SIZE); |
| + if (mode == POPULATE_ZERO_SHADOW) { |
| + pmd_populate(&init_mm, pm_dir, kasan_early_shadow_pte); |
| + address = (address + PMD_SIZE) & PMD_MASK; |
| + continue; |
| + } else if (has_edat && address) { |
| + void *page; |
| + |
| + if (mode == POPULATE_ONE2ONE) { |
| + page = (void *)address; |
| + } else { |
| + page = kasan_early_alloc_segment(); |
| + memset(page, 0, _SEGMENT_SIZE); |
| + } |
| + pmd_val(*pm_dir) = __pa(page) | sgt_prot; |
| + address = (address + PMD_SIZE) & PMD_MASK; |
| + continue; |
| } |
| - pmd_val(*pm_dir) = __pa(page) | sgt_prot; |
| - address = (address + PMD_SIZE) & PMD_MASK; |
| - continue; |
| } |
| - |
| pt_dir = kasan_early_pte_alloc(); |
| pmd_populate(&init_mm, pm_dir, pt_dir); |
| } else if (pmd_large(*pm_dir)) { |
| -- |
| 2.30.2 |
| |