]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
s390/mm: Allow large pages only for aligned physical addresses
authorAlexander Gordeev <agordeev@linux.ibm.com>
Fri, 7 Jun 2024 12:19:48 +0000 (14:19 +0200)
committerVasily Gorbik <gor@linux.ibm.com>
Tue, 11 Jun 2024 14:20:40 +0000 (16:20 +0200)
Do not allow creation of large pages against physical addresses,
which itself are not aligned on the correct boundary. Failure to
do so might lead to referencing wrong memory as result of the way
DAT works.

Fixes: c98d2ecae08f ("s390/mm: Uncouple physical vs virtual address spaces")
Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
arch/s390/boot/vmem.c

index 96d48b7112d40b09a6195f7b27fccd967ccbeab2..1f7dbb4b66b7010bba9fcd83cf41027a98bcc9b7 100644 (file)
@@ -267,15 +267,21 @@ static bool large_allowed(enum populate_mode mode)
 static bool can_large_pud(pud_t *pu_dir, unsigned long addr, unsigned long end,
                          enum populate_mode mode)
 {
+       unsigned long size = end - addr;
+
        return machine.has_edat2 && large_allowed(mode) &&
-              IS_ALIGNED(addr, PUD_SIZE) && (end - addr) >= PUD_SIZE;
+              IS_ALIGNED(addr, PUD_SIZE) && (size >= PUD_SIZE) &&
+              IS_ALIGNED(_pa(addr, size, mode), PUD_SIZE);
 }
 
 static bool can_large_pmd(pmd_t *pm_dir, unsigned long addr, unsigned long end,
                          enum populate_mode mode)
 {
+       unsigned long size = end - addr;
+
        return machine.has_edat1 && large_allowed(mode) &&
-              IS_ALIGNED(addr, PMD_SIZE) && (end - addr) >= PMD_SIZE;
+              IS_ALIGNED(addr, PMD_SIZE) && (size >= PMD_SIZE) &&
+              IS_ALIGNED(_pa(addr, size, mode), PMD_SIZE);
 }
 
 static void pgtable_pte_populate(pmd_t *pmd, unsigned long addr, unsigned long end,