linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] smb/server: various clean-ups
@ 2025-06-08 23:35 NeilBrown
  2025-06-08 23:35 ` [PATCH 1/4] smb/server: use lookup_one_unlocked() NeilBrown
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: NeilBrown @ 2025-06-08 23:35 UTC (permalink / raw)
  To: Namjae Jeon, Steve French, Sergey Senozhatsky, Tom Talpey
  Cc: Alexander Viro, Christian Brauner, Jan Kara, linux-fsdevel,
	linux-cifs, linux-kernel

I am working towards making some changes to how locking is managed for
directory operations.  Prior to attempting to land these changes I am
reviewing code that requests directory operations and cleaning up things
that might cause me problems later.

These 4 patches are the result of my review of smb/server.  Note that
patch 3 fixes what appears to be a real deadlock that should be trivial
to hit if the client can actually set the flag which, as mentioned in
the patch, can trigger the deadlock.

Patch 1 is trivial but the others deserve careful review by someone who
knows the code.  I think they are correct, but I've been wrong before.

Thanks,
NeilBrown

 [PATCH 1/4] smb/server: use lookup_one_unlocked()
 [PATCH 2/4] smb/server: simplify ksmbd_vfs_kern_path_locked()
 [PATCH 3/4] smb/server: avoid deadlock when linking with
 [PATCH 4/4] smb/server: add ksmbd_vfs_kern_path()

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/4] smb/server: use lookup_one_unlocked()
  2025-06-08 23:35 [PATCH 0/4] smb/server: various clean-ups NeilBrown
@ 2025-06-08 23:35 ` NeilBrown
  2025-06-08 23:35 ` [PATCH 2/4] smb/server: simplify ksmbd_vfs_kern_path_locked() NeilBrown
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: NeilBrown @ 2025-06-08 23:35 UTC (permalink / raw)
  To: Namjae Jeon, Steve French, Sergey Senozhatsky, Tom Talpey
  Cc: Alexander Viro, Christian Brauner, Jan Kara, linux-fsdevel,
	linux-cifs, linux-kernel

In process_query_dir_entries(), instead of locking the directory,
performing a lookup, then unlocking, we can simply call
lookup_one_unlocked().  That takes locks the directory only when needed.

This removes the only users of lock_dir() and unlock_dir() so they can
be removed.

Signed-off-by: NeilBrown <neil@brown.name>
---
 fs/smb/server/smb2pdu.c | 24 ++++--------------------
 1 file changed, 4 insertions(+), 20 deletions(-)

diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index 1a308171b599..0013052f5d98 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -4107,20 +4107,6 @@ struct smb2_query_dir_private {
 	int			info_level;
 };
 
-static void lock_dir(struct ksmbd_file *dir_fp)
-{
-	struct dentry *dir = dir_fp->filp->f_path.dentry;
-
-	inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
-}
-
-static void unlock_dir(struct ksmbd_file *dir_fp)
-{
-	struct dentry *dir = dir_fp->filp->f_path.dentry;
-
-	inode_unlock(d_inode(dir));
-}
-
 static int process_query_dir_entries(struct smb2_query_dir_private *priv)
 {
 	struct mnt_idmap	*idmap = file_mnt_idmap(priv->dir_fp->filp);
@@ -4135,12 +4121,10 @@ static int process_query_dir_entries(struct smb2_query_dir_private *priv)
 		if (dentry_name(priv->d_info, priv->info_level))
 			return -EINVAL;
 
-		lock_dir(priv->dir_fp);
-		dent = lookup_one(idmap,
-				  &QSTR_LEN(priv->d_info->name,
-					    priv->d_info->name_len),
-				  priv->dir_fp->filp->f_path.dentry);
-		unlock_dir(priv->dir_fp);
+		dent = lookup_one_unlocked(idmap,
+					   &QSTR_LEN(priv->d_info->name,
+						     priv->d_info->name_len),
+					   priv->dir_fp->filp->f_path.dentry);
 
 		if (IS_ERR(dent)) {
 			ksmbd_debug(SMB, "Cannot lookup `%s' [%ld]\n",
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/4] smb/server: simplify ksmbd_vfs_kern_path_locked()
  2025-06-08 23:35 [PATCH 0/4] smb/server: various clean-ups NeilBrown
  2025-06-08 23:35 ` [PATCH 1/4] smb/server: use lookup_one_unlocked() NeilBrown
@ 2025-06-08 23:35 ` NeilBrown
  2025-06-08 23:35 ` [PATCH 3/4] smb/server: avoid deadlock when linking with ReplaceIfExists NeilBrown
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: NeilBrown @ 2025-06-08 23:35 UTC (permalink / raw)
  To: Namjae Jeon, Steve French, Sergey Senozhatsky, Tom Talpey
  Cc: Alexander Viro, Christian Brauner, Jan Kara, linux-fsdevel,
	linux-cifs, linux-kernel

ksmbd_vfs_kern_path_locked() first tries to look up the path with the
given case.  When this fails, if caseless is set, it loops over the
components in the path, opening the relevant directory and searching
for a name which matches.  This name is copied over the original and the
the process repeats.  Each time a lookup with the newly updated path is
repeated from the top (vfs_path_lookup()).

When the last component has been case-corrected the simplest next step
is to repeat the original lookup with ksmbd_vfs_path_lookup_locked().
If this works it gives exactly what we want, if it fails it gives the
correct failure.

This observation allows the code to be simplified, in particular
removing the ksmbd_vfs_lock_parent() call.

This patch also removes the duplication of "name" and "filepath" (two
names for the one thing) and calls path_put(parent_path) sooner so
parent_path can be passed directly to vfs_path_lookup avoiding the need
to store it temporarily in "path" and then copying into parent_path.

This patch removes one user of ksmbd_vfs_lock_parent() which will
simplify a future patch.

Signed-off-by: NeilBrown <neil@brown.name>
---
 fs/smb/server/vfs.c | 101 ++++++++++++++++++--------------------------
 1 file changed, 40 insertions(+), 61 deletions(-)

diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c
index ba45e809555a..654c2f14a9e6 100644
--- a/fs/smb/server/vfs.c
+++ b/fs/smb/server/vfs.c
@@ -1208,83 +1208,62 @@ static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name,
  *
  * Return:	0 on success, otherwise error
  */
-int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
+int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *filepath,
 			       unsigned int flags, struct path *parent_path,
 			       struct path *path, bool caseless)
 {
 	struct ksmbd_share_config *share_conf = work->tcon->share_conf;
+	size_t path_len, remain_len;
 	int err;
 
-	err = ksmbd_vfs_path_lookup_locked(share_conf, name, flags, parent_path,
+retry:
+	err = ksmbd_vfs_path_lookup_locked(share_conf, filepath, flags, parent_path,
 					   path);
-	if (!err)
-		return 0;
-
-	if (caseless) {
-		char *filepath;
-		size_t path_len, remain_len;
-
-		filepath = name;
-		path_len = strlen(filepath);
-		remain_len = path_len;
-
-		*parent_path = share_conf->vfs_path;
-		path_get(parent_path);
-
-		while (d_can_lookup(parent_path->dentry)) {
-			char *filename = filepath + path_len - remain_len;
-			char *next = strchrnul(filename, '/');
-			size_t filename_len = next - filename;
-			bool is_last = !next[0];
-
-			if (filename_len == 0)
-				break;
+	if (!err || !caseless)
+		return err;
 
-			err = ksmbd_vfs_lookup_in_dir(parent_path, filename,
-						      filename_len,
-						      work->conn->um);
-			if (err)
-				goto out2;
+	path_len = strlen(filepath);
+	remain_len = path_len;
 
-			next[0] = '\0';
+	*parent_path = share_conf->vfs_path;
+	path_get(parent_path);
 
-			err = vfs_path_lookup(share_conf->vfs_path.dentry,
-					      share_conf->vfs_path.mnt,
-					      filepath,
-					      flags,
-					      path);
-			if (!is_last)
-				next[0] = '/';
-			if (err)
-				goto out2;
-			else if (is_last)
-				goto out1;
-			path_put(parent_path);
-			*parent_path = *path;
+	while (d_can_lookup(parent_path->dentry)) {
+		char *filename = filepath + path_len - remain_len;
+		char *next = strchrnul(filename, '/');
+		size_t filename_len = next - filename;
+		bool is_last = !next[0];
 
-			remain_len -= filename_len + 1;
-		}
+		if (filename_len == 0)
+			break;
 
-		err = -EINVAL;
-out2:
+		err = ksmbd_vfs_lookup_in_dir(parent_path, filename,
+					      filename_len,
+					      work->conn->um);
 		path_put(parent_path);
-	}
-
-out1:
-	if (!err) {
-		err = mnt_want_write(parent_path->mnt);
-		if (err) {
-			path_put(path);
-			path_put(parent_path);
-			return err;
+		if (err)
+			goto out;
+		if (is_last) {
+			caseless = false;
+			goto retry;
 		}
+		next[0] = '\0';
+
+		err = vfs_path_lookup(share_conf->vfs_path.dentry,
+				      share_conf->vfs_path.mnt,
+				      filepath,
+				      flags,
+				      parent_path);
+		next[0] = '/';
+		if (err)
+			goto out;
 
-		err = ksmbd_vfs_lock_parent(parent_path->dentry, path->dentry);
-		if (err) {
-			path_put(path);
-			path_put(parent_path);
-		}
+		remain_len -= filename_len + 1;
 	}
+
+	err = -EINVAL;
+	path_put(parent_path);
+out:
 	return err;
 }
 
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/4] smb/server: avoid deadlock when linking with ReplaceIfExists
  2025-06-08 23:35 [PATCH 0/4] smb/server: various clean-ups NeilBrown
  2025-06-08 23:35 ` [PATCH 1/4] smb/server: use lookup_one_unlocked() NeilBrown
  2025-06-08 23:35 ` [PATCH 2/4] smb/server: simplify ksmbd_vfs_kern_path_locked() NeilBrown
@ 2025-06-08 23:35 ` NeilBrown
  2025-06-08 23:35 ` [PATCH 4/4] smb/server: add ksmbd_vfs_kern_path() NeilBrown
  2025-07-16  5:22 ` [PATCH 0/4] smb/server: various clean-ups NeilBrown
  4 siblings, 0 replies; 10+ messages in thread
