|
Jiri Slaby |
221c28 |
From: Baokun Li <libaokun1@huawei.com>
|
|
Jiri Slaby |
221c28 |
Date: Tue, 10 Jan 2023 21:34:36 +0800
|
|
Jiri Slaby |
221c28 |
Subject: [PATCH] ext4: fix task hung in ext4_xattr_delete_inode
|
|
Jiri Slaby |
221c28 |
References: bsc#1012628
|
|
Jiri Slaby |
221c28 |
Patch-mainline: 6.2.8
|
|
Jiri Slaby |
221c28 |
Git-commit: 0f7bfd6f8164be32dbbdf36aa1e5d00485c53cd7
|
|
Jiri Slaby |
221c28 |
|
|
Jiri Slaby |
221c28 |
[ Upstream commit 0f7bfd6f8164be32dbbdf36aa1e5d00485c53cd7 ]
|
|
Jiri Slaby |
221c28 |
|
|
Jiri Slaby |
221c28 |
Syzbot reported a hung task problem:
|
|
Jiri Slaby |
221c28 |
==================================================================
|
|
Jiri Slaby |
221c28 |
INFO: task syz-executor232:5073 blocked for more than 143 seconds.
|
|
Jiri Slaby |
221c28 |
Not tainted 6.2.0-rc2-syzkaller-00024-g512dee0c00ad #0
|
|
Jiri Slaby |
221c28 |
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
|
|
Jiri Slaby |
221c28 |
task:syz-exec232 state:D stack:21024 pid:5073 ppid:5072 flags:0x00004004
|
|
Jiri Slaby |
221c28 |
Call Trace:
|
|
Jiri Slaby |
221c28 |
<TASK>
|
|
Jiri Slaby |
221c28 |
context_switch kernel/sched/core.c:5244 [inline]
|
|
Jiri Slaby |
221c28 |
__schedule+0x995/0xe20 kernel/sched/core.c:6555
|
|
Jiri Slaby |
221c28 |
schedule+0xcb/0x190 kernel/sched/core.c:6631
|
|
Jiri Slaby |
221c28 |
__wait_on_freeing_inode fs/inode.c:2196 [inline]
|
|
Jiri Slaby |
221c28 |
find_inode_fast+0x35a/0x4c0 fs/inode.c:950
|
|
Jiri Slaby |
221c28 |
iget_locked+0xb1/0x830 fs/inode.c:1273
|
|
Jiri Slaby |
221c28 |
__ext4_iget+0x22e/0x3ed0 fs/ext4/inode.c:4861
|
|
Jiri Slaby |
221c28 |
ext4_xattr_inode_iget+0x68/0x4e0 fs/ext4/xattr.c:389
|
|
Jiri Slaby |
221c28 |
ext4_xattr_inode_dec_ref_all+0x1a7/0xe50 fs/ext4/xattr.c:1148
|
|
Jiri Slaby |
221c28 |
ext4_xattr_delete_inode+0xb04/0xcd0 fs/ext4/xattr.c:2880
|
|
Jiri Slaby |
221c28 |
ext4_evict_inode+0xd7c/0x10b0 fs/ext4/inode.c:296
|
|
Jiri Slaby |
221c28 |
evict+0x2a4/0x620 fs/inode.c:664
|
|
Jiri Slaby |
221c28 |
ext4_orphan_cleanup+0xb60/0x1340 fs/ext4/orphan.c:474
|
|
Jiri Slaby |
221c28 |
__ext4_fill_super fs/ext4/super.c:5516 [inline]
|
|
Jiri Slaby |
221c28 |
ext4_fill_super+0x81cd/0x8700 fs/ext4/super.c:5644
|
|
Jiri Slaby |
221c28 |
get_tree_bdev+0x400/0x620 fs/super.c:1282
|
|
Jiri Slaby |
221c28 |
vfs_get_tree+0x88/0x270 fs/super.c:1489
|
|
Jiri Slaby |
221c28 |
do_new_mount+0x289/0xad0 fs/namespace.c:3145
|
|
Jiri Slaby |
221c28 |
do_mount fs/namespace.c:3488 [inline]
|
|
Jiri Slaby |
221c28 |
__do_sys_mount fs/namespace.c:3697 [inline]
|
|
Jiri Slaby |
221c28 |
__se_sys_mount+0x2d3/0x3c0 fs/namespace.c:3674
|
|
Jiri Slaby |
221c28 |
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
|
|
Jiri Slaby |
221c28 |
do_syscall_64+0x3d/0xb0 arch/x86/entry/common.c:80
|
|
Jiri Slaby |
221c28 |
entry_SYSCALL_64_after_hwframe+0x63/0xcd
|
|
Jiri Slaby |
221c28 |
RIP: 0033:0x7fa5406fd5ea
|
|
Jiri Slaby |
221c28 |
RSP: 002b:00007ffc7232f968 EFLAGS: 00000202 ORIG_RAX: 00000000000000a5
|
|
Jiri Slaby |
221c28 |
RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00007fa5406fd5ea
|
|
Jiri Slaby |
221c28 |
RDX: 0000000020000440 RSI: 0000000020000000 RDI: 00007ffc7232f970
|
|
Jiri Slaby |
221c28 |
RBP: 00007ffc7232f970 R08: 00007ffc7232f9b0 R09: 0000000000000432
|
|
Jiri Slaby |
221c28 |
R10: 0000000000804a03 R11: 0000000000000202 R12: 0000000000000004
|
|
Jiri Slaby |
221c28 |
R13: 0000555556a7a2c0 R14: 00007ffc7232f9b0 R15: 0000000000000000
|
|
Jiri Slaby |
221c28 |
</TASK>
|
|
Jiri Slaby |
221c28 |
==================================================================
|
|
Jiri Slaby |
221c28 |
|
|
Jiri Slaby |
221c28 |
The problem is that the inode contains an xattr entry with ea_inum of 15
|
|
Jiri Slaby |
221c28 |
when cleaning up an orphan inode <15>. When evict inode <15>, the reference
|
|
Jiri Slaby |
221c28 |
counting of the corresponding EA inode is decreased. When EA inode <15> is
|
|
Jiri Slaby |
221c28 |
found by find_inode_fast() in __ext4_iget(), it is found that the EA inode
|
|
Jiri Slaby |
221c28 |
holds the I_FREEING flag and waits for the EA inode to complete deletion.
|
|
Jiri Slaby |
221c28 |
As a result, when inode <15> is being deleted, we wait for inode <15> to
|
|
Jiri Slaby |
221c28 |
complete the deletion, resulting in an infinite loop and triggering Hung
|
|
Jiri Slaby |
221c28 |
Task. To solve this problem, we only need to check whether the ino of EA
|
|
Jiri Slaby |
221c28 |
inode and parent is the same before getting EA inode.
|
|
Jiri Slaby |
221c28 |
|
|
Jiri Slaby |
221c28 |
Link: https://syzkaller.appspot.com/bug?extid=77d6fcc37bbb92f26048
|
|
Jiri Slaby |
221c28 |
Reported-by: syzbot+77d6fcc37bbb92f26048@syzkaller.appspotmail.com
|
|
Jiri Slaby |
221c28 |
Signed-off-by: Baokun Li <libaokun1@huawei.com>
|
|
Jiri Slaby |
221c28 |
Reviewed-by: Jan Kara <jack@suse.cz>
|
|
Jiri Slaby |
221c28 |
Link: https://lore.kernel.org/r/20230110133436.996350-1-libaokun1@huawei.com
|
|
Jiri Slaby |
221c28 |
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
|
|
Jiri Slaby |
221c28 |
Signed-off-by: Sasha Levin <sashal@kernel.org>
|
|
Jiri Slaby |
221c28 |
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
|
|
Jiri Slaby |
221c28 |
---
|
|
Jiri Slaby |
221c28 |
fs/ext4/xattr.c | 11 +++++++++++
|
|
Jiri Slaby |
221c28 |
1 file changed, 11 insertions(+)
|
|
Jiri Slaby |
221c28 |
|
|
Jiri Slaby |
221c28 |
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
|
|
Jiri Slaby |
221c28 |
index 494994d9..f66c3fae 100644
|
|
Jiri Slaby |
221c28 |
--- a/fs/ext4/xattr.c
|
|
Jiri Slaby |
221c28 |
+++ b/fs/ext4/xattr.c
|
|
Jiri Slaby |
221c28 |
@@ -388,6 +388,17 @@ static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino,
|
|
Jiri Slaby |
221c28 |
struct inode *inode;
|
|
Jiri Slaby |
221c28 |
int err;
|
|
Jiri Slaby |
221c28 |
|
|
Jiri Slaby |
221c28 |
+ /*
|
|
Jiri Slaby |
221c28 |
+ * We have to check for this corruption early as otherwise
|
|
Jiri Slaby |
221c28 |
+ * iget_locked() could wait indefinitely for the state of our
|
|
Jiri Slaby |
221c28 |
+ * parent inode.
|
|
Jiri Slaby |
221c28 |
+ */
|
|
Jiri Slaby |
221c28 |
+ if (parent->i_ino == ea_ino) {
|
|
Jiri Slaby |
221c28 |
+ ext4_error(parent->i_sb,
|
|
Jiri Slaby |
221c28 |
+ "Parent and EA inode have the same ino %lu", ea_ino);
|
|
Jiri Slaby |
221c28 |
+ return -EFSCORRUPTED;
|
|
Jiri Slaby |
221c28 |
+ }
|
|
Jiri Slaby |
221c28 |
+
|
|
Jiri Slaby |
221c28 |
inode = ext4_iget(parent->i_sb, ea_ino, EXT4_IGET_NORMAL);
|
|
Jiri Slaby |
221c28 |
if (IS_ERR(inode)) {
|
|
Jiri Slaby |
221c28 |
err = PTR_ERR(inode);
|
|
Jiri Slaby |
221c28 |
--
|
|
Jiri Slaby |
221c28 |
2.35.3
|
|
Jiri Slaby |
221c28 |
|