[PATCH v4 1/3] fs: configfs: add helpers for opening non-configfs paths

From: Runyu Xiao

Date: Mon Sep 21 2026 - 05:07:41 EST


Configfs store callbacks may open user-configured paths while holding an
item frag_sem. Opening a configfs path from such a callback can re-enter
configfs and try to acquire the same semaphore.

Add helpers that reject configfs paths by comparing the actual filesystem
type and open the resolved path with file_open_root(), preserving normal
open-time permission and security checks. Provide a root-relative form for
callers that retain a resolved root and may create a file below it.

Assisted-by: LLM Codex
Signed-off-by: Runyu Xiao <runyu.xiao@xxxxxxxxxx>
---
fs/configfs/mount.c | 33 +++++++++++++++++++++++++++++++++
include/linux/configfs.h | 6 ++++++
2 files changed, 39 insertions(+)

diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c
index d8cac1cbf3bd5..77e1788ce2372 100644
--- a/fs/configfs/mount.c
+++ b/fs/configfs/mount.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/mount.h>
#include <linux/fs_context.h>
+#include <linux/namei.h>
#include <linux/pagemap.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -118,6 +119,38 @@ static struct file_system_type configfs_fs_type = {
};
MODULE_ALIAS_FS("configfs");

+bool configfs_path_is_configfs(const struct path *path)
+{
+ return path->dentry->d_sb->s_type == &configfs_fs_type;
+}
+EXPORT_SYMBOL_GPL(configfs_path_is_configfs);
+
+struct file *configfs_open_root(const struct path *root, const char *name,
+ int flags, umode_t mode)
+{
+ if (configfs_path_is_configfs(root))
+ return ERR_PTR(-EINVAL);
+
+ return file_open_root(root, name, flags, mode);
+}
+EXPORT_SYMBOL_GPL(configfs_open_root);
+
+struct file *configfs_file_open(const char *filename, int flags, umode_t mode)
+{
+ struct file *file;
+ struct path path;
+ int ret;
+
+ ret = kern_path(filename, LOOKUP_FOLLOW, &path);
+ if (ret)
+ return ERR_PTR(ret);
+
+ file = configfs_open_root(&path, "", flags, mode);
+ path_put(&path);
+ return file;
+}
+EXPORT_SYMBOL_GPL(configfs_file_open);
+
struct dentry *configfs_pin_fs(void)
{
int err = simple_pin_fs(&configfs_fs_type, &configfs_mount,
diff --git a/include/linux/configfs.h b/include/linux/configfs.h
index ef65c75beeaad..768132b2be1ae 100644
--- a/include/linux/configfs.h
+++ b/include/linux/configfs.h
@@ -34,6 +34,8 @@ struct configfs_group_operations;
struct configfs_attribute;
struct configfs_bin_attribute;
struct configfs_subsystem;
+struct file;
+struct path;

struct config_item {
char *ci_name;
@@ -243,6 +245,10 @@ void configfs_unregister_subsystem(struct configfs_subsystem *subsys);
int configfs_register_group(struct config_group *parent_group,
struct config_group *group);
void configfs_unregister_group(struct config_group *group);
+bool configfs_path_is_configfs(const struct path *path);
+struct file *configfs_open_root(const struct path *root, const char *name,
+ int flags, umode_t mode);
+struct file *configfs_file_open(const char *filename, int flags, umode_t mode);

void configfs_remove_default_groups(struct config_group *group);

--
2.34.1