[PATCH 2/2] nvmet: avoid recursive configfs open for passthru

Runyu Xiao <[email protected]>
Newsgroups org.infradead.lists.linux-nvme,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <[email protected]>
nvmet_passthru_enable_store() runs as a configfs store callback while
configfs holds the item's frag_sem. nvmet_passthru_ctrl_enable() then
uses filp_open() on the configured passthru_ctrl_path.

If passthru_ctrl_path points back into configfs, the open path
re-enters __configfs_open_file() and tries to take the same frag_sem
again.

Resolve the path with kern_path(), reject configfs paths, and open the
resolved path with dentry_open() instead of filp_open(). Configfs paths
are not valid passthru controller backends, so rejecting them avoids
the recursion without changing valid users.

Fixes: cae5b01a2afc ("nvmet: introduce the passthru configfs interface")
Cc: [email protected]

Signed-off-by: Runyu Xiao <[email protected]>
---
 drivers/nvme/target/passthru.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c
index 0c361b1e3566..be302f70d0e2 100644
--- a/drivers/nvme/target/passthru.c
+++ b/drivers/nvme/target/passthru.c
@@ -8,6 +8,7 @@
  *
  */
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/namei.h>
 #include <linux/module.h>
 
 #include "../host/nvme.h"
@@ -578,6 +579,7 @@ int nvmet_passthru_ctrl_enable(struct nvmet_subsys *subsys)
 {
 	struct nvme_ctrl *ctrl;
 	struct file *file;
+	struct path path;
 	int ret = -EINVAL;
 	void *old;
 
@@ -592,7 +594,20 @@ int nvmet_passthru_ctrl_enable(struct nvmet_subsys *subsys)
 		goto out_unlock;
 	}
 
-	file = filp_open(subsys->passthru_ctrl_path, O_RDWR, 0);
+	ret = kern_path(subsys->passthru_ctrl_path, LOOKUP_FOLLOW, &path);
+	if (ret)
+		goto out_unlock;
+
+	if (!strcmp(path.dentry->d_sb->s_type->name, "configfs")) {
+		pr_err("configfs paths cannot back passthru controller %s\n",
+		       subsys->passthru_ctrl_path);
+		path_put(&path);
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	file = dentry_open(&path, O_RDWR, current_cred());
+	path_put(&path);
 	if (IS_ERR(file)) {
 		ret = PTR_ERR(file);
 		goto out_unlock;
-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.