CVE: CVE-2024-56628
Published: 2024-12-27
Description: In the Linux kernel, the following vulnerability has been resolved:

LoongArch: Add architecture specific huge_pte_clear()

When executing mm selftests run_vmtests.sh, there is such an error:

 BUG: Bad page state in process uffd-unit-tests  pfn:00000
 page: refcount:0 mapcount:0 mapping:[PII_REDACTED] index:0x0 pfn:0x0
 flags: 0xffff[PII_REDACTED](reserved|node=0|zone=0|lastcpupid=0xffff)
 raw: 00ffff[PII_REDACTED] ffffbf[PII_REDACTED] ffffbf[PII_REDACTED] [PII_REDACTED]
 raw: [PII_REDACTED] [PII_REDACTED] 00000000ffffffff [PII_REDACTED]
 page dumped because: PAGE_FLAGS_CHECK_AT_FREE flag(s) set
 Modules linked in: snd_seq_dummy snd_seq snd_seq_device rfkill vfat fat
    virtio_balloon efi_pstore virtio_net pstore net_failover failover fuse
    nfnetlink virtio_scsi virtio_gpu virtio_dma_buf dm_multipath efivarfs
 CPU: 2 UID: 0 PID: 1913 Comm: uffd-unit-tests Not tainted 6.12.0 #184
 Hardware name: QEMU QEMU Virtual Machine, BIOS unknown 2/2/2022
 Stack : 900000047c8ac000 [PII_REDACTED][PII_REDACTED]223a7c 900000047c8ac000
         900000047c8af[PII_REDACTED]47c8af698 [PII_REDACTED] 900000047c8af7d8
         900000047c8af7d0 900000047c8af7d0 900000047c8af5b0 [PII_REDACTED]
         [PII_REDACTED] 900000047c8af698 10b3c7d53da40d26 [PII_REDACTED]
         [PII_REDACTED] 0000000fffffffff fffffffffe000000 ffff[PII_REDACTED]00
        [PII_REDACTED]00002f [PII_REDACTED] 000000017a6d4[PII_REDACTED]0028f8940
         [PII_REDACTED] [PII_REDACTED][PII_REDACTED]5aa5e0 [PII_REDACTED]
         [PII_REDACTED][PII_REDACTED]8f8940 ffff[PII_REDACTED]00 [PII_REDACTED]
         [PII_REDACTED] [PII_REDACTED][PII_REDACTED]223a94[PII_REDACTED]01839c
        [PII_REDACTED]0000b0 [PII_REDACTED] [PII_REDACTED][PII_REDACTED]071c1d
         ...
 Call Trace:
 [<[PII_REDACTED]223a94>] show_stack+0x5c/0x180
 [<[PII_REDACTED]c3fd64>] dump_stack_lvl+0x6c/0xa0
 [<[PII_REDACTED]56aa08>] bad_page+0x1a0/0x1f0
 [<[PII_REDACTED]>] free_unref_folios+0xbf0/0xd20
 [<[PII_REDACTED]4e65cc>] folios_put_refs+0x1a4/0x2b8
 [<[PII_REDACTED]599a0c>] free_pages_and_swap_cache+0x164/0x260
 [<[PII_REDACTED]>] tlb_batch_pages_flush+0xa8/0x1c0
 [<[PII_REDACTED]547f30>] tlb_finish_mmu+0xa8/0x218
 [<[PII_REDACTED]543cb8>] exit_mmap+0x1a0/0x360
 [<[PII_REDACTED]>] __mmput+0x78/0x200
 [<[PII_REDACTED]25583c>] do_exit+0x43c/0xde8
 [<[PII_REDACTED]>] do_group_exit+0x68/0x110
 [<[PII_REDACTED]>] sys_exit_group+0x1c/0x20
 [<[PII_REDACTED]c413b4>] do_syscall+0x94/0x130
 [<[PII_REDACTED]2216d8>] handle_syscall+0xb8/0x158
 Disabling lock debugging due to kernel taint
 BUG: non-zero pgtables_bytes on freeing mm: -16384

On LoongArch system, invalid huge pte entry should be invalid_pte_table
or a single _PAGE_HUGE bit rather than a zero value. And it should be
the same with invalid pmd entry, since pmd_none() is called by function
free_pgd_range() and pmd_none() return 0 by huge_pte_clear(). So single
_PAGE_HUGE bit is also treated as a valid pte table and free_pte_range()
will be called in free_pmd_range().

  free_pmd_range()
        pmd = pmd_offset(pud, addr);
        do {
                next = pmd_addr_end(addr, end);
                if (pmd_none_or_clear_bad(pmd))
                        continue;
                free_pte_range(tlb, pmd, addr);
        } while (pmd++, addr = next, addr != end);

Here invalid_pte_table is used for both invalid huge pte entry and
pmd entry.
CVSS Score: 7.8 (HIGH)
References: https://git.kernel.org/stable/c/7cd1f5f77925ae905a57296932f0f9ef0dc364f8; https://git.kernel.org/stable/c/7dfbf011a57b9e1a40f5ce8080a53c497e105c6c; https://git.kernel.org/stable/c/9b602190cf2d8ac957be0011e418ed6c3b49b9a3