Linux filesystem development
 help / color / mirror / Atom feed
From: Jingbo Xu <jefflexu@linux.alibaba.com>
To: miklos@szeredi.hu, linux-fsdevel@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, winters.zc@antgroup.com
Subject: [RFC 2/2] fuse: uid-based security enhancement for the recovery mechanism
Date: Fri, 24 May 2024 14:40:30 +0800	[thread overview]
Message-ID: <20240524064030.4944-3-jefflexu@linux.alibaba.com> (raw)
In-Reply-To: <20240524064030.4944-1-jefflexu@linux.alibaba.com>

Offer a uid-based security enhancement for the fuse server recovery
mechanism.  Otherwise any malicious attacker could kill the fuse server
and take the filesystem service over with the recovery mechanism.

Introduce a new "rescue_uid=" mount option specifying the expected uid
of the legal process running the fuse server.  Then only the process
with the matching uid is permissible to retrieve the fuse connection
with the server recovery mechanism.

Signed-off-by: Jingbo Xu <jefflexu@linux.alibaba.com>
---
 fs/fuse/dev.c    | 12 ++++++++++++
 fs/fuse/fuse_i.h |  8 ++++++++
 fs/fuse/inode.c  | 13 ++++++++++++-
 3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 7599138baac0..9db35a2bbd85 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -2376,12 +2376,24 @@ static long fuse_dev_ioctl_backing_close(struct file *file, __u32 __user *argp)
 	return fuse_backing_close(fud->fc, backing_id);
 }
 
+static inline bool fuse_device_attach_permissible(struct fuse_conn *fc)
+{
+	const struct cred *cred = current_cred();
+
+	return (uid_eq(cred->euid, fc->rescue_uid) &&
+		uid_eq(cred->suid, fc->rescue_uid) &&
+		uid_eq(cred->uid,  fc->rescue_uid));
+}
+
 static inline bool fuse_device_attach_match(struct fuse_conn *fc,
 					    const char *tag)
 {
 	if (!fc->recovery)
 		return false;
 
+	if (!fuse_device_attach_permissible(fc))
+		return false;
+
 	return !strncmp(fc->tag, tag, FUSE_TAG_NAME_MAX);
 }
 
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index e9832186f84f..c43026d7229c 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -560,6 +560,7 @@ struct fuse_fs_context {
 	unsigned int rootmode;
 	kuid_t user_id;
 	kgid_t group_id;
+	kuid_t rescue_uid;
 	bool is_bdev:1;
 	bool fd_present:1;
 	bool rootmode_present:1;
@@ -571,6 +572,7 @@ struct fuse_fs_context {
 	bool no_control:1;
 	bool no_force_umount:1;
 	bool legacy_opts_show:1;
+	bool rescue_uid_present:1;
 	enum fuse_dax_mode dax_mode;
 	unsigned int max_read;
 	unsigned int blksize;
@@ -616,6 +618,9 @@ struct fuse_conn {
 	/** The group id for this mount */
 	kgid_t group_id;
 
+	/* The expected user id of the fuse server */
+	kuid_t rescue_uid;
+
 	/** The pid namespace for this mount */
 	struct pid_namespace *pid_ns;
 
@@ -864,6 +869,9 @@ struct fuse_conn {
 	/** Support for fuse server recovery */
 	unsigned int recovery:1;
 
+	/** Is rescue_uid specified? */
+	unsigned int rescue_uid_present:1;
+
 	/** Maximum stack depth for passthrough backing files */
 	int max_stack_depth;
 
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 1ab245d6ade3..3b00482293b6 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -734,6 +734,7 @@ enum {
 	OPT_MAX_READ,
 	OPT_BLKSIZE,
 	OPT_TAG,
+	OPT_RESCUE_UID,
 	OPT_ERR
 };
 
@@ -749,6 +750,7 @@ static const struct fs_parameter_spec fuse_fs_parameters[] = {
 	fsparam_u32	("blksize",		OPT_BLKSIZE),
 	fsparam_string	("subtype",		OPT_SUBTYPE),
 	fsparam_string	("tag",			OPT_TAG),
+	fsparam_u32	("rescue_uid",		OPT_RESCUE_UID),
 	{}
 };
 
@@ -841,6 +843,13 @@ static int fuse_parse_param(struct fs_context *fsc, struct fs_parameter *param)
 		param->string = NULL;
 		return 0;
 
+	case OPT_RESCUE_UID:
+		ctx->rescue_uid = make_kuid(fsc->user_ns, result.uint_32);
+		if (!uid_valid(ctx->rescue_uid))
+			return invalfc(fsc, "Invalid rescue_uid");
+		ctx->rescue_uid_present = true;
+		break;
+
 	default:
 		return -EINVAL;
 	}
@@ -1344,7 +1353,7 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args,
 			}
 			if (flags & FUSE_NO_EXPORT_SUPPORT)
 				fm->sb->s_export_op = &fuse_export_fid_operations;
-			if (flags & FUSE_HAS_RECOVERY)
+			if (flags & FUSE_HAS_RECOVERY && fc->rescue_uid_present)
 				fc->recovery = 1;
 		} else {
 			ra_pages = fc->max_read / PAGE_SIZE;
@@ -1753,6 +1762,8 @@ int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
 	fc->destroy = ctx->destroy;
 	fc->no_control = ctx->no_control;
 	fc->no_force_umount = ctx->no_force_umount;
+	fc->rescue_uid = ctx->rescue_uid;
+	fc->rescue_uid_present = ctx->rescue_uid_present;
 	fc->tag = ctx->tag;
 	ctx->tag = NULL;
 
-- 
2.19.1.6.gb485710b


  parent reply	other threads:[~2024-05-24  6:40 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-24  6:40 [RFC 0/2] fuse: introduce fuse server recovery mechanism Jingbo Xu
2024-05-24  6:40 ` [RFC 1/2] fuse: introduce recovery mechanism for fuse server Jingbo Xu
2024-05-24  6:40 ` Jingbo Xu [this message]
2024-05-27 15:16 ` [RFC 0/2] fuse: introduce fuse server recovery mechanism Miklos Szeredi
2024-05-28  2:45   ` Jingbo Xu
2024-05-28  3:08     ` Jingbo Xu
2024-05-28  4:02       ` Gao Xiang
2024-05-28  8:43         ` Christian Brauner
2024-05-28  9:13           ` Gao Xiang
2024-05-28  9:32             ` Christian Brauner
2024-05-28  9:58               ` Gao Xiang
2024-05-28  7:46       ` Miklos Szeredi
2024-05-28  7:45     ` Miklos Szeredi
2024-05-28  8:38 ` Christian Brauner
2024-05-28  9:45   ` Jingbo Xu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240524064030.4944-3-jefflexu@linux.alibaba.com \
    --to=jefflexu@linux.alibaba.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=winters.zc@antgroup.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox