summaryrefslogtreecommitdiff
path: root/fs/debugfs
diff options
context:
space:
mode:
authorBrian Norris <briannorris@chromium.org>2022-09-12 16:31:42 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-09-24 14:01:37 +0200
commitb8de524ce46ef59889600bc29019c5ed4ccd6687 (patch)
tree2af30e77836b2f7c7927ddefd1a9657898afcd0b /fs/debugfs
parent4abc99652812a2ddf932f137515d5c5a04723538 (diff)
downloadlwn-b8de524ce46ef59889600bc29019c5ed4ccd6687.tar.gz
lwn-b8de524ce46ef59889600bc29019c5ed4ccd6687.zip
debugfs: Only clobber mode/uid/gid on remount if asked
Users may have explicitly configured their debugfs permissions; we shouldn't overwrite those just because a second mount appeared. Only clobber if the options were provided at mount time. Existing behavior: ## Pre-existing status: debugfs is 0755. # chmod 755 /sys/kernel/debug/ # stat -c '%A' /sys/kernel/debug/ drwxr-xr-x ## New mount sets kernel-default permissions: # mount -t debugfs none /mnt/foo # stat -c '%A' /mnt/foo drwx------ ## Unexpected: the original mount changed permissions: # stat -c '%A' /sys/kernel/debug drwx------ New behavior: ## Pre-existing status: debugfs is 0755. # chmod 755 /sys/kernel/debug/ # stat -c '%A' /sys/kernel/debug/ drwxr-xr-x ## New mount inherits existing permissions: # mount -t debugfs none /mnt/foo # stat -c '%A' /mnt/foo drwxr-xr-x ## Expected: old mount is unchanged: # stat -c '%A' /sys/kernel/debug drwxr-xr-x Full test cases are being submitted to LTP. Signed-off-by: Brian Norris <briannorris@chromium.org> Link: https://lore.kernel.org/r/20220912163042.v3.1.Icbd40fce59f55ad74b80e5d435ea233579348a78@changeid Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/debugfs')
-rw-r--r--fs/debugfs/inode.c37
1 files changed, 30 insertions, 7 deletions
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 232cfdf095ae..2e8e112b1993 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -82,6 +82,8 @@ struct debugfs_mount_opts {
kuid_t uid;
kgid_t gid;
umode_t mode;
+ /* Opt_* bitfield. */
+ unsigned int opts;
};
enum {
@@ -111,6 +113,7 @@ static int debugfs_parse_options(char *data, struct debugfs_mount_opts *opts)
kgid_t gid;
char *p;
+ opts->opts = 0;
opts->mode = DEBUGFS_DEFAULT_MODE;
while ((p = strsep(&data, ",")) != NULL) {
@@ -145,24 +148,44 @@ static int debugfs_parse_options(char *data, struct debugfs_mount_opts *opts)
* but traditionally debugfs has ignored all mount options
*/
}
+
+ opts->opts |= BIT(token);
}
return 0;
}
-static int debugfs_apply_options(struct super_block *sb)
+static void _debugfs_apply_options(struct super_block *sb, bool remount)
{
struct debugfs_fs_info *fsi = sb->s_fs_info;
struct inode *inode = d_inode(sb->s_root);
struct debugfs_mount_opts *opts = &fsi->mount_opts;
- inode->i_mode &= ~S_IALLUGO;
- inode->i_mode |= opts->mode;
+ /*
+ * On remount, only reset mode/uid/gid if they were provided as mount
+ * options.
+ */
- inode->i_uid = opts->uid;
- inode->i_gid = opts->gid;
+ if (!remount || opts->opts & BIT(Opt_mode)) {
+ inode->i_mode &= ~S_IALLUGO;
+ inode->i_mode |= opts->mode;
+ }
- return 0;
+ if (!remount || opts->opts & BIT(Opt_uid))
+ inode->i_uid = opts->uid;
+
+ if (!remount || opts->opts & BIT(Opt_gid))
+ inode->i_gid = opts->gid;
+}
+
+static void debugfs_apply_options(struct super_block *sb)
+{
+ _debugfs_apply_options(sb, false);
+}
+
+static void debugfs_apply_options_remount(struct super_block *sb)
+{
+ _debugfs_apply_options(sb, true);
}
static int debugfs_remount(struct super_block *sb, int *flags, char *data)
@@ -175,7 +198,7 @@ static int debugfs_remount(struct super_block *sb, int *flags, char *data)
if (err)
goto fail;
- debugfs_apply_options(sb);
+ debugfs_apply_options_remount(sb);
fail:
return err;