* [PATCH AUTOSEL 5.4 05/21] ext4: fix i_data_sem unlock order in ext4_ind_migrate()
[not found] <20241004183105.3675901-1-sashal@kernel.org>
@ 2024-10-04 18:30 ` Sasha Levin
2024-10-04 18:30 ` [PATCH AUTOSEL 5.4 06/21] ext4: ext4_search_dir should return a proper error Sasha Levin
2024-10-04 18:30 ` [PATCH AUTOSEL 5.4 07/21] ext4: nested locking for xattr inode Sasha Levin
2 siblings, 0 replies; 3+ messages in thread
From: Sasha Levin @ 2024-10-04 18:30 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Artem Sadovnikov, Ritesh Harjani, Mikhail Ukhin,
Theodore Ts'o, Sasha Levin, adilger.kernel, linux-ext4
From: Artem Sadovnikov <ancowi69@gmail.com>
[ Upstream commit cc749e61c011c255d81b192a822db650c68b313f ]
Fuzzing reports a possible deadlock in jbd2_log_wait_commit.
This issue is triggered when an EXT4_IOC_MIGRATE ioctl is set to require
synchronous updates because the file descriptor is opened with O_SYNC.
This can lead to the jbd2_journal_stop() function calling
jbd2_might_wait_for_commit(), potentially causing a deadlock if the
EXT4_IOC_MIGRATE call races with a write(2) system call.
This problem only arises when CONFIG_PROVE_LOCKING is enabled. In this
case, the jbd2_might_wait_for_commit macro locks jbd2_handle in the
jbd2_journal_stop function while i_data_sem is locked. This triggers
lockdep because the jbd2_journal_start function might also lock the same
jbd2_handle simultaneously.
Found by Linux Verification Center (linuxtesting.org) with syzkaller.
Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
Co-developed-by: Mikhail Ukhin <mish.uxin2012@yandex.ru>
Signed-off-by: Mikhail Ukhin <mish.uxin2012@yandex.ru>
Signed-off-by: Artem Sadovnikov <ancowi69@gmail.com>
Rule: add
Link: https://lore.kernel.org/stable/20240404095000.5872-1-mish.uxin2012%40yandex.ru
Link: https://patch.msgid.link/20240829152210.2754-1-ancowi69@gmail.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/ext4/migrate.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
index dbba3c3a2f064..ebee8c94b5fe6 100644
--- a/fs/ext4/migrate.c
+++ b/fs/ext4/migrate.c
@@ -678,8 +678,8 @@ int ext4_ind_migrate(struct inode *inode)
ei->i_data[i] = cpu_to_le32(blk++);
ext4_mark_inode_dirty(handle, inode);
errout:
- ext4_journal_stop(handle);
up_write(&EXT4_I(inode)->i_data_sem);
+ ext4_journal_stop(handle);
out_unlock:
percpu_up_write(&sbi->s_writepages_rwsem);
return ret;
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH AUTOSEL 5.4 06/21] ext4: ext4_search_dir should return a proper error
[not found] <20241004183105.3675901-1-sashal@kernel.org>
2024-10-04 18:30 ` [PATCH AUTOSEL 5.4 05/21] ext4: fix i_data_sem unlock order in ext4_ind_migrate() Sasha Levin
@ 2024-10-04 18:30 ` Sasha Levin
2024-10-04 18:30 ` [PATCH AUTOSEL 5.4 07/21] ext4: nested locking for xattr inode Sasha Levin
2 siblings, 0 replies; 3+ messages in thread
From: Sasha Levin @ 2024-10-04 18:30 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Thadeu Lima de Souza Cascardo, Theodore Ts'o, Sasha Levin,
adilger.kernel, linux-ext4
From: Thadeu Lima de Souza Cascardo <cascardo@igalia.com>
[ Upstream commit cd69f8f9de280e331c9e6ff689ced0a688a9ce8f ]
ext4_search_dir currently returns -1 in case of a failure, while it returns
0 when the name is not found. In such failure cases, it should return an
error code instead.
This becomes even more important when ext4_find_inline_entry returns an
error code as well in the next commit.
-EFSCORRUPTED seems appropriate as such error code as these failures would
be caused by unexpected record lengths and is in line with other instances
of ext4_check_dir_entry failures.
In the case of ext4_dx_find_entry, the current use of ERR_BAD_DX_DIR was
left as is to reduce the risk of regressions.
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@igalia.com>
Link: https://patch.msgid.link/20240821152324.3621860-2-cascardo@igalia.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/ext4/namei.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index e4fbc0f07eed2..dd795e10486b2 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1417,7 +1417,7 @@ static inline bool ext4_match(const struct inode *parent,
}
/*
- * Returns 0 if not found, -1 on failure, and 1 on success
+ * Returns 0 if not found, -EFSCORRUPTED on failure, and 1 on success
*/
int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
struct inode *dir, struct ext4_filename *fname,
@@ -1438,7 +1438,7 @@ int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
* a full check */
if (ext4_check_dir_entry(dir, NULL, de, bh, search_buf,
buf_size, offset))
- return -1;
+ return -EFSCORRUPTED;
*res_dir = de;
return 1;
}
@@ -1446,7 +1446,7 @@ int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
de_len = ext4_rec_len_from_disk(de->rec_len,
dir->i_sb->s_blocksize);
if (de_len <= 0)
- return -1;
+ return -EFSCORRUPTED;
offset += de_len;
de = (struct ext4_dir_entry_2 *) ((char *) de + de_len);
}
@@ -1596,8 +1596,10 @@ static struct buffer_head *__ext4_find_entry(struct inode *dir,
goto cleanup_and_exit;
} else {
brelse(bh);
- if (i < 0)
+ if (i < 0) {
+ ret = ERR_PTR(i);
goto cleanup_and_exit;
+ }
}
next:
if (++block >= nblocks)
@@ -1691,7 +1693,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
if (retval == 1)
goto success;
brelse(bh);
- if (retval == -1) {
+ if (retval < 0) {
bh = ERR_PTR(ERR_BAD_DX_DIR);
goto errout;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH AUTOSEL 5.4 07/21] ext4: nested locking for xattr inode
[not found] <20241004183105.3675901-1-sashal@kernel.org>
2024-10-04 18:30 ` [PATCH AUTOSEL 5.4 05/21] ext4: fix i_data_sem unlock order in ext4_ind_migrate() Sasha Levin
2024-10-04 18:30 ` [PATCH AUTOSEL 5.4 06/21] ext4: ext4_search_dir should return a proper error Sasha Levin
@ 2024-10-04 18:30 ` Sasha Levin
2 siblings, 0 replies; 3+ messages in thread
From: Sasha Levin @ 2024-10-04 18:30 UTC (permalink / raw)
To: linux-kernel, stable
Cc: Wojciech Gładysz, Theodore Ts'o, Sasha Levin,
adilger.kernel, linux-ext4
From: Wojciech Gładysz <wojciech.gladysz@infogain.com>
[ Upstream commit d1bc560e9a9c78d0b2314692847fc8661e0aeb99 ]
Add nested locking with I_MUTEX_XATTR subclass to avoid lockdep warning
while handling xattr inode on file open syscall at ext4_xattr_inode_iget.
Backtrace
EXT4-fs (loop0): Ignoring removed oldalloc option
======================================================
WARNING: possible circular locking dependency detected
5.10.0-syzkaller #0 Not tainted
------------------------------------------------------
syz-executor543/2794 is trying to acquire lock:
ffff8880215e1a48 (&ea_inode->i_rwsem#7/1){+.+.}-{3:3}, at: inode_lock include/linux/fs.h:782 [inline]
ffff8880215e1a48 (&ea_inode->i_rwsem#7/1){+.+.}-{3:3}, at: ext4_xattr_inode_iget+0x42a/0x5c0 fs/ext4/xattr.c:425
but task is already holding lock:
ffff8880215e3278 (&ei->i_data_sem/3){++++}-{3:3}, at: ext4_setattr+0x136d/0x19c0 fs/ext4/inode.c:5559
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #1 (&ei->i_data_sem/3){++++}-{3:3}:
lock_acquire+0x197/0x480 kernel/locking/lockdep.c:5566
down_write+0x93/0x180 kernel/locking/rwsem.c:1564
ext4_update_i_disksize fs/ext4/ext4.h:3267 [inline]
ext4_xattr_inode_write fs/ext4/xattr.c:1390 [inline]
ext4_xattr_inode_lookup_create fs/ext4/xattr.c:1538 [inline]
ext4_xattr_set_entry+0x331a/0x3d80 fs/ext4/xattr.c:1662
ext4_xattr_ibody_set+0x124/0x390 fs/ext4/xattr.c:2228
ext4_xattr_set_handle+0xc27/0x14e0 fs/ext4/xattr.c:2385
ext4_xattr_set+0x219/0x390 fs/ext4/xattr.c:2498
ext4_xattr_user_set+0xc9/0xf0 fs/ext4/xattr_user.c:40
__vfs_setxattr+0x404/0x450 fs/xattr.c:177
__vfs_setxattr_noperm+0x11d/0x4f0 fs/xattr.c:208
__vfs_setxattr_locked+0x1f9/0x210 fs/xattr.c:266
vfs_setxattr+0x112/0x2c0 fs/xattr.c:283
setxattr+0x1db/0x3e0 fs/xattr.c:548
path_setxattr+0x15a/0x240 fs/xattr.c:567
__do_sys_setxattr fs/xattr.c:582 [inline]
__se_sys_setxattr fs/xattr.c:578 [inline]
__x64_sys_setxattr+0xc5/0xe0 fs/xattr.c:578
do_syscall_64+0x6d/0xa0 arch/x86/entry/common.c:62
entry_SYSCALL_64_after_hwframe+0x61/0xcb
-> #0 (&ea_inode->i_rwsem#7/1){+.+.}-{3:3}:
check_prev_add kernel/locking/lockdep.c:2988 [inline]
check_prevs_add kernel/locking/lockdep.c:3113 [inline]
validate_chain+0x1695/0x58f0 kernel/locking/lockdep.c:3729
__lock_acquire+0x12fd/0x20d0 kernel/locking/lockdep.c:4955
lock_acquire+0x197/0x480 kernel/locking/lockdep.c:5566
down_write+0x93/0x180 kernel/locking/rwsem.c:1564
inode_lock include/linux/fs.h:782 [inline]
ext4_xattr_inode_iget+0x42a/0x5c0 fs/ext4/xattr.c:425
ext4_xattr_inode_get+0x138/0x410 fs/ext4/xattr.c:485
ext4_xattr_move_to_block fs/ext4/xattr.c:2580 [inline]
ext4_xattr_make_inode_space fs/ext4/xattr.c:2682 [inline]
ext4_expand_extra_isize_ea+0xe70/0x1bb0 fs/ext4/xattr.c:2774
__ext4_expand_extra_isize+0x304/0x3f0 fs/ext4/inode.c:5898
ext4_try_to_expand_extra_isize fs/ext4/inode.c:5941 [inline]
__ext4_mark_inode_dirty+0x591/0x810 fs/ext4/inode.c:6018
ext4_setattr+0x1400/0x19c0 fs/ext4/inode.c:5562
notify_change+0xbb6/0xe60 fs/attr.c:435
do_truncate+0x1de/0x2c0 fs/open.c:64
handle_truncate fs/namei.c:2970 [inline]
do_open fs/namei.c:3311 [inline]
path_openat+0x29f3/0x3290 fs/namei.c:3425
do_filp_open+0x20b/0x450 fs/namei.c:3452
do_sys_openat2+0x124/0x460 fs/open.c:1207
do_sys_open fs/open.c:1223 [inline]
__do_sys_open fs/open.c:1231 [inline]
__se_sys_open fs/open.c:1227 [inline]
__x64_sys_open+0x221/0x270 fs/open.c:1227
do_syscall_64+0x6d/0xa0 arch/x86/entry/common.c:62
entry_SYSCALL_64_after_hwframe+0x61/0xcb
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(&ei->i_data_sem/3);
lock(&ea_inode->i_rwsem#7/1);
lock(&ei->i_data_sem/3);
lock(&ea_inode->i_rwsem#7/1);
*** DEADLOCK ***
5 locks held by syz-executor543/2794:
#0: ffff888026fbc448 (sb_writers#4){.+.+}-{0:0}, at: mnt_want_write+0x4a/0x2a0 fs/namespace.c:365
#1: ffff8880215e3488 (&sb->s_type->i_mutex_key#7){++++}-{3:3}, at: inode_lock include/linux/fs.h:782 [inline]
#1: ffff8880215e3488 (&sb->s_type->i_mutex_key#7){++++}-{3:3}, at: do_truncate+0x1cf/0x2c0 fs/open.c:62
#2: ffff8880215e3310 (&ei->i_mmap_sem){++++}-{3:3}, at: ext4_setattr+0xec4/0x19c0 fs/ext4/inode.c:5519
#3: ffff8880215e3278 (&ei->i_data_sem/3){++++}-{3:3}, at: ext4_setattr+0x136d/0x19c0 fs/ext4/inode.c:5559
#4: ffff8880215e30c8 (&ei->xattr_sem){++++}-{3:3}, at: ext4_write_trylock_xattr fs/ext4/xattr.h:162 [inline]
#4: ffff8880215e30c8 (&ei->xattr_sem){++++}-{3:3}, at: ext4_try_to_expand_extra_isize fs/ext4/inode.c:5938 [inline]
#4: ffff8880215e30c8 (&ei->xattr_sem){++++}-{3:3}, at: __ext4_mark_inode_dirty+0x4fb/0x810 fs/ext4/inode.c:6018
stack backtrace:
CPU: 1 PID: 2794 Comm: syz-executor543 Not tainted 5.10.0-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 03/27/2024
Call Trace:
__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0x177/0x211 lib/dump_stack.c:118
print_circular_bug+0x146/0x1b0 kernel/locking/lockdep.c:2002
check_noncircular+0x2cc/0x390 kernel/locking/lockdep.c:2123
check_prev_add kernel/locking/lockdep.c:2988 [inline]
check_prevs_add kernel/locking/lockdep.c:3113 [inline]
validate_chain+0x1695/0x58f0 kernel/locking/lockdep.c:3729
__lock_acquire+0x12fd/0x20d0 kernel/locking/lockdep.c:4955
lock_acquire+0x197/0x480 kernel/locking/lockdep.c:5566
down_write+0x93/0x180 kernel/locking/rwsem.c:1564
inode_lock include/linux/fs.h:782 [inline]
ext4_xattr_inode_iget+0x42a/0x5c0 fs/ext4/xattr.c:425
ext4_xattr_inode_get+0x138/0x410 fs/ext4/xattr.c:485
ext4_xattr_move_to_block fs/ext4/xattr.c:2580 [inline]
ext4_xattr_make_inode_space fs/ext4/xattr.c:2682 [inline]
ext4_expand_extra_isize_ea+0xe70/0x1bb0 fs/ext4/xattr.c:2774
__ext4_expand_extra_isize+0x304/0x3f0 fs/ext4/inode.c:5898
ext4_try_to_expand_extra_isize fs/ext4/inode.c:5941 [inline]
__ext4_mark_inode_dirty+0x591/0x810 fs/ext4/inode.c:6018
ext4_setattr+0x1400/0x19c0 fs/ext4/inode.c:5562
notify_change+0xbb6/0xe60 fs/attr.c:435
do_truncate+0x1de/0x2c0 fs/open.c:64
handle_truncate fs/namei.c:2970 [inline]
do_open fs/namei.c:3311 [inline]
path_openat+0x29f3/0x3290 fs/namei.c:3425
do_filp_open+0x20b/0x450 fs/namei.c:3452
do_sys_openat2+0x124/0x460 fs/open.c:1207
do_sys_open fs/open.c:1223 [inline]
__do_sys_open fs/open.c:1231 [inline]
__se_sys_open fs/open.c:1227 [inline]
__x64_sys_open+0x221/0x270 fs/open.c:1227
do_syscall_64+0x6d/0xa0 arch/x86/entry/common.c:62
entry_SYSCALL_64_after_hwframe+0x61/0xcb
RIP: 0033:0x7f0cde4ea229
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:00007ffd81d1c978 EFLAGS: 00000246 ORIG_RAX: 0000000000000002
RAX: ffffffffffffffda RBX: 0030656c69662f30 RCX: 00007f0cde4ea229
RDX: 0000000000000089 RSI: 00000000000a0a00 RDI: 00000000200001c0
RBP: 2f30656c69662f2e R08: 0000000000208000 R09: 0000000000208000
R10: 0000000000000000 R11: 0000000000000246 R12: 00007ffd81d1c9c0
R13: 00007ffd81d1ca00 R14: 0000000000080000 R15: 0000000000000003
EXT4-fs error (device loop0): ext4_expand_extra_isize_ea:2730: inode #13: comm syz-executor543: corrupted in-inode xattr
Signed-off-by: Wojciech Gładysz <wojciech.gladysz@infogain.com>
Link: https://patch.msgid.link/20240801143827.19135-1-wojciech.gladysz@infogain.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/ext4/xattr.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index d65f1eb85a924..19982a682b9c1 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -420,7 +420,7 @@ static int ext4_xattr_inode_iget(struct inode *parent, unsigned long ea_ino,
ext4_set_inode_state(inode, EXT4_STATE_LUSTRE_EA_INODE);
ext4_xattr_inode_set_ref(inode, 1);
} else {
- inode_lock(inode);
+ inode_lock_nested(inode, I_MUTEX_XATTR);
inode->i_flags |= S_NOQUOTA;
inode_unlock(inode);
}
@@ -1033,7 +1033,7 @@ static int ext4_xattr_inode_update_ref(handle_t *handle, struct inode *ea_inode,
s64 ref_count;
int ret;
- inode_lock(ea_inode);
+ inode_lock_nested(ea_inode, I_MUTEX_XATTR);
ret = ext4_reserve_inode_write(handle, ea_inode, &iloc);
if (ret)
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2024-10-04 18:31 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20241004183105.3675901-1-sashal@kernel.org>
2024-10-04 18:30 ` [PATCH AUTOSEL 5.4 05/21] ext4: fix i_data_sem unlock order in ext4_ind_migrate() Sasha Levin
2024-10-04 18:30 ` [PATCH AUTOSEL 5.4 06/21] ext4: ext4_search_dir should return a proper error Sasha Levin
2024-10-04 18:30 ` [PATCH AUTOSEL 5.4 07/21] ext4: nested locking for xattr inode Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).