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] <TASK>
[ 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 <yuhaocheng035@gmail.com>
---
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
� ` @ @ �3�h�3�h ��S� �3�h �G +� syzkaller /tmp/syz-imagegen1169330129 _����Cƃ$/� ��B @ �3�h
S "