s390/kasan: fix large PMD pages address alignment check
authorAlexander Gordeev <agordeev@linux.ibm.com>
Fri, 6 Aug 2021 10:55:08 +0000 (12:55 +0200)
committerHeiko Carstens <hca@linux.ibm.com>
Wed, 25 Aug 2021 09:03:33 +0000 (11:03 +0200)
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>
arch/s390/mm/kasan_init.c

index facbf64..3e47351 100644 (file)
@@ -107,6 +107,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)) {
@@ -157,30 +160,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)) {