[PATCH] scsi: target: file: reject configfs-backed paths in configfs stores

From: Runyu Xiao

Date: Tue Aug 18 2026 - 00:59:22 EST


FILEIO paths can be opened from configfs store callbacks while configfs
holds the item's frag_sem.

target_dev_enable_store() reaches fd_configure_device() and
pi_prot_type_store() reaches fd_init_prot(). Both helpers call
filp_open() on user-controlled FILEIO paths. If either path resolves
inside configfs, the lookup can re-enter __configfs_open_file() and try
to take the same frag_sem again.

Reject configfs-backed FILEIO paths before calling filp_open(). Resolve
existing paths with kern_path(), and when O_CREAT may create the last
component, fall back to checking the parent directory with
kern_path_parent(). Keep reporting ordinary path lookup failures instead
of silently bypassing the existing FILEIO error paths.

Fixes: c66ac9db8d4a ("[SCSI] target: Add LIO target core v4.0.0-rc6")
Fixes: 0f5e2ec46dd6 ("target/file: Add DIF protection init/format support")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Runyu Xiao <runyu.xiao@xxxxxxxxxx>
---
drivers/target/target_core_file.c | 50 +++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)

diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
index 2d78ef7..4351300 100644
--- a/drivers/target/target_core_file.c
+++ b/drivers/target/target_core_file.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/falloc.h>
+#include <linux/namei.h>
#include <linux/uio.h>
#include <linux/scatterlist.h>
#include <scsi/scsi_proto.h>
@@ -86,6 +87,33 @@ static struct se_device *fd_alloc_device(struct se_hba *hba, const char *name)
return &fd_dev->dev;
}

+static int fd_validate_fileio_path(const char *path)
+{
+ struct path lookup_path = {};
+ struct dentry *dentry;
+ int ret;
+
+ ret = kern_path(path, LOOKUP_FOLLOW, &lookup_path);
+ if (!ret) {
+ ret = !strcmp(lookup_path.dentry->d_sb->s_type->name, "configfs") ?
+ -EINVAL : 0;
+ path_put(&lookup_path);
+ return ret;
+ }
+ if (ret != -ENOENT)
+ return ret;
+
+ dentry = kern_path_parent(path, &lookup_path);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+
+ ret = !strcmp(lookup_path.dentry->d_sb->s_type->name, "configfs") ?
+ -EINVAL : 0;
+ dput(dentry);
+ path_put(&lookup_path);
+ return ret;
+}
+
static bool fd_configure_unmap(struct se_device *dev)
{
struct file *file = FD_DEV(dev)->fd_file;
@@ -137,6 +165,17 @@ static int fd_configure_device(struct se_device *dev)
flags &= ~O_DSYNC;
}

+ ret = fd_validate_fileio_path(fd_dev->fd_dev_name);
+ if (ret) {
+ if (ret == -EINVAL)
+ pr_err("configfs-backed path is not valid for FILEIO backend: %s\n",
+ fd_dev->fd_dev_name);
+ else
+ pr_err("FILEIO backend path lookup failed for %s: %d\n",
+ fd_dev->fd_dev_name, ret);
+ goto fail;
+ }
+
file = filp_open(fd_dev->fd_dev_name, flags, 0600);
if (IS_ERR(file)) {
pr_err("filp_open(%s) failed\n", fd_dev->fd_dev_name);
@@ -847,6 +886,17 @@ static int fd_init_prot(struct se_device *dev)
snprintf(buf, FD_MAX_DEV_PROT_NAME, "%s.protection",
fd_dev->fd_dev_name);

+ ret = fd_validate_fileio_path(buf);
+ if (ret) {
+ if (ret == -EINVAL)
+ pr_err("configfs-backed path is not valid for FILEIO protection: %s\n",
+ buf);
+ else
+ pr_err("FILEIO protection path lookup failed for %s: %d\n",
+ buf, ret);
+ return ret;
+ }
+
prot_file = filp_open(buf, flags, 0600);
if (IS_ERR(prot_file)) {
pr_err("filp_open(%s) failed\n", buf);
--
2.34.1