powerpc/mm: Fix UBSAN warning reported on hugetlb
authorAneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Thu, 8 Sep 2022 07:24:40 +0000 (12:54 +0530)
committerMichael Ellerman <mpe@ellerman.id.au>
Fri, 30 Sep 2022 08:35:52 +0000 (18:35 +1000)
Powerpc architecture supports 16GB hugetlb pages with hash translation.
For 4K page size, this is implemented as a hugepage directory entry at
PGD level and for 64K it is implemented as a huge page pte at PUD level

With 16GB hugetlb size, offset within a page is greater than 32 bits.
Hence switch to use unsigned long type when using hugepd_shift.

In order to keep things simpler, we make sure we always use unsigned
long type when using hugepd_shift() even though all the hugetlb page
size won't require that.

The hugetlb_free_p*d_range changes are all related to nohash usage where
we can have multiple pgd entries pointing to the same hugepd entries.
Hence on book3s64 where we can have > 4GB hugetlb page size we will
always find more < next even if we compute the value of more correctly.

Hence there is no functional change in this patch except that it fixes
the below warning.

  UBSAN: shift-out-of-bounds in arch/powerpc/mm/hugetlbpage.c:499:21
  shift exponent 34 is too large for 32-bit type 'int'
  CPU: 39 PID: 1673 Comm: a.out Not tainted 6.0.0-rc2-00327-gee88a56e8517-dirty #1
  Call Trace:
    dump_stack_lvl+0x98/0xe0 (unreliable)
    ubsan_epilogue+0x18/0x70
    __ubsan_handle_shift_out_of_bounds+0x1bc/0x390
    hugetlb_free_pgd_range+0x5d8/0x600
    free_pgtables+0x114/0x290
    exit_mmap+0x150/0x550
    mmput+0xcc/0x210
    do_exit+0x420/0xdd0
    do_group_exit+0x4c/0xd0
    sys_exit_group+0x24/0x30
    system_call_exception+0x250/0x600
    system_call_common+0xec/0x250

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
[mpe: Drop generic change to be sent separately, change 1ULL to 1UL]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20220908072440.258301-1-aneesh.kumar@linux.ibm.com
arch/powerpc/mm/hugetlbpage.c

index 8c3ea5300ac304ef4c0356b077270b36539b2ed2..5852a86d990d66f6b0ddf24db4dcee6fd0ab7fb9 100644 (file)
@@ -392,7 +392,7 @@ static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud,
                 * single hugepage, but all of them point to
                 * the same kmem cache that holds the hugepte.
                 */
-               more = addr + (1 << hugepd_shift(*(hugepd_t *)pmd));
+               more = addr + (1UL << hugepd_shift(*(hugepd_t *)pmd));
                if (more > next)
                        next = more;
 
@@ -434,7 +434,7 @@ static void hugetlb_free_pud_range(struct mmu_gather *tlb, p4d_t *p4d,
                         * single hugepage, but all of them point to
                         * the same kmem cache that holds the hugepte.
                         */
-                       more = addr + (1 << hugepd_shift(*(hugepd_t *)pud));
+                       more = addr + (1UL << hugepd_shift(*(hugepd_t *)pud));
                        if (more > next)
                                next = more;
 
@@ -496,7 +496,7 @@ void hugetlb_free_pgd_range(struct mmu_gather *tlb,
                         * for a single hugepage, but all of them point to the
                         * same kmem cache that holds the hugepte.
                         */
-                       more = addr + (1 << hugepd_shift(*(hugepd_t *)pgd));
+                       more = addr + (1UL << hugepd_shift(*(hugepd_t *)pgd));
                        if (more > next)
                                next = more;