Blob Blame History Raw
From: Miklos Szeredi <mszeredi@redhat.com>
Date: Tue, 14 Jul 2020 14:45:41 +0200
Subject: fuse: reject options on reconfigure via fsconfig(2)
Git-commit: b330966f79fb4fdc49183f58db113303695a750f
Patch-mainline: v5.8-rc6
References: jsc#SLE-13782

Previous patch changed handling of remount/reconfigure to ignore all
options, including those that are unknown to the fuse kernel fs.  This was
done for backward compatibility, but this likely only affects the old
mount(2) API.

The new fsconfig(2) based reconfiguration could possibly be improved.  This
would make the new API less of a drop in replacement for the old, OTOH this
is a good chance to get rid of some weirdnesses in the old API.

Several other behaviors might make sense:

 1) unknown options are rejected, known options are ignored

 2) unknown options are rejected, known options are rejected if the value
 is changed, allowed otherwise

 3) all options are rejected

Prior to the backward compatibility fix to ignore all options all known
options were accepted (1), even if they change the value of a mount
parameter; fuse_reconfigure() does not look at the config values set by
fuse_parse_param().

To fix that we'd need to verify that the value provided is the same as set
in the initial configuration (2).  The major drawback is that this is much
more complex than just rejecting all attempts at changing options (3);
i.e. all options signify initial configuration values and don't make sense
on reconfigure.

This patch opts for (3) with the rationale that no mount options are
reconfigurable in fuse.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
[luis: use invalf instead of invalfc as we're missing commit
 2e28c49ea648 ("fuse: switch to use errorfc() et.al.") ]
Acked-by: Luis Henriques <lhenriques@suse.com>
---
 fs/fuse/inode.c            |   16 ++++++++++------
 fs/namespace.c             |    1 +
 include/linux/fs_context.h |    1 +
 3 files changed, 12 insertions(+), 6 deletions(-)

--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -475,12 +475,16 @@ static int fuse_parse_param(struct fs_co
 	struct fuse_fs_context *ctx = fc->fs_private;
 	int opt;
 
-	/*
-	 * Ignore options coming from mount(MS_REMOUNT) for backward
-	 * compatibility.
-	 */
-	if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE)
-		return 0;
+	if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) {
+		/*
+		 * Ignore options coming from mount(MS_REMOUNT) for backward
+		 * compatibility.
+		 */
+		if (fc->oldapi)
+			return 0;
+
+		return invalf(fc, "No changes allowed in reconfigure");
+	}
 
 	opt = fs_parse(fc, &fuse_fs_parameters, param, &result);
 	if (opt < 0)
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2517,6 +2517,7 @@ static int do_remount(struct path *path,
 	if (IS_ERR(fc))
 		return PTR_ERR(fc);
 
+	fc->oldapi = true;
 	err = parse_monolithic_mount_data(fc, data);
 	if (!err) {
 		down_write(&sb->s_umount);
--- a/include/linux/fs_context.h
+++ b/include/linux/fs_context.h
@@ -105,6 +105,7 @@ struct fs_context {
 	enum fs_context_phase	phase:8;	/* The phase the context is in */
 	bool			need_free:1;	/* Need to call ops->free() */
 	bool			global:1;	/* Goes into &init_user_ns */
+	bool			oldapi:1;	/* Coming from mount(2) */
 };
 
 struct fs_context_operations {