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

Reply via email to