s390/kasan: fix large PMD pages address alignment check

[ 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>
This commit is contained in:
Alexander Gordeev
2021-08-06 12:55:08 +02:00
committed by Greg Kroah-Hartman
parent 9d999957cb
commit 8b471e72b5

View File

@@ -108,6 +108,9 @@ static void __init kasan_early_vmemmap_populate(unsigned long address,
sgt_prot &= ~_SEGMENT_ENTRY_NOEXEC; sgt_prot &= ~_SEGMENT_ENTRY_NOEXEC;
} }
/*
* The first 1MB of 1:1 mapping is mapped with 4KB pages
*/
while (address < end) { while (address < end) {
pg_dir = pgd_offset_k(address); pg_dir = pgd_offset_k(address);
if (pgd_none(*pg_dir)) { if (pgd_none(*pg_dir)) {
@@ -165,17 +168,13 @@ static void __init kasan_early_vmemmap_populate(unsigned long address,
pm_dir = pmd_offset(pu_dir, address); pm_dir = pmd_offset(pu_dir, address);
if (pmd_none(*pm_dir)) { if (pmd_none(*pm_dir)) {
if (mode == POPULATE_ZERO_SHADOW && if (IS_ALIGNED(address, PMD_SIZE) &&
IS_ALIGNED(address, PMD_SIZE) &&
end - address >= PMD_SIZE) { end - address >= PMD_SIZE) {
pmd_populate(&init_mm, pm_dir, if (mode == POPULATE_ZERO_SHADOW) {
kasan_early_shadow_pte); pmd_populate(&init_mm, pm_dir, kasan_early_shadow_pte);
address = (address + PMD_SIZE) & PMD_MASK; address = (address + PMD_SIZE) & PMD_MASK;
continue; continue;
} } else if (has_edat && address) {
/* 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; void *page;
if (mode == POPULATE_ONE2ONE) { if (mode == POPULATE_ONE2ONE) {
@@ -188,7 +187,7 @@ static void __init kasan_early_vmemmap_populate(unsigned long address,
address = (address + PMD_SIZE) & PMD_MASK; address = (address + PMD_SIZE) & PMD_MASK;
continue; continue;
} }
}
pt_dir = kasan_early_pte_alloc(); pt_dir = kasan_early_pte_alloc();
pmd_populate(&init_mm, pm_dir, pt_dir); pmd_populate(&init_mm, pm_dir, pt_dir);
} else if (pmd_large(*pm_dir)) { } else if (pmd_large(*pm_dir)) {