Patch "ext4: avoid OOB when system.data xattr changes underneath the filesystem" has been added to the 6.1-stable tree

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

 



This is a note to let you know that I've just added the patch titled

    ext4: avoid OOB when system.data xattr changes underneath the filesystem

to the 6.1-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     ext4-avoid-oob-when-system.data-xattr-changes-undern.patch
and it can be found in the queue-6.1 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit d091c92f4077f5e01178112dd631345da3a779c9
Author: Thadeu Lima de Souza Cascardo <cascardo@xxxxxxxxxx>
Date:   Wed Aug 21 12:23:24 2024 -0300

    ext4: avoid OOB when system.data xattr changes underneath the filesystem
    
    [ Upstream commit c6b72f5d82b1017bad80f9ebf502832fc321d796 ]
    
    When looking up for an entry in an inlined directory, 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.
    
    EXT4-fs (loop0): mounted filesystem 00000000-0000-0000-0000-000000000000 r/w without journal. Quota mode: none.
    loop0: detected capacity change from 2048 to 2047
    ==================================================================
    BUG: KASAN: use-after-free in ext4_search_dir+0xf2/0x1c0 fs/ext4/namei.c:1500
    Read of size 1 at addr ffff88803e91130f by task syz-executor269/5103
    
    CPU: 0 UID: 0 PID: 5103 Comm: syz-executor269 Not tainted 6.11.0-rc4-syzkaller #0
    Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
    Call Trace:
     <TASK>
     __dump_stack lib/dump_stack.c:93 [inline]
     dump_stack_lvl+0x241/0x360 lib/dump_stack.c:119
     print_address_description mm/kasan/report.c:377 [inline]
     print_report+0x169/0x550 mm/kasan/report.c:488
     kasan_report+0x143/0x180 mm/kasan/report.c:601
     ext4_search_dir+0xf2/0x1c0 fs/ext4/namei.c:1500
     ext4_find_inline_entry+0x4be/0x5e0 fs/ext4/inline.c:1697
     __ext4_find_entry+0x2b4/0x1b30 fs/ext4/namei.c:1573
     ext4_lookup_entry fs/ext4/namei.c:1727 [inline]
     ext4_lookup+0x15f/0x750 fs/ext4/namei.c:1795
     lookup_one_qstr_excl+0x11f/0x260 fs/namei.c:1633
     filename_create+0x297/0x540 fs/namei.c:3980
     do_symlinkat+0xf9/0x3a0 fs/namei.c:4587
     __do_sys_symlinkat fs/namei.c:4610 [inline]
     __se_sys_symlinkat fs/namei.c:4607 [inline]
     __x64_sys_symlinkat+0x95/0xb0 fs/namei.c:4607
     do_syscall_x64 arch/x86/entry/common.c:52 [inline]
     do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
     entry_SYSCALL_64_after_hwframe+0x77/0x7f
    RIP: 0033:0x7f3e73ced469
    Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 21 18 00 00 90 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 c7 c1 b8 ff ff ff f7 d8 64 89 01 48
    RSP: 002b:00007fff4d40c258 EFLAGS: 00000246 ORIG_RAX: 000000000000010a
    RAX: ffffffffffffffda RBX: 0032656c69662f2e RCX: 00007f3e73ced469
    RDX: 0000000020000200 RSI: 00000000ffffff9c RDI: 00000000200001c0
    RBP: 0000000000000000 R08: 00007fff4d40c290 R09: 00007fff4d40c290
    R10: 0023706f6f6c2f76 R11: 0000000000000246 R12: 00007fff4d40c27c
    R13: 0000000000000003 R14: 431bde82d7b634db R15: 00007fff4d40c2b0
     </TASK>
    
    Calling ext4_xattr_ibody_find right 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+0c2508114d912a54ee79@xxxxxxxxxxxxxxxxxxxxxxxxx
    Closes: https://syzkaller.appspot.com/bug?extid=0c2508114d912a54ee79
    Fixes: e8e948e7802a ("ext4: let ext4_find_entry handle inline data")
    Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@xxxxxxxxxx>
    Link: https://patch.msgid.link/20240821152324.3621860-5-cascardo@xxxxxxxxxx
    Signed-off-by: Theodore Ts'o <tytso@xxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index e6c2650335a9f..7c9efc9330fe1 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -1693,25 +1693,36 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir,
 					struct ext4_dir_entry_2 **res_dir,
 					int *has_inline_data)
 {
+	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;
-	struct ext4_iloc iloc;
 	void *inline_start;
 	int inline_size;
 
-	ret = ext4_get_inode_loc(dir, &iloc);
+	ret = ext4_get_inode_loc(dir, &is.iloc);
 	if (ret)
 		return ERR_PTR(ret);
 
 	down_read(&EXT4_I(dir)->xattr_sem);
+
+	ret = ext4_xattr_ibody_find(dir, &i, &is);
+	if (ret)
+		goto out;
+
 	if (!ext4_has_inline_data(dir)) {
 		*has_inline_data = 0;
 		goto out;
 	}
 
-	inline_start = (void *)ext4_raw_inode(&iloc)->i_block +
+	inline_start = (void *)ext4_raw_inode(&is.iloc)->i_block +
 						EXT4_INLINE_DOTDOT_SIZE;
 	inline_size = EXT4_MIN_INLINE_DATA_SIZE - EXT4_INLINE_DOTDOT_SIZE;
-	ret = ext4_search_dir(iloc.bh, inline_start, inline_size,
+	ret = ext4_search_dir(is.iloc.bh, inline_start, inline_size,
 			      dir, fname, 0, res_dir);
 	if (ret == 1)
 		goto out_find;
@@ -1721,23 +1732,23 @@ struct buffer_head *ext4_find_inline_entry(struct inode *dir,
 	if (ext4_get_inline_size(dir) == EXT4_MIN_INLINE_DATA_SIZE)
 		goto out;
 
-	inline_start = ext4_get_inline_xattr_pos(dir, &iloc);
+	inline_start = ext4_get_inline_xattr_pos(dir, &is.iloc);
 	inline_size = ext4_get_inline_size(dir) - EXT4_MIN_INLINE_DATA_SIZE;
 
-	ret = ext4_search_dir(iloc.bh, inline_start, inline_size,
+	ret = ext4_search_dir(is.iloc.bh, inline_start, inline_size,
 			      dir, fname, 0, res_dir);
 	if (ret == 1)
 		goto out_find;
 
 out:
-	brelse(iloc.bh);
+	brelse(is.iloc.bh);
 	if (ret < 0)
-		iloc.bh = ERR_PTR(ret);
+		is.iloc.bh = ERR_PTR(ret);
 	else
-		iloc.bh = NULL;
+		is.iloc.bh = NULL;
 out_find:
 	up_read(&EXT4_I(dir)->xattr_sem);
-	return iloc.bh;
+	return is.iloc.bh;
 }
 
 int ext4_delete_inline_entry(handle_t *handle,




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux