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 for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-id: <176454037897.634289.3566631742434963788@noble.neil.brown.name>
Date: Mon, 01 Dec 2025 09:06:18 +1100
From: NeilBrown <neilb@...mail.net>
To: "Alexander Viro" <viro@...iv.linux.org.uk>,
 "Christian Brauner" <brauner@...nel.org>, "Val Packett" <val@...kett.cool>
Cc: "Amir Goldstein" <amir73il@...il.com>, "Jan Kara" <jack@...e.cz>,
 linux-fsdevel@...r.kernel.org, "Jeff Layton" <jlayton@...nel.org>,
 "Chris Mason" <clm@...com>, "David Sterba" <dsterba@...e.com>,
 "David Howells" <dhowells@...hat.com>,
 "Greg Kroah-Hartman" <gregkh@...uxfoundation.org>,
 "Rafael J. Wysocki" <rafael@...nel.org>,
 "Danilo Krummrich" <dakr@...nel.org>, "Tyler Hicks" <code@...icks.com>,
 "Miklos Szeredi" <miklos@...redi.hu>,
 "Chuck Lever" <chuck.lever@...cle.com>,
 "Olga Kornievskaia" <okorniev@...hat.com>,
 "Dai Ngo" <Dai.Ngo@...cle.com>, "Namjae Jeon" <linkinjeon@...nel.org>,
 "Steve French" <smfrench@...il.com>,
 "Sergey Senozhatsky" <senozhatsky@...omium.org>,
 "Carlos Maiolino" <cem@...nel.org>,
 "John Johansen" <john.johansen@...onical.com>,
 "Paul Moore" <paul@...l-moore.com>, "James Morris" <jmorris@...ei.org>,
 "Serge E. Hallyn" <serge@...lyn.com>,
 "Stephen Smalley" <stephen.smalley.work@...il.com>,
 "Ondrej Mosnacek" <omosnace@...hat.com>,
 "Mateusz Guzik" <mjguzik@...il.com>,
 "Lorenzo Stoakes" <lorenzo.stoakes@...cle.com>,
 "Stefan Berger" <stefanb@...ux.ibm.com>,
 "Darrick J. Wong" <djwong@...nel.org>, linux-kernel@...r.kernel.org,
 netfs@...ts.linux.dev, ecryptfs@...r.kernel.org,
 linux-nfs@...r.kernel.org, linux-unionfs@...r.kernel.org,
 linux-cifs@...r.kernel.org, linux-xfs@...r.kernel.org,
 linux-security-module@...r.kernel.org, selinux@...r.kernel.org
Subject: [PATCH] fuse: fix conversion of fuse_reverse_inval_entry() to
 start_removing()


From: NeilBrown <neil@...wn.name>

The recent conversion of fuse_reverse_inval_entry() to use
start_removing() was wrong.
As Val Packett points out the original code did not call ->lookup
while the new code does.  This can lead to a deadlock.

Rather than using full_name_hash() and d_lookup() as the old code
did, we can use try_lookup_noperm() which combines these.  Then
the result can be given to start_removing_dentry() to get the required
locks for removal.  We then double check that the name hasn't
changed.

As 'dir' needs to be used several times now, we load the dput() until
the end, and initialise to NULL so dput() is always safe.

Reported-by: Val Packett <val@...kett.cool>
Closes: https://lore.kernel.org/all/6713ea38-b583-4c86-b74a-bea55652851d@packett.cool
Fixes: c9ba789dad15 ("VFS: introduce start_creating_noperm() and start_removing_noperm()")
Signed-off-by: NeilBrown <neil@...wn.name>
---
 fs/fuse/dir.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index a0d5b302bcc2..8384fa96cf53 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1390,8 +1390,8 @@ int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid,
 {
 	int err = -ENOTDIR;
 	struct inode *parent;
-	struct dentry *dir;
-	struct dentry *entry;
+	struct dentry *dir = NULL;
+	struct dentry *entry = NULL;
 
 	parent = fuse_ilookup(fc, parent_nodeid, NULL);
 	if (!parent)
@@ -1404,11 +1404,19 @@ int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid,
 	dir = d_find_alias(parent);
 	if (!dir)
 		goto put_parent;
-
-	entry = start_removing_noperm(dir, name);
-	dput(dir);
-	if (IS_ERR(entry))
-		goto put_parent;
+	while (!entry) {
+		struct dentry *child = try_lookup_noperm(name, dir);
+		if (!child || IS_ERR(child))
+			goto put_parent;
+		entry = start_removing_dentry(dir, child);
+		dput(child);
+		if (IS_ERR(entry))
+			goto put_parent;
+		if (!d_same_name(entry, dir, name)) {
+			end_removing(entry);
+			entry = NULL;
+		}
+	}
 
 	fuse_dir_changed(parent);
 	if (!(flags & FUSE_EXPIRE_ONLY))
@@ -1446,6 +1454,7 @@ int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid,
 
 	end_removing(entry);
  put_parent:
+	dput(dir);
 	iput(parent);
 	return err;
 }
-- 
2.50.0.107.gf914562f5916.dirty


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