From aa5ffd87c32a442634ea01661f62e82fe2efc69b Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Mon, 13 Mar 2023 09:12:29 -0400 Subject: [PATCH] Fixes for 5.4 Signed-off-by: Sasha Levin --- ...fix-deadlock-during-directory-rename.patch | 86 +++++++++++++++++++ queue-5.4/series | 1 + 2 files changed, 87 insertions(+) create mode 100644 queue-5.4/ext4-fix-deadlock-during-directory-rename.patch diff --git a/queue-5.4/ext4-fix-deadlock-during-directory-rename.patch b/queue-5.4/ext4-fix-deadlock-during-directory-rename.patch new file mode 100644 index 00000000000..cb22b75c5d7 --- /dev/null +++ b/queue-5.4/ext4-fix-deadlock-during-directory-rename.patch @@ -0,0 +1,86 @@ +From 105726f68000d334f6017dcdc30ad1ec06cd66bc 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 f9d11f59df7d2..b708b437b3e36 100644 +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -3795,10 +3795,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 +@@ -3855,11 +3865,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); +@@ -3960,12 +3965,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.4/series b/queue-5.4/series index 53aa07766f8..406c4227f26 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -57,3 +57,4 @@ btf-fix-resolving-btf_kind_var-after-array-struct-un.patch scsi-megaraid_sas-update-max-supported-ld-ids-to-240.patch net-smc-fix-fallback-failed-while-sendmsg-with-fasto.patch riscv-use-read_once_nocheck-in-imprecise-unwinding-s.patch +ext4-fix-deadlock-during-directory-rename.patch -- 2.47.3