[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20241122113245.395016-1-cascardo@igalia.com>
Date: Fri, 22 Nov 2024 08:32:45 -0300
From: Thadeu Lima de Souza Cascardo <cascardo@...lia.com>
To: linux-ext4@...r.kernel.org
Cc: "Theodore Ts'o" <tytso@....edu>,
Andreas Dilger <adilger.kernel@...ger.ca>,
Tao Ma <boyu.mt@...bao.com>,
Thadeu Lima de Souza Cascardo <cascardo@...lia.com>,
syzbot+f6a8aa7e307cf6ee835e@...kaller.appspotmail.com
Subject: [PATCH] ext4: avoid OOB when converting inline data
When converting an inline file to non-inline, if e_value_offs is changed
underneath the filesystem by some change in the block device, it will lead
to an out-of-bounds access that KASAN detects as an UAF.
[ 17.272876] ==================================================================
[ 17.273620] BUG: KASAN: slab-use-after-free in ext4_read_inline_data+0x19c/0x270
[ 17.274286] Read of size 20 at addr ffff8880099821a3 by task repro/690
[ 17.274949]
[ 17.275487] CPU: 0 UID: 0 PID: 690 Comm: repro Not tainted 6.12.0-rc7-00078-g94f739ba5406 #164
[ 17.276372] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.15.0-1 04/01/2014
[ 17.277186] Call Trace:
[ 17.277524] <TASK>
[ 17.277824] dump_stack_lvl+0xf3/0x140
[ 17.278391] ? __pfx_dump_stack_lvl+0x10/0x10
[ 17.278949] ? _printk+0xa7/0xf0
[ 17.279381] ? __virt_addr_valid+0x142/0x340
[ 17.279919] print_report+0x163/0x4d0
[ 17.280381] ? __virt_addr_valid+0x142/0x340
[ 17.280882] ? __virt_addr_valid+0x2d9/0x340
[ 17.281286] ? ext4_read_inline_data+0x19c/0x270
[ 17.281720] kasan_report+0x99/0xd0
[ 17.282024] ? ext4_read_inline_data+0x19c/0x270
[ 17.282407] kasan_check_range+0x16a/0x170
[ 17.282686] ? ext4_read_inline_data+0x19c/0x270
[ 17.283364] __asan_memcpy+0x25/0x70
[ 17.283883] ext4_read_inline_data+0x19c/0x270
[ 17.284354] ext4_convert_inline_data_nolock+0x15b/0x7c0
[ 17.284893] ? find_held_lock+0x41/0x1d0
[ 17.285326] ? ext4_convert_inline_data+0x2f6/0x4d0
[ 17.285833] ? __pfx_ext4_convert_inline_data_nolock+0x10/0x10
[ 17.286390] ? ext4_convert_inline_data+0x26b/0x4d0
[ 17.286752] ? __pfx_down_write+0x10/0x10
[ 17.287037] ? ext4_journal_check_start+0x5e/0x1c0
[ 17.287342] ? __ext4_journal_start_sb+0x288/0x420
[ 17.287677] ext4_convert_inline_data+0x3aa/0x4d0
[ 17.288007] ? __pfx_ext4_convert_inline_data+0x10/0x10
[ 17.288373] ? lock_is_held_type+0x91/0x130
[ 17.288659] ext4_fallocate+0xd0/0x1840
[ 17.288927] vfs_fallocate+0x380/0x4d0
[ 17.289233] ksys_fallocate+0x33/0x60
[ 17.289532] __x64_sys_fallocate+0x92/0xb0
[ 17.289863] do_syscall_64+0xb6/0x160
[ 17.290170] ? clear_bhb_loop+0x45/0xa0
[ 17.290498] ? clear_bhb_loop+0x45/0xa0
[ 17.290828] entry_SYSCALL_64_after_hwframe+0x76/0x7e
[ 17.291265] RIP: 0033:0x7806623d0c7d
[ 17.291583] Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 73 81 0d 00 f7 d8 64 89 01 48
[ 17.294082] RSP: 002b:00007ffd763fc498 EFLAGS: 00000203 ORIG_RAX: 000000000000011d
[ 17.294838] RAX: ffffffffffffffda RBX: 00007ffd763fc5d8 RCX: 00007806623d0c7d
[ 17.295697] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000004
[ 17.296665] RBP: 00007ffd763fc4c0 R08: 0000000000000000 R09: 0000000000000000
[ 17.297621] R10: 0000000000008000 R11: 0000000000000203 R12: 0000000000000000
[ 17.298364] R13: 00007ffd763fc5e8 R14: 00005af91214ecc8 R15: 0000780662518000
[ 17.299062] </TASK>
Calling ext4_xattr_ibody_find after reading the inode with
ext4_get_inode_loc will lead to a check of the validity of the xattrs,
avoiding this problem.
Reported-by: syzbot+f6a8aa7e307cf6ee835e@...kaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=f6a8aa7e307cf6ee835e
Fixes: 0c8d414f163f ("ext4: let fallocate handle inline data correctly")
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@...lia.com>
---
fs/ext4/inline.c | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index 3536ca7e4fcc..401a224f0956 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -2022,9 +2022,15 @@ int ext4_inline_data_truncate(struct inode *inode, int *has_inline)
int ext4_convert_inline_data(struct inode *inode)
{
+ 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 error, needed_blocks, no_expand;
handle_t *handle;
- struct ext4_iloc iloc;
if (!ext4_has_inline_data(inode)) {
ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
@@ -2045,8 +2051,8 @@ int ext4_convert_inline_data(struct inode *inode)
needed_blocks = ext4_writepage_trans_blocks(inode);
- iloc.bh = NULL;
- error = ext4_get_inode_loc(inode, &iloc);
+ is.iloc.bh = NULL;
+ error = ext4_get_inode_loc(inode, &is.iloc);
if (error)
return error;
@@ -2057,11 +2063,17 @@ int ext4_convert_inline_data(struct inode *inode)
}
ext4_write_lock_xattr(inode, &no_expand);
+
+ error = ext4_xattr_ibody_find(inode, &i, &is);
+ if (error)
+ goto out_xattr;
+
if (ext4_has_inline_data(inode))
- error = ext4_convert_inline_data_nolock(handle, inode, &iloc);
+ error = ext4_convert_inline_data_nolock(handle, inode, &is.iloc);
+out_xattr:
ext4_write_unlock_xattr(inode, &no_expand);
ext4_journal_stop(handle);
out_free:
- brelse(iloc.bh);
+ brelse(is.iloc.bh);
return error;
}
--
2.34.1
Powered by blists - more mailing lists