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 Works with any security_model Signed-off-by: Andrey Erokhin <[email protected]> --- fsdev/file-op-9p.h | 5 +++++ fsdev/qemu-fsdev-opts.c | 12 ++++++++++++ fsdev/qemu-fsdev.c | 2 ++ hw/9pfs/9p-local.c | 15 +++++++++++++++ hw/9pfs/9p.c | 2 ++ system/vl.c | 9 +++++++++ 6 files changed, 45 insertions(+) diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h index b9dae8c84c..46fb88001e 100644 --- a/fsdev/file-op-9p.h +++ b/fsdev/file-op-9p.h @@ -15,6 +15,7 @@ #define FILE_OP_9P_H #include <dirent.h> +#include <sys/types.h> #include <utime.h> #include "qemu-fsdev-throttle.h" #include "p9array.h" @@ -94,6 +95,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 +110,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..cecf4aa50c 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; @@ -1570,6 +1582,9 @@ static int local_parse_opts(QemuOpts *opts, FsDriverEntry *fse, Error **errp) return -1; } + fse->dflt_uid = qemu_opt_get_number(opts, "uid", -1); + fse->dflt_gid = qemu_opt_get_number(opts, "gid", -1); + if (fse->export_flags & V9FS_SM_MAPPED || fse->export_flags & V9FS_SM_MAPPED_FILE) { fse->fmode = 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/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); -- 2.34.1
