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

From: Runyu Xiao

Date: Thu Sep 10 2026 - 00:56:55 EST


nvmet_passthru_enable_store() runs as a configfs store callback while
configfs holds the item's frag_sem. Enabling passthru then opens the
configured passthru_ctrl_path with filp_open(). If that path resolves
into configfs, the open path re-enters __configfs_open_file() and attempts
to acquire the same frag_sem again.

Resolve the configured path first, reject paths resolved on configfs, and
open the resolved path with file_open_root(). This preserves the standard
open-time permission checks without performing a second pathname walk. Use
the configfs helper for the filesystem type check so this caller shares the
classification with other configfs users.

Fixes: cae5b01a2afc ("nvmet: introduce the passthru configfs interface")
Cc: stable@xxxxxxxxxxxxxxx
Reviewed-by: Sagi Grimberg <sagi@xxxxxxxxxxx>
Assisted-by: LLM Codex
Signed-off-by: Runyu Xiao <runyu.xiao@xxxxxxxxxx>
---
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 fa6527c53..aa1778c9e 100644
--- a/drivers/nvme/target/passthru.c
+++ b/drivers/nvme/target/passthru.c
@@ -9,6 +9,8 @@
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
+#include <linux/configfs.h>
+#include <linux/namei.h>

#include "../host/nvme.h"
#include "nvmet.h"
@@ -588,6 +590,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;

@@ -602,7 +605,19 @@ 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 (configfs_path_is_configfs(&path)) {
+ pr_err("configfs paths cannot back passthru controller %s\n",
+ subsys->passthru_ctrl_path);
+ path_put(&path);
+ goto out_unlock;
+ }
+
+ file = file_open_root(&path, "", O_RDWR, 0);
+ path_put(&path);
if (IS_ERR(file)) {
ret = PTR_ERR(file);
goto out_unlock;
--
2.34.1