[PATCH v4 21/31] firmware: arm_scmi: stlmfs: Add basic mount options

Cristian Marussi cristian.marussi at arm.com
Fri Jun 12 15:37:51 PDT 2026


Add mount options to choose different uid/gid/umask for all the created
files; reject handling changes to these options while remounting.

Signed-off-by: Cristian Marussi <cristian.marussi at arm.com>
---
 .../firmware/arm_scmi/scmi_system_telemetry.c | 146 +++++++++++++++++-
 1 file changed, 143 insertions(+), 3 deletions(-)

diff --git a/drivers/firmware/arm_scmi/scmi_system_telemetry.c b/drivers/firmware/arm_scmi/scmi_system_telemetry.c
index 567585dfb036..f4d284335ac0 100644
--- a/drivers/firmware/arm_scmi/scmi_system_telemetry.c
+++ b/drivers/firmware/arm_scmi/scmi_system_telemetry.c
@@ -34,6 +34,32 @@
 #define MAX_AVAILABLE_INTERV_CHAR_LENGTH	25
 #define MAX_BULK_LINE_CHAR_LENGTH		64
 
+enum {
+	Opt_uid,
+	Opt_gid,
+	Opt_umask,
+};
+
+static const struct fs_parameter_spec stlmfs_param_spec[] = {
+	fsparam_uid("uid", Opt_uid),
+	fsparam_gid("gid", Opt_gid),
+	fsparam_u32oct("umask", Opt_umask),
+	{}
+};
+
+struct stlmfs_fs_context {
+	unsigned int opts;
+	kuid_t uid;
+	kgid_t gid;
+	umode_t umask;
+};
+
+struct stlmfs_sb_info {
+	kuid_t uid;
+	kgid_t gid;
+	umode_t umask;
+};
+
 static struct kmem_cache *stlmfs_inode_cachep;
 
 static DEFINE_MUTEX(stlmfs_mtx);
@@ -202,10 +228,12 @@ static struct inode *stlmfs_get_inode(struct super_block *sb, umode_t mode)
 	struct inode *inode = new_inode(sb);
 
 	if (inode) {
+		struct stlmfs_sb_info *sbi = sb->s_fs_info;
+
 		inode->i_ino = get_next_ino();
-		inode->i_uid = GLOBAL_ROOT_UID;
-		inode->i_gid = GLOBAL_ROOT_GID;
-		inode->i_mode = mode & ~SCMI_TLM_DEFAULT_UMASK;
+		inode->i_uid = sbi->uid;
+		inode->i_gid = sbi->gid;
+		inode->i_mode = mode & ~sbi->umask;
 		simple_inode_init_ts(inode);
 	}
 
@@ -1282,10 +1310,25 @@ static void stlmfs_free_inode(struct inode *inode)
 	kmem_cache_free(stlmfs_inode_cachep, tlmi);
 }
 
+static int stlmfs_show_options(struct seq_file *seq, struct dentry *root)
+{
+	struct stlmfs_sb_info *sbi = root->d_sb->s_fs_info;
+
+	if (!uid_eq(sbi->uid, GLOBAL_ROOT_UID))
+		seq_printf(seq, ",uid=%u", from_kuid_munged(&init_user_ns, sbi->uid));
+	if (!gid_eq(sbi->gid, GLOBAL_ROOT_GID))
+		seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, sbi->gid));
+	if (sbi->umask != SCMI_TLM_DEFAULT_UMASK)
+		seq_printf(seq, ",umask=%04u", sbi->umask);
+
+	return 0;
+}
+
 static const struct super_operations tlm_sops = {
 	.statfs = simple_statfs,
 	.alloc_inode = stlmfs_alloc_inode,
 	.free_inode = stlmfs_free_inode,
+	.show_options = stlmfs_show_options,
 };
 
 static struct dentry *stlmfs_create_root_dentry(struct super_block *sb)
