public inbox for linux-fsdevel@vger.kernel.org
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <djwong@kernel.org>
To: bschubert@ddn.com
Cc: linux-fsdevel@vger.kernel.org, bernd@bsbernd.com,
	miklos@szeredi.hu, neal@gompa.dev, joannelkoong@gmail.com
Subject: Re: [PATCH 11/17] mount_service: use over the other non-root user checks
Date: Tue, 7 Apr 2026 16:47:45 -0700	[thread overview]
Message-ID: <20260407234745.GQ6202@frogsfrogsfrogs> (raw)
In-Reply-To: <177457463316.1008428.211933150228152448.stgit@frogsfrogsfrogs>

On Thu, Mar 26, 2026 at 06:27:38PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> Now that we've hoisted the code that checks non-root fuse mounts to a
> common file, make fuservicemount obey them too.
> 
> Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>

Codex pointed out quite a few setuid related problems in this patch that
I wasn't aware of.  Good for it!

The first is that I needed to wrap all the system calls that involve
access and permission checks with drop_privs() and restore_privs().
That way an unprivileged user cannot connect to fuse server sockets,
files, fuse devices, call block device ioctls, or mount() to places that
the original unprivileged user cannot access.

It also mentioned that we ought to call fuse_mnt_resolve_path to make
sure that the path mount point can be resolved with the real uid of the
mount helper process; this was fortunate, because that was also key to
enabling unmount if the fuse server initialization fails early on.

--D

