Blob Blame History Raw
From 7307b73fa5a82661808b5541972176c344978789 Mon Sep 17 00:00:00 2001
From: Jan Kara <jack@suse.cz>
Date: Thu, 12 Oct 2023 23:14:22 +0200
Subject: [PATCH] ext2: Avoid reading renamed directory if parent does not
 change
Git-commit: 7307b73fa5a82661808b5541972176c344978789
Patch-mainline: v6.8-rc1
References: bsc#1221044 CVE-2023-52591

The VFS will not be locking moved directory if its parent does not
change. Change ext2 rename code to avoid reading renamed directory if
its parent does not change. Although it is currently harmless it is a
bad practice to read directory contents without inode->i_rwsem.

Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: Jan Kara <jack@suse.cz>

---
 fs/ext2/namei.c |   11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -328,6 +328,7 @@ static int ext2_rename (struct mnt_idmap
 	struct page * old_page;
 	void *old_page_addr;
 	struct ext2_dir_entry_2 * old_de;
+	bool old_is_dir = S_ISDIR(old_inode->i_mode);
 	int err;
 
 	if (flags & ~RENAME_NOREPLACE)
@@ -348,7 +349,7 @@ static int ext2_rename (struct mnt_idmap
 		goto out;
 	}
 
-	if (S_ISDIR(old_inode->i_mode)) {
+	if (old_is_dir && old_dir != new_dir) {
 		err = -EIO;
 		dir_de = ext2_dotdot(old_inode, &dir_page, &dir_page_addr);
 		if (!dir_de)
@@ -361,7 +362,7 @@ static int ext2_rename (struct mnt_idmap
 		struct ext2_dir_entry_2 *new_de;
 
 		err = -ENOTEMPTY;
-		if (dir_de && !ext2_empty_dir (new_inode))
+		if (old_is_dir && !ext2_empty_dir(new_inode))
 			goto out_dir;
 
 		new_de = ext2_find_entry(new_dir, &new_dentry->d_name,
@@ -376,14 +377,14 @@ static int ext2_rename (struct mnt_idmap
 		if (err)
 			goto out_dir;
 		new_inode->i_ctime = current_time(new_inode);
-		if (dir_de)
+		if (old_is_dir)
 			drop_nlink(new_inode);
 		inode_dec_link_count(new_inode);
 	} else {
 		err = ext2_add_link(new_dentry, old_inode);
 		if (err)
 			goto out_dir;
-		if (dir_de)
+		if (old_is_dir)
 			inode_inc_link_count(new_dir);
 	}
 
@@ -396,7 +397,7 @@ static int ext2_rename (struct mnt_idmap
 
 	ext2_delete_entry(old_de, old_page, old_page_addr);
 
-	if (dir_de) {
+	if (old_is_dir) {
 		if (old_dir != new_dir) {
 			err = ext2_set_link(old_inode, dir_de, dir_page,
 					    dir_page_addr, new_dir, false);