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

Runyu Xiao <[email protected]>
Newsgroups gmane.linux.scsi,gmane.linux.scsi.target.devel,gmane.linux.kernel,gmane.linux.kernel.stable
Message-ID <[email protected]>
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: [email protected]
Signed-off-by: Runyu Xiao <[email protected]>
---
 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
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.