mm/ioremap: check virtual address alignment while creating huge mappings
authorAnshuman Khandual <anshuman.khandual@arm.com>
Tue, 16 Jul 2019 23:27:30 +0000 (16:27 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 17 Jul 2019 02:23:22 +0000 (19:23 -0700)
Virtual address alignment is essential in ensuring correct clearing for
all intermediate level pgtable entries and freeing associated pgtable
pages.  An unaligned address can end up randomly freeing pgtable page
that potentially still contains valid mappings.  Hence also check it's
alignment along with existing phys_addr check.

Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Cc: Toshi Kani <toshi.kani@hpe.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Chintan Pandya <cpandya@codeaurora.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
lib/ioremap.c

index 063213685563c30c2575161f4fbc92dc1bb53d64..a95161d9c883cc54c4971d6eb44ffa0e57fcf83b 100644 (file)
@@ -86,6 +86,9 @@ static int ioremap_try_huge_pmd(pmd_t *pmd, unsigned long addr,
        if ((end - addr) != PMD_SIZE)
                return 0;
 
+       if (!IS_ALIGNED(addr, PMD_SIZE))
+               return 0;
+
        if (!IS_ALIGNED(phys_addr, PMD_SIZE))
                return 0;
 
@@ -126,6 +129,9 @@ static int ioremap_try_huge_pud(pud_t *pud, unsigned long addr,
        if ((end - addr) != PUD_SIZE)
                return 0;
 
+       if (!IS_ALIGNED(addr, PUD_SIZE))
+               return 0;
+
        if (!IS_ALIGNED(phys_addr, PUD_SIZE))
                return 0;
 
@@ -166,6 +172,9 @@ static int ioremap_try_huge_p4d(p4d_t *p4d, unsigned long addr,
        if ((end - addr) != P4D_SIZE)
                return 0;
 
+       if (!IS_ALIGNED(addr, P4D_SIZE))
+               return 0;
+
        if (!IS_ALIGNED(phys_addr, P4D_SIZE))
                return 0;