Hello, I would like to report a potential security issue in the Linux kernel ext4 filesystem, which I found using a modified syzkaller-based kernel fuzzing tool that I developed. Summary ------- A local unprivileged user who can mount a crafted ext4 filesystem image and execute concurrent file operations (such as sendfile or write) can trigger a KASAN-reported slab-use-after-free in ext4_find_extent(). The bug is triggered by a crafted ext4 image where the eh_entries field of an extent header exceeds the eh_max field. This corruption leads to an out-of-bounds pointer calculation in EXT_LAST_EXTENT, causing the kernel to access freed memory during binary search operations. I have extracted the crafted ext4 image using python, which can pass the e2fsck checking without any error or warning. I verified this on Linux kernel version 6.12.51. Environment ----------- - Kernel version: 6.12.51 (built with KASAN, PREEMPT, SMP, NOPTI) - Architecture: x86_64 - Hypervisor: QEMU (Standard PC i440FX + PIIX, BIOS 1.13.0-1ubuntu1.1) - Filesystem: ext4, mounted from a crafted disk image via /dev/loopN Symptoms and logs ----------------- When running the syzkaller reproducer, the kernel crashes with a KASAN slab-use-after-free report. Relevant part of the KASAN report: [ 40.783761] BUG: KASAN: slab-use-after-free in ext4_find_extent+0x909/0x9e0 [ 40.784839] Read of size 4 at addr ffff8880030a8e0c by task kworker/u10:2/46 [ 40.785878] [ 40.786186] CPU: 1 UID: 0 PID: 46 Comm: kworker/u10:2 Not tainted 6.12.51 #4 [ 40.786206] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014 [ 40.786219] Workqueue: writeback wb_workfn (flush-7:0) [ 40.786243] Call Trace: [ 40.786250] [ 40.786257] dump_stack_lvl+0x7d/0xa0 [ 40.786301] print_report+0xcf/0x610 [ 40.786324] ? __virt_addr_valid+0xcb/0x320 [ 40.786348] ? ext4_find_extent+0x909/0x9e0 [ 40.786368] kasan_report+0xb5/0xe0 [ 40.786391] ? ext4_find_extent+0x909/0x9e0 [ 40.786413] ext4_find_extent+0x909/0x9e0 [ 40.786434] ext4_ext_map_blocks+0x13d/0x35b0 Reproducer ---------- The issue is reproducible with a C program generated automatically. The reproducer performs roughly the following steps: 1. Mounts a crafted ext4 image containing an inode with a corrupted extent header (eh_entries > eh_max). 2. Executes concurrent file operations (like sendfile) that trigger extent lookup on the corrupted inode. I am attaching the full C program as well as the simplified one for convenience. Also, I have extracted the corrupted file system and attached it as image.img. Security impact --------------- This is at least a local denial-of-service issue (kernel crash/panic) reachable by an unprivileged local user who can mount a crafted filesystem image. The out-of-bounds read accesses a freed slab object, which could potentially be exploited for further memory corruption. Because KASAN reports a slab use-after-free involving task_struct objects, I am not sure whether this can be further exploited for privilege escalation, but in principle it looks like a memory corruption bug. Patch -------------- This patch fixes a slab-use-after-free vulnerability in ext4_find_extent() that occurs when processing a corrupted filesystem image. When traversing the extent tree, if an extent header's eh_entries field is corrupted and exceeds eh_max, the EXT_LAST_EXTENT macro calculates a pointer that points beyond the allocated memory of the extent block. This leads to an out-of-bounds access in ext4_ext_binsearch_idx() or ext4_ext_binsearch(), which can access a freed slab object, triggering a KASAN panic. The fix enforces a consistency check in ext4_find_extent(). It verifies that eh_entries does not exceed eh_max before invoking the binary search functions. If the check fails, it reports an error via EXT4_ERROR_INODE and returns -EFSCORRUPTED, preventing the invalid memory access. Signed-off-by: 0ne1r0s --- fs/ext4/extents.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 34e25eee6521..2f420e04b095 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -929,7 +929,11 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block, while (i) { ext_debug(inode, "depth %d: num %d, max %d\n", ppos, le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max)); - + if (unlikely(le16_to_cpu(eh->eh_entries) > le16_to_cpu(eh->eh_max))) { + EXT4_ERROR_INODE(inode, "inode has invalid extent entries"); + ret = -EFSCORRUPTED; + goto err; + } ext4_ext_binsearch_idx(inode, path + ppos, block); path[ppos].p_block = ext4_idx_pblock(path[ppos].p_idx); path[ppos].p_depth = i; @@ -951,6 +955,11 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block, path[ppos].p_ext = NULL; path[ppos].p_idx = NULL; + if (unlikely(le16_to_cpu(eh->eh_entries) > le16_to_cpu(eh->eh_max))) { + EXT4_ERROR_INODE(inode, "inode has invalid extent entries"); + ret = -EFSCORRUPTED; + goto err; + } /* find extent */ ext4_ext_binsearch(inode, path + ppos, block); /* if not an empty leaf */ -- 2.51.0 Request ------- Could you please confirm if this is a known issue? And if it is considered a new security vulnerability, I would like to request or coordinate a CVE ID for it and will reference the relevant patch / mailing list thread in the CVE description. Thank you very much for your time and for maintaining ext4. Best regards, Haocheng Yu Zhejiang University