> ---
>  util/mount_service.c |   62 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 62 insertions(+)
> 
> 
> diff --git a/util/mount_service.c b/util/mount_service.c
> index 9f6feab902f89d..6e53447e1d65be 100644
> --- a/util/mount_service.c
> +++ b/util/mount_service.c
> @@ -1224,6 +1224,30 @@ static int mount_service_fsopen_mount(struct mount_service *mo,
>  # define mount_service_fsopen_mount(...)	(-2)
>  #endif
>  
> +static int check_nonroot_file_access(const struct mount_service *mo)
> +{
> +	char buf[32];
> +	char *mntpt;
> +	int fd;
> +
> +	if (mo->mountfd >= 0) {
> +		snprintf(buf, sizeof(buf), "/dev/fd/%d", mo->mountfd);
> +		mntpt = buf;
> +	} else {
> +		mntpt = mo->mountpoint;
> +	}
> +
> +	fd = open(mntpt, O_WRONLY);
> +	if (fd < 0) {
> +		fprintf(stderr, "%s: user has no write access to mountpoint %s\n",
> +			mo->msgtag, mo->mountpoint);
> +		return -1;
> +	}
> +
> +	close(fd);
> +	return 0;
> +}
> +
>  static int mount_service_handle_mount_cmd(struct mount_service *mo,
>  					  struct fuse_service_packet *p)
>  {
> @@ -1298,6 +1322,44 @@ static int mount_service_handle_mount_cmd(struct mount_service *mo,
>  		return mount_service_send_reply(mo, EINVAL);
>  	}
>  
> +	/*
> +	 * fuse.conf can limit the number of unprivileged fuse mounts.
> +	 * For unprivileged mounts (via setuid) we also require write access
> +	 * to the mountpoint, and we'll only accept certain underlying
> +	 * filesystems.
> +	 */
> +	if (getuid() != 0) {
> +		struct statfs fs_buf;
> +
> +		ret = check_nonroot_mount_count(mo->msgtag);
> +		if (ret)
> +			return mount_service_send_reply(mo, ENOMEM);
> +
> +		ret = fstatfs(mo->mountfd, &fs_buf);
> +		if (ret) {
> +			int error = errno;
> +
> +			fprintf(stderr, "%s: %s: %s\n",
> +				mo->msgtag, mo->mountpoint, strerror(error));
> +			return mount_service_send_reply(mo, error);
> +		}
> +
> +		drop_privs();
> +		if (S_ISDIR(stbuf.st_mode))
> +			ret = check_nonroot_dir_access(mo->msgtag,
> +						       mo->mountpoint,
> +						       mo->real_mountpoint,
> +						       &stbuf);
> +		else
> +			ret = check_nonroot_file_access(mo);
> +		if (!ret)
> +			ret = check_nonroot_fstype(mo->msgtag, &fs_buf);
> +		restore_privs();
> +
> +		if (ret)
> +			return mount_service_send_reply(mo, EPERM);
> +	}
> +
>  	if (mo->fsopenfd >= 0) {
>  		ret = mount_service_fsopen_mount(mo, oc, &stbuf);
>  		if (ret != -2)
> 
> 

  reply	other threads:[~2026-04-07 23:47 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-27  1:24 [PATCHSET v3] libfuse: run fuse servers as a contained service Darrick J. Wong
2026-03-27  1:25 ` [PATCH 01/17] Refactor mount code / move common functions to mount_util.c Darrick J. Wong
2026-03-27  1:25 ` [PATCH 02/17] mount_service: add systemd/inetd socket service mounting helper Darrick J. Wong
2026-03-30 20:44   ` Bernd Schubert
2026-03-30 21:37     ` Darrick J. Wong
2026-04-07 23:39   ` Darrick J. Wong
2026-03-27  1:25 ` [PATCH 03/17] mount_service: create high level fuse helpers Darrick J. Wong
2026-03-30 19:37   ` Bernd Schubert
2026-03-30 20:30     ` Darrick J. Wong
2026-03-30 20:51       ` Bernd Schubert
2026-03-30 21:09         ` Darrick J. Wong
2026-03-27  1:25 ` [PATCH 04/17] mount_service: use the new mount api for the mount service Darrick J. Wong
2026-03-30 21:06   ` Bernd Schubert
2026-03-30 21:18     ` Darrick J. Wong
2026-03-30 21:40       ` Bernd Schubert
2026-03-30 21:47         ` Darrick J. Wong
2026-03-27  1:26 ` [PATCH 05/17] mount_service: update mtab after a successful mount Darrick J. Wong
2026-04-07 23:42   ` Darrick J. Wong
2026-03-27  1:26 ` [PATCH 06/17] util: hoist the fuse.conf parsing code Darrick J. Wong
2026-04-07 23:40   ` Darrick J. Wong
2026-03-27  1:26 ` [PATCH 07/17] util: fix checkpatch complaints in fuser_conf.[ch] Darrick J. Wong
2026-03-27  1:26 ` [PATCH 08/17] mount_service: read fuse.conf to enable allow_other for unprivileged mounts Darrick J. Wong
2026-03-27  1:27 ` [PATCH 09/17] util: hoist the other non-root user limits Darrick J. Wong
2026-03-27  1:27 ` [PATCH 10/17] util: fix more checkpatch complaints in fuser_conf.[ch] Darrick J. Wong
2026-03-27  1:27 ` [PATCH 11/17] mount_service: use over the other non-root user checks Darrick J. Wong
2026-04-07 23:47   ` Darrick J. Wong [this message]
2026-03-27  1:27 ` [PATCH 12/17] mount.fuse3: integrate systemd service startup Darrick J. Wong
2026-04-07 23:56   ` Darrick J. Wong
2026-03-27  1:28 ` [PATCH 13/17] mount_service: allow installation as a setuid program Darrick J. Wong
2026-03-27  1:28 ` [PATCH 14/17] example/service_ll: create a sample systemd service fuse server Darrick J. Wong
2026-04-08  0:09   ` Darrick J. Wong
2026-03-27  1:28 ` [PATCH 15/17] example/service: create a sample systemd service for a high-level " Darrick J. Wong
2026-03-27  1:28 ` [PATCH 16/17] example/hello_ll: port to single-file common code Darrick J. Wong
2026-03-27  1:29 ` [PATCH 17/17] nullfs: support fuse systemd service mode Darrick J. Wong
2026-04-08  0:11   ` Darrick J. Wong

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=20260407234745.GQ6202@frogsfrogsfrogs \
    --to=djwong@kernel.org \
    --cc=bernd@bsbernd.com \
    --cc=bschubert@ddn.com \
    --cc=joannelkoong@gmail.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=neal@gompa.dev \
    /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