9pfs: local: Add support for custom fmode/dmode in 9ps mapped security modes
In mapped security modes, files are created with very restrictive
permissions (600 for files and 700 for directories). This makes
file sharing between virtual machines and users on the host rather
complicated. Imagine eg. a group of users that need to access data
produced by processes on a virtual machine. Giving those users access
to the data will be difficult since the group access mode is always 0.
This patch makes the default mode for both files and directories
configurable. Existing setups that don't know about the new parameters
keep using the current secure behavior.
Signed-off-by: Tobias Schramm <tobleminer@gmail.com>
Signed-off-by: Greg Kurz <groug@kaod.org>
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index 83952ef..6e478f4 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -633,7 +633,7 @@
if (fs_ctx->export_flags & V9FS_SM_MAPPED ||
fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
- err = mknodat(dirfd, name, SM_LOCAL_MODE_BITS | S_IFREG, 0);
+ err = mknodat(dirfd, name, fs_ctx->fmode | S_IFREG, 0);
if (err == -1) {
goto out;
}
@@ -685,7 +685,7 @@
if (fs_ctx->export_flags & V9FS_SM_MAPPED ||
fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
- err = mkdirat(dirfd, name, SM_LOCAL_DIR_MODE_BITS);
+ err = mkdirat(dirfd, name, fs_ctx->dmode);
if (err == -1) {
goto out;
}
@@ -786,7 +786,7 @@
/* Determine the security model */
if (fs_ctx->export_flags & V9FS_SM_MAPPED ||
fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
- fd = openat_file(dirfd, name, flags, SM_LOCAL_MODE_BITS);
+ fd = openat_file(dirfd, name, flags, fs_ctx->fmode);
if (fd == -1) {
goto out;
}
@@ -849,7 +849,7 @@
ssize_t oldpath_size, write_size;
fd = openat_file(dirfd, name, O_CREAT | O_EXCL | O_RDWR,
- SM_LOCAL_MODE_BITS);
+ fs_ctx->fmode);
if (fd == -1) {
goto out;
}
@@ -1467,6 +1467,23 @@
return -1;
}
+ if (fse->export_flags & V9FS_SM_MAPPED ||
+ fse->export_flags & V9FS_SM_MAPPED_FILE) {
+ fse->fmode =
+ qemu_opt_get_number(opts, "fmode", SM_LOCAL_MODE_BITS) & 0777;
+ fse->dmode =
+ qemu_opt_get_number(opts, "dmode", SM_LOCAL_DIR_MODE_BITS) & 0777;
+ } else {
+ if (qemu_opt_find(opts, "fmode")) {
+ error_report("fmode is only valid for mapped 9p modes");
+ return -1;
+ }
+ if (qemu_opt_find(opts, "dmode")) {
+ error_report("dmode is only valid for mapped 9p modes");
+ return -1;
+ }
+ }
+
fse->path = g_strdup(path);
return 0;
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 96d2683..a0ae98f 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -3533,6 +3533,9 @@
s->ops = fse->ops;
+ s->ctx.fmode = fse->fmode;
+ s->ctx.dmode = fse->dmode;
+
s->fid_list = NULL;
qemu_co_rwlock_init(&s->rename_lock);