@@ -1366,10 +1409,26 @@ static int scmi_telemetry_instance_register(struct super_block *sb,
 
 static int stlmfs_fill_super(struct super_block *sb, struct fs_context *fc)
 {
+	struct stlmfs_fs_context *ctx;
 	struct scmi_tlm_instance *ti;
 	struct dentry *root_dentry;
 	int ret;
 
+	/* Bail out if already initialized */
+	if (sb->s_fs_info)
+		return 0;
+
+	struct stlmfs_sb_info *sbi __free(kfree) =
+		kzalloc(sizeof(*sbi), GFP_KERNEL);
+	if (!sbi)
+		return -ENOMEM;
+
+	ctx = fc->fs_private;
+	sbi->uid = ctx->uid;
+	sbi->gid = ctx->gid;
+	sbi->umask = ctx->umask;
+
+	sb->s_fs_info = sbi;
 	sb->s_magic = TLM_FS_MAGIC;
 	sb->s_blocksize = PAGE_SIZE;
 	sb->s_blocksize_bits = PAGE_SHIFT;
@@ -1379,6 +1438,7 @@ static int stlmfs_fill_super(struct super_block *sb, struct fs_context *fc)
 	if (IS_ERR(root_dentry))
 		return PTR_ERR(root_dentry);
 
+	retain_and_null_ptr(sbi);
 	sb->s_root = root_dentry;
 
 	mutex_lock(&stlmfs_mtx);
@@ -1396,17 +1456,93 @@ static int stlmfs_fill_super(struct super_block *sb, struct fs_context *fc)
 	return 0;
 }
 
+static void stlmfs_free(struct fs_context *fc)
+{
+	struct stlmfs_fs_context *ctx;
+
+	ctx = fc->fs_private;
+
+	kfree(ctx);
+}
+
 static int stlmfs_get_tree(struct fs_context *fc)
 {
 	return get_tree_single(fc, stlmfs_fill_super);
 }
 
+static int stlmfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
+{
+	struct stlmfs_fs_context *ctx;
+	struct fs_parse_result result;
+	int opt;
+
+	opt = fs_parse(fc, stlmfs_param_spec, param, &result);
+	if (opt < 0)
+		return opt;
+
+	ctx = fc->fs_private;
+
+	switch (opt) {
+	case Opt_uid:
+		if (!kuid_has_mapping(fc->user_ns, result.uid))
+			return invalfc(fc, "Invalid uid");
+		ctx->uid = result.uid;
+		ctx->opts |= BIT(Opt_uid);
+		break;
+	case Opt_gid:
+		if (!kgid_has_mapping(fc->user_ns, result.gid))
+			return invalfc(fc, "Invalid gid");
+		ctx->gid = result.gid;
+		ctx->opts |= BIT(Opt_gid);
+		break;
+	case Opt_umask:
+		ctx->umask = result.uint_32 & 07777;
+		ctx->opts |= BIT(Opt_umask);
+		break;
+	default:
+		return -ENOPARAM;
+	}
+
+	return 0;
+}
+
+static int stlmfs_reconfigure(struct fs_context *fc)
+{
+	struct stlmfs_fs_context *ctx = fc->fs_private;
+
+	sync_filesystem(fc->root->d_sb);
+
+	if (ctx->opts & BIT(Opt_uid))
+		return invalfc(fc, "uid cannot be changed on remount");
+	if (ctx->opts & BIT(Opt_gid))
+		return invalfc(fc, "gid cannot be changed on remount");
+	if (ctx->opts & BIT(Opt_umask))
+		return invalfc(fc, "umask cannot be changed on remount");
+
+	return 0;
+}
+
 static const struct fs_context_operations stlmfs_fc_ops = {
 	.get_tree = stlmfs_get_tree,
+	.parse_param = stlmfs_parse_param,
+	.free = stlmfs_free,
+	.reconfigure = stlmfs_reconfigure,
 };
 
 static int stlmfs_init_fs_context(struct fs_context *fc)
 {
+	struct stlmfs_fs_context *ctx;
+
+	ctx = kzalloc_obj(*ctx);
+	if (!ctx)
+		return -ENOMEM;
+
+	/* defaults */
+	ctx->uid = GLOBAL_ROOT_UID;
+	ctx->gid = GLOBAL_ROOT_GID;
+	ctx->umask = SCMI_TLM_DEFAULT_UMASK;
+
+	fc->fs_private = ctx;
 	fc->ops = &stlmfs_fc_ops;
 
 	return 0;
@@ -1414,11 +1550,15 @@ static int stlmfs_init_fs_context(struct fs_context *fc)
 
 static void stlmfs_kill_sb(struct super_block *sb)
 {
+	struct stlmfs_sb_info *sbi = sb->s_fs_info;
+
 	mutex_lock(&stlmfs_mtx);
 	stlmfs_sb = NULL;
 	mutex_unlock(&stlmfs_mtx);
 
 	kill_anon_super(sb);
+
+	kfree(sbi);
 }
 
 static struct file_system_type scmi_telemetry_fs = {
-- 
2.54.0




More information about the linux-arm-kernel mailing list