From: NeilBrown @ 2025-06-08 23:35 UTC (permalink / raw)
  To: Namjae Jeon, Steve French, Sergey Senozhatsky, Tom Talpey
  Cc: Alexander Viro, Christian Brauner, Jan Kara, linux-fsdevel,
	linux-cifs, linux-kernel

If smb2_create_link() is called with ReplaceIfExists set and the name
does exist then a deadlock will happen.

ksmbd_vfs_kern_path_locked() will return with success and the parent
directory will be locked.  ksmbd_vfs_remove_file() will then remove the
file.  ksmbd_vfs_link() will then be called while the parent is still
locked.  It will try to lock the same parent and will deadlock.

This patch moves the ksmbd_vfs_kern_path_unlock() call to *before*
ksmbd_vfs_link() and then simplifies the code, removing the file_present
flag variable.

Signed-off-by: NeilBrown <neil@brown.name>
---
 fs/smb/server/smb2pdu.c | 16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index 0013052f5d98..2e98717a0268 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -6009,7 +6009,6 @@ static int smb2_create_link(struct ksmbd_work *work,
 {
 	char *link_name = NULL, *target_name = NULL, *pathname = NULL;
 	struct path path, parent_path;
-	bool file_present = false;
 	int rc;
 
 	if (buf_len < (u64)sizeof(struct smb2_file_link_info) +
@@ -6042,11 +6041,8 @@ static int smb2_create_link(struct ksmbd_work *work,
 	if (rc) {
 		if (rc != -ENOENT)
 			goto out;
-	} else
-		file_present = true;
-
-	if (file_info->ReplaceIfExists) {
-		if (file_present) {
+	} else {
+		if (file_info->ReplaceIfExists) {
 			rc = ksmbd_vfs_remove_file(work, &path);
 			if (rc) {
 				rc = -EINVAL;
@@ -6054,21 +6050,17 @@ static int smb2_create_link(struct ksmbd_work *work,
 					    link_name);
 				goto out;
 			}
-		}
-	} else {
-		if (file_present) {
+		} else {
 			rc = -EEXIST;
 			ksmbd_debug(SMB, "link already exists\n");
 			goto out;
 		}
+		ksmbd_vfs_kern_path_unlock(&parent_path, &path);
 	}
-
 	rc = ksmbd_vfs_link(work, target_name, link_name);
 	if (rc)
 		rc = -EINVAL;
 out:
-	if (file_present)
-		ksmbd_vfs_kern_path_unlock(&parent_path, &path);
 
 	if (!IS_ERR(link_name))
 		kfree(link_name);
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/4] smb/server: add ksmbd_vfs_kern_path()
  2025-06-08 23:35 [PATCH 0/4] smb/server: various clean-ups NeilBrown
                   ` (2 preceding siblings ...)
  2025-06-08 23:35 ` [PATCH 3/4] smb/server: avoid deadlock when linking with ReplaceIfExists NeilBrown
@ 2025-06-08 23:35 ` NeilBrown
  2025-07-23 15:36   ` Stefan Metzmacher
  2025-07-16  5:22 ` [PATCH 0/4] smb/server: various clean-ups NeilBrown
  4 siblings, 1 reply; 10+ messages in thread
From: NeilBrown @ 2025-06-08 23:35 UTC (permalink / raw)
  To: Namjae Jeon, Steve French, Sergey Senozhatsky, Tom Talpey
  Cc: Alexander Viro, Christian Brauner, Jan Kara, linux-fsdevel,
	linux-cifs, linux-kernel

The function ksmbd_vfs_kern_path_locked() seems to serve two functions
and as a result has an odd interface.

On success it returns with the parent directory locked and with write
access on that filesystem requested, but it may have crossed over a
mount point to return the "path", which makes the lock and the write
access irrelevant.

This patches separates the functionality into two functions:
- ksmbd_vfs_kern_path() does not lock the parent, does not request
  write access, but does cross mount points
- ksmbd_vfs_kern_path_locked() does not cross mount points but
  does lock the parent and request write access.

The parent_path parameter is no longer needed.  For the _locked case
the final path is sufficient to drop write access and to unlock the
parent (using path->dentry->d_parent which is safe while the lock is
held).

There were 3 caller of ksmbd_vfs_kern_path_locked().

- smb2_create_link() needs to remove the target if it existed and
  needs the lock and the write-access, so it continues to use
  ksmbd_vfs_kern_path_locked().  It would not make sense to
  cross mount points in this case.
- smb2_open() is the only user that needs to cross mount points
  and it has no need for the lock or write access, so it now uses
  ksmbd_vfs_kern_path()
- smb2_creat() does not need to cross mountpoints as it is accessing
  a file that it has just created on *this* filesystem.  But also it
  does not need the lock or write access because by the time
  ksmbd_vfs_kern_path_locked() was called it has already created the
  file.  So it could use either interface.  It is simplest to use
  ksmbd_vfs_kern_path().

ksmbd_vfs_kern_path_unlock() is still needed after
ksmbd_vfs_kern_path_locked() but it doesn't require the parent_path any
more.  After a successful call to ksmbd_vfs_kern_path(), only path_put()
is needed to release the path.

Signed-off-by: NeilBrown <neil@brown.name>
---
 fs/smb/server/smb2pdu.c |  22 +++---
 fs/smb/server/vfs.c     | 156 ++++++++++++++++++++++++++--------------
 fs/smb/server/vfs.h     |   7 +-
 3 files changed, 118 insertions(+), 67 deletions(-)

diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index 2e98717a0268..6d2faf19ab96 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -2580,7 +2580,7 @@ static void smb2_update_xattrs(struct ksmbd_tree_connect *tcon,
 	}
 }
 
-static int smb2_creat(struct ksmbd_work *work, struct path *parent_path,
+static int smb2_creat(struct ksmbd_work *work,
 		      struct path *path, char *name, int open_flags,
 		      umode_t posix_mode, bool is_dir)
 {
@@ -2609,7 +2609,7 @@ static int smb2_creat(struct ksmbd_work *work, struct path *parent_path,
 			return rc;
 	}
 
-	rc = ksmbd_vfs_kern_path_locked(work, name, 0, parent_path, path, 0);
+	rc = ksmbd_vfs_kern_path(work, name, 0, path, 0);
 	if (rc) {
 		pr_err("cannot get linux path (%s), err = %d\n",
 		       name, rc);
@@ -2859,7 +2859,7 @@ int smb2_open(struct ksmbd_work *work)
 	struct ksmbd_tree_connect *tcon = work->tcon;
 	struct smb2_create_req *req;
 	struct smb2_create_rsp *rsp;
-	struct path path, parent_path;
+	struct path path;
 	struct ksmbd_share_config *share = tcon->share_conf;
 	struct ksmbd_file *fp = NULL;
 	struct file *filp = NULL;
@@ -3115,8 +3115,8 @@ int smb2_open(struct ksmbd_work *work)
 		goto err_out2;
 	}
 
-	rc = ksmbd_vfs_kern_path_locked(work, name, LOOKUP_NO_SYMLINKS,
-					&parent_path, &path, 1);
+	rc = ksmbd_vfs_kern_path(work, name, LOOKUP_NO_SYMLINKS,
+				 &path, 1);
 	if (!rc) {
 		file_present = true;
 
@@ -3237,7 +3237,7 @@ int smb2_open(struct ksmbd_work *work)
 
 	/*create file if not present */
 	if (!file_present) {
-		rc = smb2_creat(work, &parent_path, &path, name, open_flags,
+		rc = smb2_creat(work, &path, name, open_flags,
 				posix_mode,
 				req->CreateOptions & FILE_DIRECTORY_FILE_LE);
 		if (rc) {
@@ -3442,7 +3442,7 @@ int smb2_open(struct ksmbd_work *work)
 	}
 
 	if (file_present || created)
-		ksmbd_vfs_kern_path_unlock(&parent_path, &path);
+		path_put(&path);
 
 	if (!S_ISDIR(file_inode(filp)->i_mode) && open_flags & O_TRUNC &&
 	    !fp->attrib_only && !stream_name) {
@@ -3723,7 +3723,7 @@ int smb2_open(struct ksmbd_work *work)
 
 err_out:
 	if (rc && (file_present || created))
-		ksmbd_vfs_kern_path_unlock(&parent_path, &path);
+		path_put(&path);
 
 err_out1:
 	ksmbd_revert_fsids(work);
@@ -6008,7 +6008,7 @@ static int smb2_create_link(struct ksmbd_work *work,
 			    struct nls_table *local_nls)
 {
 	char *link_name = NULL, *target_name = NULL, *pathname = NULL;
-	struct path path, parent_path;
+	struct path path;
 	int rc;
 
 	if (buf_len < (u64)sizeof(struct smb2_file_link_info) +
@@ -6037,7 +6037,7 @@ static int smb2_create_link(struct ksmbd_work *work,
 
 	ksmbd_debug(SMB, "target name is %s\n", target_name);
 	rc = ksmbd_vfs_kern_path_locked(work, link_name, LOOKUP_NO_SYMLINKS,
-					&parent_path, &path, 0);
+					&path, 0);
 	if (rc) {
 		if (rc != -ENOENT)
 			goto out;
@@ -6055,7 +6055,7 @@ static int smb2_create_link(struct ksmbd_work *work,
 			ksmbd_debug(SMB, "link already exists\n");
 			goto out;
 		}
-		ksmbd_vfs_kern_path_unlock(&parent_path, &path);
+		ksmbd_vfs_kern_path_unlock(&path);
 	}
 	rc = ksmbd_vfs_link(work, target_name, link_name);
 	if (rc)
diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c
index 654c2f14a9e6..a5599d2e9ab0 100644
--- a/fs/smb/server/vfs.c
+++ b/fs/smb/server/vfs.c
@@ -66,10 +66,9 @@ int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child)
 	return 0;
 }
 
-static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
-					char *pathname, unsigned int flags,
-					struct path *parent_path,
-					struct path *path)
+static int ksmbd_vfs_path_lookup(struct ksmbd_share_config *share_conf,
+				 char *pathname, unsigned int flags,
+				 struct path *path, bool do_lock)
 {
 	struct qstr last;
 	struct filename *filename;
@@ -89,51 +88,58 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
 		return PTR_ERR(filename);
 
 	err = vfs_path_parent_lookup(filename, flags,
-				     parent_path, &last, &type,
+				     path, &last, &type,
 				     root_share_path);
-	if (err) {
-		putname(filename);
+	putname(filename);
+	if (err)
 		return err;
-	}
 
 	if (unlikely(type != LAST_NORM)) {
-		path_put(parent_path);
-		putname(filename);
-		return -ENOENT;
-	}
-
-	err = mnt_want_write(parent_path->mnt);
-	if (err) {
-		path_put(parent_path);
-		putname(filename);
+		path_put(path);
 		return -ENOENT;
 	}
 
-	inode_lock_nested(parent_path->dentry->d_inode, I_MUTEX_PARENT);
-	d = lookup_one_qstr_excl(&last, parent_path->dentry, 0);
-	if (IS_ERR(d))
-		goto err_out;
+	if (do_lock) {
+		err = mnt_want_write(path->mnt);
+		if (err) {
+			path_put(path);
+			return -ENOENT;
+		}
 
-	path->dentry = d;
-	path->mnt = mntget(parent_path->mnt);
+		inode_lock_nested(path->dentry->d_inode, I_MUTEX_PARENT);
+		d = lookup_one_qstr_excl(&last, path->dentry, 0);
 
-	if (test_share_config_flag(share_conf, KSMBD_SHARE_FLAG_CROSSMNT)) {
-		err = follow_down(path, 0);
-		if (err < 0) {
+		if (!IS_ERR(d)) {
+			dput(path->dentry);
+			path->dentry = d;
+			return 0;
+		}
+		inode_unlock(path->dentry->d_inode);
+		mnt_drop_write(path->mnt);
+		path_put(path);
+		return -ENOENT;
+	} else {
+		d = lookup_noperm_unlocked(&last, path->dentry);
+		if (!IS_ERR(d) && d_is_negative(d)) {
+			dput(d);
+			d = ERR_PTR(-ENOENT);
+		}
+		if (IS_ERR(d)) {
 			path_put(path);
-			goto err_out;
+			return -ENOENT;
 		}
+		dput(path->dentry);
+		path->dentry = d;
+
+		if (test_share_config_flag(share_conf, KSMBD_SHARE_FLAG_CROSSMNT)) {
+			err = follow_down(path, 0);
+			if (err < 0) {
+				path_put(path);
+				return -ENOENT;
+			}
+		}
+		return 0;
 	}
-
-	putname(filename);
-	return 0;
-
-err_out:
-	inode_unlock(d_inode(parent_path->dentry));
-	mnt_drop_write(parent_path->mnt);
-	path_put(parent_path);
-	putname(filename);
-	return -ENOENT;
 }
 
 void ksmbd_vfs_query_maximal_access(struct mnt_idmap *idmap,
@@ -1202,33 +1208,33 @@ static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name,
  * @work:	work
  * @name:		file path that is relative to share
  * @flags:		lookup flags
- * @parent_path:	if lookup succeed, return parent_path info
  * @path:		if lookup succeed, return path info
  * @caseless:	caseless filename lookup
  *
  * Return:	0 on success, otherwise error
  */
-int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *filepath,
-			       unsigned int flags, struct path *parent_path,
-			       struct path *path, bool caseless)
+static
+int __ksmbd_vfs_kern_path(struct ksmbd_work *work, char *filepath,
+			  unsigned int flags,
+			  struct path *path, bool caseless, bool do_lock)
 {
 	struct ksmbd_share_config *share_conf = work->tcon->share_conf;
+	struct path parent_path;
 	size_t path_len, remain_len;
 	int err;
 
 retry:
-	err = ksmbd_vfs_path_lookup_locked(share_conf, filepath, flags, parent_path,
-					   path);
+	err = ksmbd_vfs_path_lookup(share_conf, filepath, flags, path, do_lock);
 	if (!err || !caseless)
 		return err;
 
 	path_len = strlen(filepath);
 	remain_len = path_len;
 
-	*parent_path = share_conf->vfs_path;
-	path_get(parent_path);
+	parent_path = share_conf->vfs_path;
+	path_get(&parent_path);
 
-	while (d_can_lookup(parent_path->dentry)) {
+	while (d_can_lookup(parent_path.dentry)) {
 		char *filename = filepath + path_len - remain_len;
 		char *next = strchrnul(filename, '/');
 		size_t filename_len = next - filename;
@@ -1237,10 +1243,10 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *filepath,
 		if (filename_len == 0)
 			break;
 
-		err = ksmbd_vfs_lookup_in_dir(parent_path, filename,
+		err = ksmbd_vfs_lookup_in_dir(&parent_path, filename,
 					      filename_len,
 					      work->conn->um);
-		path_put(parent_path);
+		path_put(&parent_path);
 		if (err)
 			goto out;
 		if (is_last) {
@@ -1253,7 +1259,7 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *filepath,
 				      share_conf->vfs_path.mnt,
 				      filepath,
 				      flags,
-				      parent_path);
+				      &parent_path);
 		next[0] = '/';
 		if (err)
 			goto out;
@@ -1262,17 +1268,59 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *filepath,
 	}
 
 	err = -EINVAL;
-	path_put(parent_path);
+	path_put(&parent_path);
 out:
 	return err;
 }
 
-void ksmbd_vfs_kern_path_unlock(struct path *parent_path, struct path *path)
+/**
+ * ksmbd_vfs_kern_path() - lookup a file and get path info
+ * @work:	work
+ * @name:		file path that is relative to share
+ * @flags:		lookup flags
+ * @path:		if lookup succeed, return path info
+ * @caseless:	caseless filename lookup
+ *
+ * Perform the lookup, possibly crossing over any mount point.
+ * On return no locks will be held and write-access to filesystem
+ * won't have been checked.
+ * Return:	0 if file was found, otherwise error
+ */
+int ksmbd_vfs_kern_path(struct ksmbd_work *work, char *filepath,
+			unsigned int flags,
+			struct path *path, bool caseless)
+{
+	return __ksmbd_vfs_kern_path(work, filepath, flags, path,
+				     caseless, false);
+}
+
+/**
+ * ksmbd_vfs_kern_path_locked() - lookup a file and get path info
+ * @work:	work
+ * @name:		file path that is relative to share
+ * @flags:		lookup flags
+ * @path:		if lookup succeed, return path info
+ * @caseless:	caseless filename lookup
+ *
+ * Perform the lookup, but don't cross over any mount point.
+ * On return the parent of path->dentry will be locked and write-access to
+ * filesystem will have been gained.
+ * Return:	0 on if file was found, otherwise error
+ */
+int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *filepath,
+			       unsigned int flags,
+			       struct path *path, bool caseless)
+{
+	return __ksmbd_vfs_kern_path(work, filepath, flags, path,
+				     caseless, true);
+}
+
+void ksmbd_vfs_kern_path_unlock(struct path *path)
 {
-	inode_unlock(d_inode(parent_path->dentry));
-	mnt_drop_write(parent_path->mnt);
+	/* While lock is still held, ->d_parent is safe */
+	inode_unlock(d_inode(path->dentry->d_parent));
+	mnt_drop_write(path->mnt);
 	path_put(path);
-	path_put(parent_path);
 }
 
 struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work,
diff --git a/fs/smb/server/vfs.h b/fs/smb/server/vfs.h
index 2893f59803a6..d47472f3e30b 100644
--- a/fs/smb/server/vfs.h
+++ b/fs/smb/server/vfs.h
@@ -117,10 +117,13 @@ int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name,
 int ksmbd_vfs_remove_xattr(struct mnt_idmap *idmap,
 			   const struct path *path, char *attr_name,
 			   bool get_write);
+int ksmbd_vfs_kern_path(struct ksmbd_work *work, char *name,
+			unsigned int flags,
+			struct path *path, bool caseless);
 int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
-			       unsigned int flags, struct path *parent_path,
+			       unsigned int flags,
 			       struct path *path, bool caseless);
-void ksmbd_vfs_kern_path_unlock(struct path *parent_path, struct path *path);
+void ksmbd_vfs_kern_path_unlock(struct path *path);
 struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work,
 					  const char *name,
 					  unsigned int flags,
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/4] smb/server: various clean-ups
  2025-06-08 23:35 [PATCH 0/4] smb/server: various clean-ups NeilBrown
                   ` (3 preceding siblings ...)
  2025-06-08 23:35 ` [PATCH 4/4] smb/server: add ksmbd_vfs_kern_path() NeilBrown
@ 2025-07-16  5:22 ` NeilBrown
  2025-07-16  6:59   ` Namjae Jeon
  4 siblings, 1 reply; 10+ messages in thread
From: NeilBrown @ 2025-07-16  5:22 UTC (permalink / raw)
  To: Namjae Jeon, Steve French, Sergey Senozhatsky, Tom Talpey
  Cc: Alexander Viro, Christian Brauner, Jan Kara, linux-fsdevel,
	linux-cifs, linux-kernel


Hi,
 did anyone have a chance to look at these - no replies and they don't
 appear in linux-next ??

Thanks,
NeilBrown
 

On Mon, 09 Jun 2025, NeilBrown wrote:
> I am working towards making some changes to how locking is managed for
> directory operations.  Prior to attempting to land these changes I am
> reviewing code that requests directory operations and cleaning up things
> that might cause me problems later.
> 
> These 4 patches are the result of my review of smb/server.  Note that
> patch 3 fixes what appears to be a real deadlock that should be trivial
> to hit if the client can actually set the flag which, as mentioned in
> the patch, can trigger the deadlock.
> 
> Patch 1 is trivial but the others deserve careful review by someone who
> knows the code.  I think they are correct, but I've been wrong before.
> 
> Thanks,
> NeilBrown
> 
>  [PATCH 1/4] smb/server: use lookup_one_unlocked()
>  [PATCH 2/4] smb/server: simplify ksmbd_vfs_kern_path_locked()
>  [PATCH 3/4] smb/server: avoid deadlock when linking with
>  [PATCH 4/4] smb/server: add ksmbd_vfs_kern_path()
> 
> 


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/4] smb/server: various clean-ups
  2025-07-16  5:22 ` [PATCH 0/4] smb/server: various clean-ups NeilBrown
@ 2025-07-16  6:59   ` Namjae Jeon
  0 siblings, 0 replies; 10+ messages in thread
From: Namjae Jeon @ 2025-07-16  6:59 UTC (permalink / raw)
  To: NeilBrown
  Cc: Steve French, Sergey Senozhatsky, Tom Talpey, Alexander Viro,
	Christian Brauner, Jan Kara, linux-fsdevel, linux-cifs,
	linux-kernel

On Wed, Jul 16, 2025 at 2:22 PM NeilBrown <neil@brown.name> wrote:
>
>
> Hi,
Hi Neil,
>  did anyone have a chance to look at these - no replies and they don't
>  appear in linux-next ??
Sorry, these patches are not in my mailbox for some reason I don't know...
I guess I missed these ones. I will check and apply the patches now.

Thanks.
>
> Thanks,
> NeilBrown
>
>
> On Mon, 09 Jun 2025, NeilBrown wrote:
> > I am working towards making some changes to how locking is managed for
> > directory operations.  Prior to attempting to land these changes I am
> > reviewing code that requests directory operations and cleaning up things
> > that might cause me problems later.
> >
> > These 4 patches are the result of my review of smb/server.  Note that
> > patch 3 fixes what appears to be a real deadlock that should be trivial
> > to hit if the client can actually set the flag which, as mentioned in
> > the patch, can trigger the deadlock.
> >
> > Patch 1 is trivial but the others deserve careful review by someone who
> > knows the code.  I think they are correct, but I've been wrong before.
> >
> > Thanks,
> > NeilBrown
> >
> >  [PATCH 1/4] smb/server: use lookup_one_unlocked()
> >  [PATCH 2/4] smb/server: simplify ksmbd_vfs_kern_path_locked()
> >  [PATCH 3/4] smb/server: avoid deadlock when linking with
> >  [PATCH 4/4] smb/server: add ksmbd_vfs_kern_path()
> >
> >
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/4] smb/server: add ksmbd_vfs_kern_path()
  2025-06-08 23:35 ` [PATCH 4/4] smb/server: add ksmbd_vfs_kern_path() NeilBrown
@ 2025-07-23 15:36   ` Stefan Metzmacher
  2025-07-23 23:03     ` NeilBrown
  0 siblings, 1 reply; 10+ messages in thread
From: Stefan Metzmacher @ 2025-07-23 15:36 UTC (permalink / raw)
  To: NeilBrown, Namjae Jeon, Steve French, Sergey Senozhatsky,
	Tom Talpey
  Cc: Alexander Viro, Christian Brauner, Jan Kara, linux-fsdevel,
	linux-cifs, linux-kernel

Hi Neil,

for me this reliable generates the following problem, just doing a simple:
mount -t cifs -ousername=root,password=test,noperm,vers=3.1.1,mfsymlinks,actimeo=0 //172.31.9.167/test /mnt/test/

[ 2213.234061] [   T1972] ==================================================================
[ 2213.234607] [   T1972] BUG: KASAN: slab-use-after-free in lookup_noperm_common+0x237/0x2b0
[ 2213.235122] [   T1972] Read of size 1 at addr ffff88801c95b326 by task kworker/2:0/1972
[ 2213.235635] [   T1972]
[ 2213.235806] [   T1972] CPU: 2 UID: 0 PID: 1972 Comm: kworker/2:0 Kdump: loaded Tainted: G        W  OE       6.16.0-rc7-metze-kasan.01+ #1 PREEMPT(voluntary)
[ 2213.235820] [   T1972] Tainted: [W]=WARN, [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
[ 2213.235824] [   T1972] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[ 2213.235829] [   T1972] Workqueue: ksmbd-io handle_ksmbd_work [ksmbd]
[ 2213.235871] [   T1972] Call Trace:
[ 2213.235875] [   T1972]  <TASK>
[ 2213.235880] [   T1972]  dump_stack_lvl+0x76/0xa0
[ 2213.235893] [   T1972]  print_report+0xd1/0x600
[ 2213.235909] [   T1972]  ? __pfx__raw_spin_lock_irqsave+0x10/0x10
[ 2213.235920] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.235929] [   T1972]  ? kasan_complete_mode_report_info+0x72/0x210
[ 2213.235937] [   T1972]  kasan_report+0xe7/0x130
[ 2213.235944] [   T1972]  ? lookup_noperm_common+0x237/0x2b0
[ 2213.235952] [   T1972]  ? lookup_noperm_common+0x237/0x2b0
[ 2213.235963] [   T1972]  __asan_report_load1_noabort+0x14/0x30
[ 2213.235976] [   T1972]  lookup_noperm_common+0x237/0x2b0
[ 2213.235984] [   T1972]  lookup_noperm_unlocked+0x1d/0xa0
[ 2213.235991] [   T1972]  ? putname+0xfa/0x150
[ 2213.235998] [   T1972]  __ksmbd_vfs_kern_path+0x376/0xa80 [ksmbd]
[ 2213.236024] [   T1972]  ? local_clock+0x15/0x30
[ 2213.236039] [   T1972]  ? kasan_save_track+0x27/0x70
[ 2213.236047] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.236054] [   T1972]  ? __entry_text_end+0x10257a/0x10257d
[ 2213.236066] [   T1972]  ? __pfx___ksmbd_vfs_kern_path+0x10/0x10 [ksmbd]
[ 2213.236097] [   T1972]  ? groups_alloc+0x41/0xe0
[ 2213.236106] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.236114] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.236122] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.236128] [   T1972]  ? __kasan_check_write+0x14/0x30
[ 2213.236134] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.236140] [   T1972]  ? __ksmbd_override_fsids+0x340/0x630 [ksmbd]
[ 2213.236188] [   T1972]  ? smb2_open+0x40b/0x9db0 [ksmbd]
[ 2213.236223] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.236233] [   T1972]  ksmbd_vfs_kern_path+0x15/0x30 [ksmbd]
[ 2213.236260] [   T1972]  smb2_open+0x2de6/0x9db0 [ksmbd]
[ 2213.236292] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.236299] [   T1972]  ? stack_depot_save_flags+0x28/0x840
[ 2213.236315] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.236321] [   T1972]  ? enqueue_hrtimer+0x10b/0x230
[ 2213.236338] [   T1972]  ? ksm_scan_thread+0x480/0x59b0
[ 2213.236345] [   T1972]  ? ksm_scan_thread+0x480/0x59b0
[ 2213.236357] [   T1972]  ? __pfx_smb2_open+0x10/0x10 [ksmbd]
[ 2213.236401] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.236407] [   T1972]  ? xas_load+0x19/0x300
[ 2213.236423] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.236429] [   T1972]  ? __kasan_check_write+0x14/0x30
[ 2213.236435] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.236441] [   T1972]  ? down_read_killable+0x120/0x290
[ 2213.236458] [   T1972]  handle_ksmbd_work+0x3fb/0xfe0 [ksmbd]
[ 2213.236489] [   T1972]  process_one_work+0x629/0xf80
[ 2213.236498] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.236504] [   T1972]  ? __kasan_check_write+0x14/0x30
[ 2213.236526] [   T1972]  worker_thread+0x87f/0x1570
[ 2213.236534] [   T1972]  ? __pfx__raw_spin_lock_irqsave+0x10/0x10
[ 2213.236541] [   T1972]  ? __pfx_try_to_wake_up+0x10/0x10
[ 2213.236552] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.236558] [   T1972]  ? kasan_print_address_stack_frame+0x227/0x280
[ 2213.236567] [   T1972]  ? __pfx_worker_thread+0x10/0x10
[ 2213.236581] [   T1972]  kthread+0x396/0x830
[ 2213.236589] [   T1972]  ? __pfx__raw_spin_lock_irq+0x10/0x10
[ 2213.236598] [   T1972]  ? __pfx_kthread+0x10/0x10
[ 2213.236604] [   T1972]  ? __kasan_check_write+0x14/0x30
[ 2213.236610] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.236616] [   T1972]  ? recalc_sigpending+0x180/0x210
[ 2213.236624] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.236630] [   T1972]  ? _raw_spin_unlock_irq+0xe/0x50
[ 2213.236643] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.236649] [   T1972]  ? calculate_sigpending+0x84/0xb0
[ 2213.236656] [   T1972]  ? __pfx_kthread+0x10/0x10
[ 2213.236664] [   T1972]  ret_from_fork+0x2b8/0x3b0
[ 2213.236671] [   T1972]  ? __pfx_kthread+0x10/0x10
[ 2213.236679] [   T1972]  ret_from_fork_asm+0x1a/0x30
[ 2213.236694] [   T1972]  </TASK>
[ 2213.236704] [   T1972]
[ 2213.269993] [   T1972] Allocated by task 1972 on cpu 2 at 2213.234048s:
[ 2213.270550] [   T1972]  kasan_save_stack+0x39/0x70
[ 2213.270569] [   T1972]  kasan_save_track+0x18/0x70
[ 2213.270578] [   T1972]  kasan_save_alloc_info+0x37/0x60
[ 2213.270587] [   T1972]  __kasan_slab_alloc+0x9d/0xa0
[ 2213.270606] [   T1972]  kmem_cache_alloc_noprof+0x13c/0x3f0
[ 2213.270619] [   T1972]  getname_kernel+0x55/0x390
[ 2213.270629] [   T1972]  __ksmbd_vfs_kern_path+0x1cf/0xa80 [ksmbd]
[ 2213.270712] [   T1972]  ksmbd_vfs_kern_path+0x15/0x30 [ksmbd]
[ 2213.270747] [   T1972]  smb2_open+0x2de6/0x9db0 [ksmbd]
[ 2213.270784] [   T1972]  handle_ksmbd_work+0x3fb/0xfe0 [ksmbd]
[ 2213.270814] [   T1972]  process_one_work+0x629/0xf80
[ 2213.270826] [   T1972]  worker_thread+0x87f/0x1570
[ 2213.270835] [   T1972]  kthread+0x396/0x830
[ 2213.270852] [   T1972]  ret_from_fork+0x2b8/0x3b0
[ 2213.270862] [   T1972]  ret_from_fork_asm+0x1a/0x30
[ 2213.270873] [   T1972]
[ 2213.271183] [   T1972] Freed by task 1972 on cpu 2 at 2213.234058s:
[ 2213.271707] [   T1972]  kasan_save_stack+0x39/0x70
[ 2213.271716] [   T1972]  kasan_save_track+0x18/0x70
[ 2213.271724] [   T1972]  kasan_save_free_info+0x3b/0x60
[ 2213.271732] [   T1972]  __kasan_slab_free+0x52/0x80
[ 2213.271741] [   T1972]  kmem_cache_free+0x316/0x560
[ 2213.271750] [   T1972]  putname+0xfa/0x150
[ 2213.271768] [   T1972]  __ksmbd_vfs_kern_path+0x20b/0xa80 [ksmbd]
[ 2213.271795] [   T1972]  ksmbd_vfs_kern_path+0x15/0x30 [ksmbd]
[ 2213.271829] [   T1972]  smb2_open+0x2de6/0x9db0 [ksmbd]
[ 2213.271857] [   T1972]  handle_ksmbd_work+0x3fb/0xfe0 [ksmbd]
[ 2213.271891] [   T1972]  process_one_work+0x629/0xf80
[ 2213.271901] [   T1972]  worker_thread+0x87f/0x1570
[ 2213.271910] [   T1972]  kthread+0x396/0x830
[ 2213.271918] [   T1972]  ret_from_fork+0x2b8/0x3b0
[ 2213.271926] [   T1972]  ret_from_fork_asm+0x1a/0x30
[ 2213.271935] [   T1972]
[ 2213.272236] [   T1972] The buggy address belongs to the object at ffff88801c95b300
                            which belongs to the cache names_cache of size 4096
