[syzbot] [ext4?] kernel BUG in ext4_update_inline_data

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



#syz test
From 4c910ac989e7a6d97565a67677a1ee88e2d1a9ad Mon Sep 17 00:00:00 2001
From: Moon Hee Lee <moonhee.lee.ca@xxxxxxxxx>
Date: Thu, 10 Jul 2025 00:36:59 -0700
Subject: [PATCH] ext4: bail out when INLINE_DATA_FL lacks system.data xattr

A syzbot fuzzed image triggered a BUG_ON in ext4_update_inline_data()
when an inode had the INLINE_DATA_FL flag set but was missing the
system.data extended attribute.

ext4_prepare_inline_data() now checks for the presence of that xattr
and returns -EFSCORRUPTED if it is missing, preventing corrupted inodes
from reaching the update path and triggering a crash.

Proof from e2fsck on the fuzzed image:

    $ e2fsck -fn mount_0
    e2fsck 1.47.0 (5-Feb-2023)
    One or more block group descriptor checksums are invalid.  Fix? no

    Group descriptor 0 checksum is 0x8245, should be 0x353a.  IGNORED.
    Pass 1: Checking inodes, blocks, and sizes
    Inode 12 has INLINE_DATA_FL flag but extended attribute not found.  Truncate? no

    Inode 16, i_blocks is 3298534883346, should be 18.  Fix? no

    Inode 17, i_blocks is 17592186044416, should be 0.  Fix? no

    Pass 2: Checking directory structure
    Symlink /file0/file1 (inode #14) is invalid.
    Clear? no

    Entry 'file1' in /file0 (12) has an incorrect filetype (was 7, should be 0).
    Fix? no

    Directory inode 11, block #5, offset 0: directory corrupted
    Salvage? no

    e2fsck: aborted

    syzkaller: ********** WARNING: Filesystem still has errors **********

Signed-off-by: Moon Hee Lee <moonhee.lee.ca@xxxxxxxxx>
---
 fs/ext4/inline.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index a1bbcdf40824..d9dcb0b09e5c 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -399,6 +399,13 @@ static int ext4_update_inline_data(handle_t *handle, struct inode *inode,
 static int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,
 				    loff_t len)
 {
+	struct ext4_xattr_ibody_find is = {
+		.s = { .not_found = -ENODATA, },
+	};
+	struct ext4_xattr_info i = {
+		.name_index = EXT4_XATTR_INDEX_SYSTEM,
+		.name = EXT4_XATTR_SYSTEM_DATA,
+	};
 	int ret, size, no_expand;
 	struct ext4_inode_info *ei = EXT4_I(inode);
 
@@ -409,6 +416,19 @@ static int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,
 	if (size < len)
 		return -ENOSPC;
 
+	ret = ext4_get_inode_loc(inode, &is.iloc);
+	if (ret)
+		goto out;
+
+	ret = ext4_xattr_ibody_find(inode, &i, &is);
+	if (ret)
+		goto out;
+
+	if (is.s.not_found) {
+		ret = -EFSCORRUPTED;
+		goto out;
+	}
+
 	ext4_write_lock_xattr(inode, &no_expand);
 
 	if (ei->i_inline_off)
@@ -417,6 +437,8 @@ static int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,
 		ret = ext4_create_inline_data(handle, inode, len);
 
 	ext4_write_unlock_xattr(inode, &no_expand);
+out:
+	brelse(is.iloc.bh);
 	return ret;
 }
 
-- 
2.43.0


[Index of Archives]     [Reiser Filesystem Development]     [Ceph FS]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite National Park]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]     [Linux Media]

  Powered by Linux