cve/2024/CVE-2024-42243.md
2024-08-08 18:49:29 +00:00

4.3 KiB

CVE-2024-42243

Description

In the Linux kernel, the following vulnerability has been resolved:mm/filemap: make MAX_PAGECACHE_ORDER acceptable to xarrayPatch series "mm/filemap: Limit page cache size to that supported byxarray", v2.Currently, xarray can't support arbitrary page cache size. More detailscan be found from the WARN_ON() statement in xas_split_alloc(). In ourtest whose code is attached below, we hit the WARN_ON() on ARM64 systemwhere the base page size is 64KB and huge page size is 512MB. The issuewas reported long time ago and some discussions on it can be found here[1].[1] https://www.spinics.net/lists/linux-xfs/msg75404.htmlIn order to fix the issue, we need to adjust MAX_PAGECACHE_ORDER to onesupported by xarray and avoid PMD-sized page cache if needed. The codechanges are suggested by David Hildenbrand.PATCH[1] adjusts MAX_PAGECACHE_ORDER to that supported by xarrayPATCH[2-3] avoids PMD-sized page cache in the synchronous readahead pathPATCH[4] avoids PMD-sized page cache for shmem files if neededTest program============# cat test.c#define _GNU_SOURCE#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <fcntl.h>#include <errno.h>#include <sys/syscall.h>#include <sys/mman.h>#define TEST_XFS_FILENAME "/tmp/data"#define TEST_SHMEM_FILENAME "/dev/shm/data"#define TEST_MEM_SIZE 0x20000000int main(int argc, char **argv){ const char *filename; int fd = 0; void *buf = (void *)-1, p; int pgsize = getpagesize(); int ret; if (pgsize != 0x10000) { fprintf(stderr, "64KB base page size is required\n"); return -EPERM; } system("echo force > /sys/kernel/mm/transparent_hugepage/shmem_enabled"); system("rm -fr /tmp/data"); system("rm -fr /dev/shm/data"); system("echo 1 > /proc/sys/vm/drop_caches"); / Open xfs or shmem file / filename = TEST_XFS_FILENAME; if (argc > 1 && !strcmp(argv[1], "shmem")) filename = TEST_SHMEM_FILENAME; fd = open(filename, O_CREAT | O_RDWR | O_TRUNC); if (fd < 0) { fprintf(stderr, "Unable to open <%s>\n", filename); return -EIO; } / Extend file size / ret = ftruncate(fd, TEST_MEM_SIZE); if (ret) { fprintf(stderr, "Error %d to ftruncate()\n", ret); goto cleanup; } / Create VMA */ buf = mmap(NULL, TEST_MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (buf == (void )-1) { fprintf(stderr, "Unable to mmap <%s>\n", filename); goto cleanup; } fprintf(stdout, "mapped buffer at 0x%p\n", buf); ret = madvise(buf, TEST_MEM_SIZE, MADV_HUGEPAGE); if (ret) { fprintf(stderr, "Unable to madvise(MADV_HUGEPAGE)\n"); goto cleanup; } / Populate VMA / ret = madvise(buf, TEST_MEM_SIZE, MADV_POPULATE_WRITE); if (ret) { fprintf(stderr, "Error %d to madvise(MADV_POPULATE_WRITE)\n", ret); goto cleanup; } / Punch the file to enforce xarray split */ ret = fallocate(fd, FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE, TEST_MEM_SIZE - pgsize, pgsize); if (ret) fprintf(stderr, "Error %d to fallocate()\n", ret);cleanup: if (buf != (void *)-1) munmap(buf, TEST_MEM_SIZE); if (fd > 0) close(fd); return 0;}# gcc test.c -o test# cat /proc/1/smaps | grep KernelPageSize | head -n 1KernelPageSize: 64 kB# ./test shmem :------------[ cut here ]------------WARNING: CPU: 17 PID: 5253 at lib/xarray.c:1025 xas_split_alloc+0xf8/0x128Modules linked in: nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib \nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject nft_ct \nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 \ip_set nf_tables rfkill nfnetlink vfat fat virtio_balloon \drm fuse xfs libcrc32c crct10dif_ce ghash_ce sha2_ce sha256_arm64 \virtio_net sha1_ce net_failover failover virtio_console virtio_blk \dimlib virtio_mmioCPU: 17 PID: 5253 Comm: test Kdump: loaded Tainted: G W 6.10.0-rc5-gavin+ #12Hardware name: QEMU KVM Virtual Machine, BIOS edk2-20240524-1.el9 05/24/2024pstate: 83400005 (Nzcv daif +PAN -UAO +TC---truncated---

POC

Reference

No PoCs from references.

Github