From: Christian Schoenebeck <qemu_oss@crudebyte.com>
To: qemu-devel@nongnu.org
Cc: Andrey Erokhin <language.lawyer@gmail.com>, Greg Kurz <groug@kaod.org>
Subject: Re: [RFC PATCH] virtfs: 9p: local: add default uid and gid options
Date: Wed, 11 Feb 2026 15:07:06 +0100 [thread overview]
Message-ID: <12835278.O9o76ZdvQC@weasel> (raw)
In-Reply-To: <5e904364-240a-4853-ad28-b2e3c5ac8f83@gmail.com>
On Tuesday, 10 February 2026 10:45:09 CET Andrey Erokhin wrote:
> On 30/01/2026 19:30, Christian Schoenebeck wrote:
> > On Wednesday, 28 January 2026 20:13:45 CET Andrey Erokhin wrote:
> >>> I was trying to boot from a directory tree owned by an ordinary user,
> >>> and some daemons weren't happy about non-root ownership of some files
> >>>
> >>> Example use:
> >>> -virtfs
> >>> local,path=rootfs,mount_tag=root,security_model=mapped,uid=0,gid=0
> >>
> >> I personally switched from fuse-overlayfs to user namespaces+kernel
> >> overlay
> >> fs (for writeable overlay for rootfs) long time ago, so I do not need
> >> uid=0,gid=0, I'm being mapped to 0:0 in the user namespace. I wanted to
> >> publish this change to support users which can't use user namespaces, but
> >> yesterday I realized I could just run QEMU (with fuse-overlayfs) under
> >> fakeroot 🤦♂️
> >
> > Nevertheless you already came more than half way to finish this. All it
> > would take is adding some lines to the command line docs.
> Do you mean smth. like this?
Yes, but you know the drill: top post as v2, please.
> (BTW, is it OK that there is no fmode/dmode processing in system/vl.c?)
You mean error handling of these options. Well, earlier error handling on one
hand might be more desirable, but OTOH it might also be more complicated to be
handled in vl.c than either in 9p.c or 9p-local.c I guess.
/Christian
>
> ---
> fsdev/file-op-9p.h | 4 ++++
> fsdev/qemu-fsdev-opts.c | 12 ++++++++++++
> fsdev/qemu-fsdev.c | 2 ++
> hw/9pfs/9p-local.c | 25 +++++++++++++++++++++++++
> hw/9pfs/9p.c | 2 ++
> qemu-options.hx | 24 ++++++++++++++++++++----
> system/vl.c | 9 +++++++++
> 7 files changed, 74 insertions(+), 4 deletions(-)
>
> diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
> index b9dae8c84c..10f3a7270c 100644
> --- a/fsdev/file-op-9p.h
> +++ b/fsdev/file-op-9p.h
> @@ -94,6 +94,8 @@ typedef struct FsDriverEntry {
> FsThrottle fst;
> mode_t fmode;
> mode_t dmode;
> + uid_t dflt_uid;
> + gid_t dflt_gid;
> } FsDriverEntry;
>
> struct FsContext {
> @@ -107,6 +109,8 @@ struct FsContext {
> void *private;
> mode_t fmode;
> mode_t dmode;
> + uid_t dflt_uid;
> + gid_t dflt_gid;
> };
>
> struct V9fsPath {
> diff --git a/fsdev/qemu-fsdev-opts.c b/fsdev/qemu-fsdev-opts.c
> index 07a18c6e48..c99abb3de6 100644
> --- a/fsdev/qemu-fsdev-opts.c
> +++ b/fsdev/qemu-fsdev-opts.c
> @@ -46,6 +46,12 @@ static QemuOptsList qemu_fsdev_opts = {
> }, {
> .name = "dmode",
> .type = QEMU_OPT_NUMBER,
> + }, {
> + .name = "uid",
> + .type = QEMU_OPT_NUMBER,
> + }, {
> + .name = "gid",
> + .type = QEMU_OPT_NUMBER,
> },
>
> THROTTLE_OPTS,
> @@ -92,6 +98,12 @@ static QemuOptsList qemu_virtfs_opts = {
> }, {
> .name = "dmode",
> .type = QEMU_OPT_NUMBER,
> + }, {
> + .name = "uid",
> + .type = QEMU_OPT_NUMBER,
> + }, {
> + .name = "gid",
> + .type = QEMU_OPT_NUMBER,
> },
>
> { /*End of list */ }
> diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
> index 57877dad0a..faa84dc033 100644
> --- a/fsdev/qemu-fsdev.c
> +++ b/fsdev/qemu-fsdev.c
> @@ -58,6 +58,8 @@ static FsDriverTable FsDrivers[] = {
> "writeout",
> "fmode",
> "dmode",
> + "uid",
> + "gid",
> "multidevs",
> "throttling.bps-total",
> "throttling.bps-read",
> diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
> index 5ce97b76a6..f20b1c5d1a 100644
> --- a/hw/9pfs/9p-local.c
> +++ b/hw/9pfs/9p-local.c
> @@ -198,6 +198,12 @@ static int local_lstat(FsContext *fs_ctx, V9fsPath
> *fs_path, struct stat *stbuf) if (err) {
> goto err_out;
> }
> + if (fs_ctx->dflt_uid != -1) {
> + stbuf->st_uid = fs_ctx->dflt_uid;
> + }
> + if (fs_ctx->dflt_gid != -1) {
> + stbuf->st_gid = fs_ctx->dflt_gid;
> + }
> if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
> /* Actual credentials are part of extended attrs */
> uid_t tmp_uid;
> @@ -788,6 +794,12 @@ static int local_fstat(FsContext *fs_ctx, int fid_type,
> if (err) {
> return err;
> }
> + if (fs_ctx->dflt_uid != -1) {
> + stbuf->st_uid = fs_ctx->dflt_uid;
> + }
> + if (fs_ctx->dflt_gid != -1) {
> + stbuf->st_gid = fs_ctx->dflt_gid;
> + }
> if (fs_ctx->export_flags & V9FS_SM_MAPPED) {
> /* Actual credentials are part of extended attrs */
> uid_t tmp_uid;
> @@ -1587,6 +1599,19 @@ static int local_parse_opts(QemuOpts *opts,
> FsDriverEntry *fse, Error **errp) }
> }
>
> + if (fse->export_flags & V9FS_SM_PASSTHROUGH) {
> + if (qemu_opt_find(opts, "uid")) {
> + error_setg(errp, "uid is invalid in the passthrough security
> mode"); + return -1;
> + }
> + if (qemu_opt_find(opts, "gid")) {
> + error_setg(errp, "gid is invalid in the passthrough security
> mode"); + return -1;
> + }
> + }
> + fse->dflt_uid = qemu_opt_get_number(opts, "uid", -1);
> + fse->dflt_gid = qemu_opt_get_number(opts, "gid", -1);
> +
> fse->path = g_strdup(path);
>
> return 0;
> diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
> index acfa7db4e1..492379d361 100644
> --- a/hw/9pfs/9p.c
> +++ b/hw/9pfs/9p.c
> @@ -4317,6 +4317,8 @@ int v9fs_device_realize_common(V9fsState *s, const
> V9fsTransport *t,
>
> s->ctx.fmode = fse->fmode;
> s->ctx.dmode = fse->dmode;
> + s->ctx.dflt_uid = fse->dflt_uid;
> + s->ctx.dflt_gid = fse->dflt_gid;
>
> s->fids = g_hash_table_new(NULL, NULL);
> qemu_co_rwlock_init(&s->rename_lock);
> diff --git a/qemu-options.hx b/qemu-options.hx
> index ab23f14d21..84f108d9ad 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -1806,7 +1806,7 @@ ERST
>
> DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev,
> "-fsdev
> local,id=id,path=path,security_model=mapped-xattr|mapped-file|passthrough|n
> one\n" - "
> [,writeout=immediate][,readonly=on][,fmode=fmode][,dmode=dmode]\n" + "
> [,writeout=immediate][,readonly=on][,fmode=fmode][,dmode=dmode][,uid=uid][,
> gid=gid]\n" "
> [[,throttling.bps-total=b]|[[,throttling.bps-read=r][,throttling.bps-write=
> w]]]\n" "
> [[,throttling.iops-total=i]|[[,throttling.iops-read=r][,throttling.iops-wri
> te=w]]]\n" "
> [[,throttling.bps-total-max=bm]|[[,throttling.bps-read-max=rm][,throttling.
> bps-write-max=wm]]]\n" @@ -1816,7 +1816,7 @@ DEF("fsdev", HAS_ARG,
> QEMU_OPTION_fsdev,
> QEMU_ARCH_ALL)
>
> SRST
> -``-fsdev local,id=id,path=path,security_model=security_model
> [,writeout=writeout][,readonly=on][,fmode=fmode][,dmode=dmode]
> [,throttling.option=value[,throttling.option=value[,...]]]`` +``-fsdev
> local,id=id,path=path,security_model=security_model
> [,writeout=writeout][,readonly=on][,fmode=fmode][,dmode=dmode][,uid=uid][,g
> id=gid] [,throttling.option=value[,throttling.option=value[,...]]]`` \
> ``-fsdev synth,id=id[,readonly=on]``
> Define a new file system device. Valid options are:
> @@ -1870,6 +1870,14 @@ SRST
> host. Works only with security models "mapped-xattr" and
> "mapped-file".
>
> + ``uid=uid``
> + Specifies the default uid for files and directories. Works with
> + security models "mapped-xattr", "mapped-file" and "none".
> +
> + ``gid=gid``
> + Specifies the default gid for files and directories. Works with
> + security models "mapped-xattr", "mapped-file" and "none".
> +
> ``throttling.bps-total=b,throttling.bps-read=r,throttling.bps-write=w``
> Specify bandwidth throttling limits in bytes per second, either for all
> request types or for reads or writes only.
> @@ -1911,12 +1919,12 @@ ERST
>
> DEF("virtfs", HAS_ARG, QEMU_OPTION_virtfs,
> "-virtfs
> local,path=path,mount_tag=tag,security_model=mapped-xattr|mapped-file|passt
> hrough|none\n" - "
> [,id=id][,writeout=immediate][,readonly=on][,fmode=fmode][,dmode=dmode][,mu
> ltidevs=remap|forbid|warn]\n" + "
> [,id=id][,writeout=immediate][,readonly=on][,fmode=fmode][,dmode=dmode][,ui
> d=uid][,gid=gid][,multidevs=remap|forbid|warn]\n" "-virtfs
> synth,mount_tag=tag[,id=id][,readonly=on]\n",
> QEMU_ARCH_ALL)
>
> SRST
> -``-virtfs local,path=path,mount_tag=mount_tag
> ,security_model=security_model[,writeout=writeout][,readonly=on]
> [,fmode=fmode][,dmode=dmode][,multidevs=multidevs]`` +``-virtfs
> local,path=path,mount_tag=mount_tag
> ,security_model=security_model[,writeout=writeout][,readonly=on]
> [,fmode=fmode][,dmode=dmode][,uid=uid][,gid=gid][,multidevs=multidevs]`` \
> ``-virtfs synth,mount_tag=mount_tag``
> Define a new virtual filesystem device and expose it to the guest using
> @@ -1980,6 +1988,14 @@ SRST
> host. Works only with security models "mapped-xattr" and
> "mapped-file".
>
> + ``uid=uid``
> + Specifies the default uid for files and directories. Works with
> + security models "mapped-xattr", "mapped-file" and "none".
> +
> + ``gid=gid``
> + Specifies the default gid for files and directories. Works with
> + security models "mapped-xattr", "mapped-file" and "none".
> +
> ``mount_tag=mount_tag``
> Specifies the tag name to be used by the guest to mount this
> export point.
> diff --git a/system/vl.c b/system/vl.c
> index 3b7057e6c6..d363b046a6 100644
> --- a/system/vl.c
> +++ b/system/vl.c
> @@ -3253,6 +3253,7 @@ void qemu_init(int argc, char **argv)
> QemuOpts *fsdev;
> QemuOpts *device;
> const char *writeout, *sock_fd, *socket, *path,
> *security_model, + *uid, *gid,
> *multidevs;
>
> olist = qemu_find_opts("virtfs");
> @@ -3301,6 +3302,14 @@ void qemu_init(int argc, char **argv)
> qemu_opt_set(fsdev, "security_model", security_model,
> &error_abort);
> }
> + uid = qemu_opt_get(opts, "uid");
> + if (uid) {
> + qemu_opt_set(fsdev, "uid", uid, &error_abort);
> + }
> + gid = qemu_opt_get(opts, "gid");
> + if (gid) {
> + qemu_opt_set(fsdev, "gid", gid, &error_abort);
> + }
> socket = qemu_opt_get(opts, "socket");
> if (socket) {
> qemu_opt_set(fsdev, "socket", socket, &error_abort);
> --
next prev parent reply other threads:[~2026-02-11 14:09 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-01 18:00 [RFC PATCH] virtfs: 9p: local: add default uid and gid options Andrey Erokhin
2025-12-03 10:33 ` Christian Schoenebeck
2025-12-06 17:10 ` Andrey Erokhin
2025-12-07 11:34 ` Warner Losh
2025-12-09 10:21 ` Christian Schoenebeck
2025-12-09 10:38 ` Warner Losh
2026-01-28 19:13 ` Andrey Erokhin
2026-01-30 14:30 ` Christian Schoenebeck
2026-02-10 9:45 ` Andrey Erokhin
2026-02-11 14:07 ` Christian Schoenebeck [this message]
2026-02-13 21:53 ` Andrey Erokhin
2026-02-16 8:51 ` Christian Schoenebeck
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=12835278.O9o76ZdvQC@weasel \
--to=qemu_oss@crudebyte.com \
--cc=groug@kaod.org \
--cc=language.lawyer@gmail.com \
--cc=qemu-devel@nongnu.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.