[ 2213.273326] [   T1972] The buggy address is located 38 bytes inside of
                            freed 4096-byte region [ffff88801c95b300, ffff88801c95c300)
[ 2213.274374] [   T1972]
[ 2213.274671] [   T1972] The buggy address belongs to the physical page:
[ 2213.275233] [   T1972] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x1c958
[ 2213.275249] [   T1972] head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
[ 2213.275259] [   T1972] anon flags: 0xfffffc0000040(head|node=0|zone=1|lastcpupid=0x1fffff)
[ 2213.275270] [   T1972] page_type: f5(slab)
[ 2213.275280] [   T1972] raw: 000fffffc0000040 ffff888001367c80 0000000000000000 dead000000000001
[ 2213.275289] [   T1972] raw: 0000000000000000 0000000080070007 00000000f5000000 0000000000000000
[ 2213.275304] [   T1972] head: 000fffffc0000040 ffff888001367c80 0000000000000000 dead000000000001
[ 2213.275316] [   T1972] head: 0000000000000000 0000000080070007 00000000f5000000 0000000000000000
[ 2213.275326] [   T1972] head: 000fffffc0000003 ffffea0000725601 00000000ffffffff 00000000ffffffff
[ 2213.275334] [   T1972] head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000008
[ 2213.275341] [   T1972] page dumped because: kasan: bad access detected
[ 2213.275348] [   T1972]
[ 2213.275652] [   T1972] Memory state around the buggy address:
[ 2213.276139] [   T1972]  ffff88801c95b200: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 2213.276920] [   T1972]  ffff88801c95b280: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 2213.277700] [   T1972] >ffff88801c95b300: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 2213.278482] [   T1972]                                ^
[ 2213.278933] [   T1972]  ffff88801c95b380: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 2213.279723] [   T1972]  ffff88801c95b400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 2213.280496] [   T1972] ==================================================================
[ 2213.281383] [   T1972] Kernel panic - not syncing: KASAN: panic_on_warn set ...
[ 2213.281988] [   T1972] CPU: 2 UID: 0 PID: 1972 Comm: kworker/2:0 Kdump: loaded Tainted: G        W  OE       6.16.0-rc7-metze-kasan.01+ #1 PREEMPT(voluntary)
[ 2213.283165] [   T1972] Tainted: [W]=WARN, [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
[ 2213.283749] [   T1972] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[ 2213.284595] [   T1972] Workqueue: ksmbd-io handle_ksmbd_work [ksmbd]
[ 2213.285146] [   T1972] Call Trace:
[ 2213.285510] [   T1972]  <TASK>
[ 2213.285840] [   T1972]  dump_stack_lvl+0x27/0xa0
[ 2213.286276] [   T1972]  dump_stack+0x10/0x20
[ 2213.286700] [   T1972]  panic+0x538/0x610
[ 2213.287098] [   T1972]  ? __pfx_panic+0x10/0x10
[ 2213.287719] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.288223] [   T1972]  ? vprintk_default+0x1d/0x30
[ 2213.288682] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.289181] [   T1972]  ? sysvec_apic_timer_interrupt+0xa6/0xd0
[ 2213.289697] [   T1972]  ? asm_sysvec_apic_timer_interrupt+0x1b/0x20
[ 2213.290228] [   T1972]  check_panic_on_warn+0x6f/0x90
[ 2213.290691] [   T1972]  end_report+0xe6/0x100
[ 2213.291101] [   T1972]  kasan_report+0xf9/0x130
[ 2213.291537] [   T1972]  ? lookup_noperm_common+0x237/0x2b0
[ 2213.292013] [   T1972]  ? lookup_noperm_common+0x237/0x2b0
[ 2213.292524] [   T1972]  __asan_report_load1_noabort+0x14/0x30
[ 2213.293014] [   T1972]  lookup_noperm_common+0x237/0x2b0
[ 2213.293498] [   T1972]  lookup_noperm_unlocked+0x1d/0xa0
[ 2213.293961] [   T1972]  ? putname+0xfa/0x150
[ 2213.294397] [   T1972]  __ksmbd_vfs_kern_path+0x376/0xa80 [ksmbd]
[ 2213.294935] [   T1972]  ? local_clock+0x15/0x30
[ 2213.295361] [   T1972]  ? kasan_save_track+0x27/0x70
[ 2213.295823] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.296328] [   T1972]  ? __entry_text_end+0x10257a/0x10257d
[ 2213.296822] [   T1972]  ? __pfx___ksmbd_vfs_kern_path+0x10/0x10 [ksmbd]
[ 2213.297389] [   T1972]  ? groups_alloc+0x41/0xe0
[ 2213.297829] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.298318] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.298808] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.299322] [   T1972]  ? __kasan_check_write+0x14/0x30
[ 2213.299790] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.300277] [   T1972]  ? __ksmbd_override_fsids+0x340/0x630 [ksmbd]
[ 2213.300839] [   T1972]  ? smb2_open+0x40b/0x9db0 [ksmbd]
[ 2213.301333] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.301834] [   T1972]  ksmbd_vfs_kern_path+0x15/0x30 [ksmbd]
[ 2213.302358] [   T1972]  smb2_open+0x2de6/0x9db0 [ksmbd]
[ 2213.302841] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.303332] [   T1972]  ? stack_depot_save_flags+0x28/0x840
[ 2213.303829] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.304323] [   T1972]  ? enqueue_hrtimer+0x10b/0x230
[ 2213.304786] [   T1972]  ? ksm_scan_thread+0x480/0x59b0
[ 2213.305238] [   T1972]  ? ksm_scan_thread+0x480/0x59b0
[ 2213.305702] [   T1972]  ? __pfx_smb2_open+0x10/0x10 [ksmbd]
[ 2213.306225] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.306718] [   T1972]  ? xas_load+0x19/0x300
[ 2213.307141] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.307846] [   T1972]  ? __kasan_check_write+0x14/0x30
[ 2213.308330] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.308834] [   T1972]  ? down_read_killable+0x120/0x290
[ 2213.309319] [   T1972]  handle_ksmbd_work+0x3fb/0xfe0 [ksmbd]
[ 2213.309853] [   T1972]  process_one_work+0x629/0xf80
[ 2213.310308] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.310800] [   T1972]  ? __kasan_check_write+0x14/0x30
[ 2213.311262] [   T1972]  worker_thread+0x87f/0x1570
[ 2213.311700] [   T1972]  ? __pfx__raw_spin_lock_irqsave+0x10/0x10
[ 2213.312204] [   T1972]  ? __pfx_try_to_wake_up+0x10/0x10
[ 2213.312691] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.313183] [   T1972]  ? kasan_print_address_stack_frame+0x227/0x280
[ 2213.313728] [   T1972]  ? __pfx_worker_thread+0x10/0x10
[ 2213.314192] [   T1972]  kthread+0x396/0x830
[ 2213.314599] [   T1972]  ? __pfx__raw_spin_lock_irq+0x10/0x10
[ 2213.315097] [   T1972]  ? __pfx_kthread+0x10/0x10
[ 2213.315536] [   T1972]  ? __kasan_check_write+0x14/0x30
[ 2213.315993] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.316485] [   T1972]  ? recalc_sigpending+0x180/0x210
[ 2213.316954] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.317455] [   T1972]  ? _raw_spin_unlock_irq+0xe/0x50
[ 2213.317921] [   T1972]  ? srso_alias_return_thunk+0x5/0xfbef5
[ 2213.318409] [   T1972]  ? calculate_sigpending+0x84/0xb0
[ 2213.318883] [   T1972]  ? __pfx_kthread+0x10/0x10
[ 2213.319311] [   T1972]  ret_from_fork+0x2b8/0x3b0
[ 2213.319750] [   T1972]  ? __pfx_kthread+0x10/0x10
[ 2213.320188] [   T1972]  ret_from_fork_asm+0x1a/0x30
[ 2213.320656] [   T1972]  </TASK>

