Skip to content

Commit 4b2f167

Browse files
Thadeu Lima de Souza Cascardointel-lab-lkp
authored andcommitted
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 torvalds#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: [email protected] Closes: https://syzkaller.appspot.com/bug?extid=f6a8aa7e307cf6ee835e Fixes: 0c8d414 ("ext4: let fallocate handle inline data correctly") Signed-off-by: Thadeu Lima de Souza Cascardo <[email protected]>
1 parent 3e7c69c commit 4b2f167

File tree

1 file changed

+17
-5
lines changed

1 file changed

+17
-5
lines changed

fs/ext4/inline.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2022,9 +2022,15 @@ int ext4_inline_data_truncate(struct inode *inode, int *has_inline)
20222022

20232023
int ext4_convert_inline_data(struct inode *inode)
20242024
{
2025+
struct ext4_xattr_ibody_find is = {
2026+
.s = { .not_found = -ENODATA, },
2027+
};
2028+
struct ext4_xattr_info i = {
2029+
.name_index = EXT4_XATTR_INDEX_SYSTEM,
2030+
.name = EXT4_XATTR_SYSTEM_DATA,
2031+
};
20252032
int error, needed_blocks, no_expand;
20262033
handle_t *handle;
2027-
struct ext4_iloc iloc;
20282034

20292035
if (!ext4_has_inline_data(inode)) {
20302036
ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
@@ -2045,8 +2051,8 @@ int ext4_convert_inline_data(struct inode *inode)
20452051

20462052
needed_blocks = ext4_writepage_trans_blocks(inode);
20472053

2048-
iloc.bh = NULL;
2049-
error = ext4_get_inode_loc(inode, &iloc);
2054+
is.iloc.bh = NULL;
2055+
error = ext4_get_inode_loc(inode, &is.iloc);
20502056
if (error)
20512057
return error;
20522058

@@ -2057,11 +2063,17 @@ int ext4_convert_inline_data(struct inode *inode)
20572063
}
20582064

20592065
ext4_write_lock_xattr(inode, &no_expand);
2066+
2067+
error = ext4_xattr_ibody_find(inode, &i, &is);
2068+
if (error)
2069+
goto out_xattr;
2070+
20602071
if (ext4_has_inline_data(inode))
2061-
error = ext4_convert_inline_data_nolock(handle, inode, &iloc);
2072+
error = ext4_convert_inline_data_nolock(handle, inode, &is.iloc);
2073+
out_xattr:
20622074
ext4_write_unlock_xattr(inode, &no_expand);
20632075
ext4_journal_stop(handle);
20642076
out_free:
2065-
brelse(iloc.bh);
2077+
brelse(is.iloc.bh);
20662078
return error;
20672079
}

0 commit comments

Comments
 (0)