From: Sasha Levin Date: Mon, 13 Mar 2023 13:12:28 +0000 (-0400) Subject: Fixes for 5.10 X-Git-Tag: v4.14.310~80 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4e26b4cdf1aa7ef066c065f852473f94eb6fb49a;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.10 Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/ext4-fix-deadlock-during-directory-rename.patch b/queue-5.10/ext4-fix-deadlock-during-directory-rename.patch new file mode 100644 index 00000000000..9b4cdbc8f12 --- /dev/null +++ b/queue-5.10/ext4-fix-deadlock-during-directory-rename.patch @@ -0,0 +1,86 @@ +From 618deb30f999816462fddeec6126fd3789ea093a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 1 Mar 2023 15:10:04 +0100 +Subject: ext4: Fix deadlock during directory rename + +From: Jan Kara + +[ Upstream commit 3c92792da8506a295afb6d032b4476e46f979725 ] + +As lockdep properly warns, we should not be locking i_rwsem while having +transactions started as the proper lock ordering used by all directory +handling operations is i_rwsem -> transaction start. Fix the lock +ordering by moving the locking of the directory earlier in +ext4_rename(). + +Reported-by: syzbot+9d16c39efb5fade84574@syzkaller.appspotmail.com +Fixes: 0813299c586b ("ext4: Fix possible corruption when moving a directory") +Link: https://syzkaller.appspot.com/bug?extid=9d16c39efb5fade84574 +Signed-off-by: Jan Kara +Link: https://lore.kernel.org/r/20230301141004.15087-1-jack@suse.cz +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/namei.c | 26 +++++++++++++++++--------- + 1 file changed, 17 insertions(+), 9 deletions(-) + +diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c +index 17590bb769147..1f47aeca71422 100644 +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -3863,10 +3863,20 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, + return retval; + } + ++ /* ++ * We need to protect against old.inode directory getting converted ++ * from inline directory format into a normal one. ++ */ ++ if (S_ISDIR(old.inode->i_mode)) ++ inode_lock_nested(old.inode, I_MUTEX_NONDIR2); ++ + old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, + &old.inlined); +- if (IS_ERR(old.bh)) +- return PTR_ERR(old.bh); ++ if (IS_ERR(old.bh)) { ++ retval = PTR_ERR(old.bh); ++ goto unlock_moved_dir; ++ } ++ + /* + * Check for inode number is _not_ due to possible IO errors. + * We might rmdir the source, keep it as pwd of some process +@@ -3923,11 +3933,6 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, + if (new.dir != old.dir && EXT4_DIR_LINK_MAX(new.dir)) + goto end_rename; + } +- /* +- * We need to protect against old.inode directory getting +- * converted from inline directory format into a normal one. +- */ +- inode_lock_nested(old.inode, I_MUTEX_NONDIR2); + retval = ext4_rename_dir_prepare(handle, &old); + if (retval) { + inode_unlock(old.inode); +@@ -4057,12 +4062,15 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, + } else { + ext4_journal_stop(handle); + } +- if (old.dir_bh) +- inode_unlock(old.inode); + release_bh: + brelse(old.dir_bh); + brelse(old.bh); + brelse(new.bh); ++ ++unlock_moved_dir: ++ if (S_ISDIR(old.inode->i_mode)) ++ inode_unlock(old.inode); ++ + return retval; + } + +-- +2.39.2 + diff --git a/queue-5.10/series b/queue-5.10/series index 6f8b8d919f9..57f952e68ed 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -63,3 +63,4 @@ net-smc-fix-fallback-failed-while-sendmsg-with-fasto.patch sunrpc-fix-a-server-shutdown-leak.patch riscv-use-read_once_nocheck-in-imprecise-unwinding-s.patch risc-v-don-t-check-text_mutex-during-stop_machine.patch +ext4-fix-deadlock-during-directory-rename.patch