Can you please have a look?

Thanks!
metze

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/4] smb/server: add ksmbd_vfs_kern_path()
  2025-07-23 15:36   ` Stefan Metzmacher
@ 2025-07-23 23:03     ` NeilBrown
  2025-07-23 23:19       ` Namjae Jeon
  0 siblings, 1 reply; 10+ messages in thread
From: NeilBrown @ 2025-07-23 23:03 UTC (permalink / raw)
  To: Stefan Metzmacher
  Cc: Namjae Jeon, Steve French, Sergey Senozhatsky, Tom Talpey,
	Alexander Viro, Christian Brauner, Jan Kara, linux-fsdevel,
	linux-cifs, linux-kernel

On Thu, 24 Jul 2025, Stefan Metzmacher wrote:
> Hi Neil,
> 
> for me this reliable generates the following problem, just doing a simple:
> mount -t cifs -ousername=root,password=test,noperm,vers=3.1.1,mfsymlinks,actimeo=0 //172.31.9.167/test /mnt/test/
> 
> [ 2213.234061] [   T1972] ==================================================================
> [ 2213.234607] [   T1972] BUG: KASAN: slab-use-after-free in lookup_noperm_common+0x237/0x2b0

Hi,
 thanks for testing and reporting.  Sorry about this obvious bug...

I called putname() too early.  The following should fix it.  Please test
and support.
Namjae: it would be good to squash this into the offending patch before
submitting upstream.  Can you do that?  Do you want me to resend the
whole patch?

Thanks,
NeilBrown

--- a/fs/smb/server/vfs.c
+++ b/fs/smb/server/vfs.c
@@ -53,7 +53,7 @@ static int ksmbd_vfs_path_lookup(struct ksmbd_share_config *share_conf,
 				 struct path *path, bool do_lock)
 {
 	struct qstr last;
-	struct filename *filename;
+	struct filename *filename __free(putname) = NULL;
 	struct path *root_share_path = &share_conf->vfs_path;
 	int err, type;
 	struct dentry *d;
@@ -72,7 +72,6 @@ static int ksmbd_vfs_path_lookup(struct ksmbd_share_config *share_conf,
 	err = vfs_path_parent_lookup(filename, flags,
 				     path, &last, &type,
 				     root_share_path);
-	putname(filename);
 	if (err)
 		return err;
 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 4/4] smb/server: add ksmbd_vfs_kern_path()
  2025-07-23 23:03     ` NeilBrown
