lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <tencent_4D663A3CE9374A970636084B0C75E3768D09@qq.com>
Date: Tue, 26 Nov 2024 07:42:09 +0800
From: Edward Adam Davis <eadavis@...com>
To: syzbot+028180f480a74961919c@...kaller.appspotmail.com
Cc: linux-fsdevel@...r.kernel.org,
	linux-kernel@...r.kernel.org,
	syzkaller-bugs@...glegroups.com
Subject: [PATCH] hfsplus: restore i_nlink and flags when rename_cat fails

After the rename syscall fails, the unlink syscall triggers a warning in
drop_nlink() because the i_nlink value is 0.

When unlink succeeds but rename_cat fails in rename, the i_nlink and flags
values of the inode of the new dentry should be restored.

Reported-and-tested-by: syzbot+028180f480a74961919c@...kaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=028180f480a74961919c
Signed-off-by: Edward Adam Davis <eadavis@...com>
---
 fs/hfsplus/dir.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index f5c4b3e31a1c..b489d22409e7 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -534,7 +534,7 @@ static int hfsplus_rename(struct mnt_idmap *idmap,
 			  struct inode *new_dir, struct dentry *new_dentry,
 			  unsigned int flags)
 {
-	int res;
+	int res, unlinked_new = 0;
 
 	if (flags & ~RENAME_NOREPLACE)
 		return -EINVAL;
@@ -543,8 +543,10 @@ static int hfsplus_rename(struct mnt_idmap *idmap,
 	if (d_really_is_positive(new_dentry)) {
 		if (d_is_dir(new_dentry))
 			res = hfsplus_rmdir(new_dir, new_dentry);
-		else
+		else {
 			res = hfsplus_unlink(new_dir, new_dentry);
+			unlinked_new = res == 0 && d_inode(new_dentry)->i_flags & S_DEAD;
+		}
 		if (res)
 			return res;
 	}
@@ -554,6 +556,12 @@ static int hfsplus_rename(struct mnt_idmap *idmap,
 				 new_dir, &new_dentry->d_name);
 	if (!res)
 		new_dentry->d_fsdata = old_dentry->d_fsdata;
+	else if (unlinked_new) {
+		struct inode *inode = d_inode(new_dentry);
+		set_nlink(inode, inode->i_nlink + 1);
+		inode->i_flags &= ~S_DEAD;
+	}
+
 	return res;
 }
 
-- 
2.43.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