@ 2025-07-23 23:19       ` Namjae Jeon
  0 siblings, 0 replies; 10+ messages in thread
From: Namjae Jeon @ 2025-07-23 23:19 UTC (permalink / raw)
  To: NeilBrown
  Cc: Stefan Metzmacher, Steve French, Sergey Senozhatsky, Tom Talpey,
	Alexander Viro, Christian Brauner, Jan Kara, linux-fsdevel,
	linux-cifs, linux-kernel

On Thu, Jul 24, 2025 at 8:04 AM NeilBrown <neil@brown.name> wrote:
>
> On Thu, 24 Jul 2025, Stefan Metzmacher wrote:
> > Hi Neil,
> >
> > for me this reliable generates the following problem, just doing a simple:
> > mount -t cifs -ousername=root,password=test,noperm,vers=3.1.1,mfsymlinks,actimeo=0 //172.31.9.167/test /mnt/test/
> >
> > [ 2213.234061] [   T1972] ==================================================================
> > [ 2213.234607] [   T1972] BUG: KASAN: slab-use-after-free in lookup_noperm_common+0x237/0x2b0
>
> Hi,
>  thanks for testing and reporting.  Sorry about this obvious bug...
>
> I called putname() too early.  The following should fix it.  Please test
> and support.
> Namjae: it would be good to squash this into the offending patch before
> submitting upstream.  Can you do that?  Do you want me to resend the
> whole patch?
You don't need to resend the patch. I will directly update and test it.
Thanks!

>
> Thanks,
> NeilBrown
>
> --- a/fs/smb/server/vfs.c
> +++ b/fs/smb/server/vfs.c
> @@ -53,7 +53,7 @@ static int ksmbd_vfs_path_lookup(struct ksmbd_share_config *share_conf,
>                                  struct path *path, bool do_lock)
>  {
>         struct qstr last;
> -       struct filename *filename;
> +       struct filename *filename __free(putname) = NULL;
>         struct path *root_share_path = &share_conf->vfs_path;
>         int err, type;
>         struct dentry *d;
> @@ -72,7 +72,6 @@ static int ksmbd_vfs_path_lookup(struct ksmbd_share_config *share_conf,
>         err = vfs_path_parent_lookup(filename, flags,
>                                      path, &last, &type,
>                                      root_share_path);
> -       putname(filename);
>         if (err)
>                 return err;
>
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2025-07-23 23:20 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-08 23:35 [PATCH 0/4] smb/server: various clean-ups NeilBrown
2025-06-08 23:35 ` [PATCH 1/4] smb/server: use lookup_one_unlocked() NeilBrown
2025-06-08 23:35 ` [PATCH 2/4] smb/server: simplify ksmbd_vfs_kern_path_locked() NeilBrown
2025-06-08 23:35 ` [PATCH 3/4] smb/server: avoid deadlock when linking with ReplaceIfExists NeilBrown
2025-06-08 23:35 ` [PATCH 4/4] smb/server: add ksmbd_vfs_kern_path() NeilBrown
2025-07-23 15:36   ` Stefan Metzmacher
2025-07-23 23:03     ` NeilBrown
2025-07-23 23:19       ` Namjae Jeon
2025-07-16  5:22 ` [PATCH 0/4] smb/server: various clean-ups NeilBrown
2025-07-16  6:59   ` Namjae Jeon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).