We are automatically generating some socket paths for domains, but all
those paths end up in a directory that's the same for multiple domains.
The problem is that multiple domains can each run with different
seclabels (users, selinux contexts, etc.). The idea here is to create a
per-domain directory labelled in a way that each domain can access its
own unix sockets.
Resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=1146886
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
src/qemu/qemu_command.c | 2 +-
src/qemu/qemu_domain.c | 17 ++++-----
src/qemu/qemu_process.c | 43 +++++++++++++++++++++-
.../qemuxml2argv-channel-virtio-unix.args | 7 ++--
4 files changed, 54 insertions(+), 15 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 5a92ad4b2edb..2a0e4aceb9af 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -8045,7 +8045,7 @@ qemuBuildGraphicsVNCCommandLine(virQEMUDriverConfigPtr cfg,
if (graphics->data.vnc.socket || cfg->vncAutoUnixSocket) {
if (!graphics->data.vnc.socket &&
virAsprintf(&graphics->data.vnc.socket,
- "%s/%s.vnc", cfg->libDir, def->name) == -1)
+ "%s/domain-%s/vnc.sock", cfg->libDir, def->name)
== -1)
goto error;
virBufferAsprintf(&opt, "unix:%s", graphics->data.vnc.socket);
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 84e5fa530cba..7dae93bc477c 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1307,17 +1307,14 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
goto cleanup;
}
- if (dev->data.chr->target.name) {
- if (virAsprintf(&dev->data.chr->source.data.nix.path,
"%s/%s.%s",
- cfg->channelTargetDir,
- def->name, dev->data.chr->target.name) < 0)
- goto cleanup;
- } else {
- if (virAsprintf(&dev->data.chr->source.data.nix.path,
"%s/%s",
- cfg->channelTargetDir, def->name) < 0)
- goto cleanup;
- }
+ if (virAsprintf(&dev->data.chr->source.data.nix.path,
+ "%s/domain-%s/%s",
+ cfg->channelTargetDir, def->name,
+ dev->data.chr->target.name ?
dev->data.chr->target.name
+ : "unknown.sock") < 0)
+ goto cleanup;
+ dev->data.chr->source.data.nix.autopath = true;
dev->data.chr->source.data.nix.listen = true;
}
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 505778ec2f05..4d2670b1bdc0 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3264,10 +3264,14 @@ qemuProcessPrepareMonitorChr(virQEMUDriverConfigPtr cfg,
{
monConfig->type = VIR_DOMAIN_CHR_TYPE_UNIX;
monConfig->data.nix.listen = true;
+ monConfig->data.nix.autopath = true;
- if (virAsprintf(&monConfig->data.nix.path, "%s/%s.monitor",
+ if (virAsprintf(&monConfig->data.nix.path,
"%s/domain-%s/monitor.sock",
cfg->libDir, vm) < 0)
return -1;
+
+ monConfig->data.nix.autopath = true;
+
return 0;
}
@@ -4389,6 +4393,7 @@ int qemuProcessStart(virConnectPtr conn,
unsigned int hostdev_flags = 0;
size_t nnicindexes = 0;
int *nicindexes = NULL;
+ char *tmppath = NULL;
VIR_DEBUG("vm=%p name=%s id=%d asyncJob=%d migrateFrom=%s stdin_fd=%d "
"stdin_path=%s snapshot=%p vmop=%d flags=0x%x",
@@ -4725,6 +4730,22 @@ int qemuProcessStart(virConnectPtr conn,
&nnicindexes, &nicindexes)))
goto cleanup;
+ /*
+ * Create all per-domain directories in order to make sure domain
+ * with any possible seclabels can access it.
+ */
+ if (virAsprintf(&tmppath, "%s/domain-%s",
+ cfg->libDir, vm->def->name) < 0 ||
+ virFileMakePath(tmppath) < 0)
+ goto cleanup;
+ VIR_FREE(tmppath);
+
+ if (virAsprintf(&tmppath, "%s/domain-%s",
+ cfg->channelTargetDir, vm->def->name) < 0 ||
+ virFileMakePath(tmppath) < 0)
+ goto cleanup;
+ VIR_FREE(tmppath);
+
/* now that we know it is about to start call the hook if present */
if (virHookPresent(VIR_HOOK_DRIVER_QEMU)) {
char *xml = qemuDomainDefFormatXML(driver, vm->def, 0);
@@ -4861,6 +4882,12 @@ int qemuProcessStart(virConnectPtr conn,
vm->def, stdin_path) < 0)
goto cleanup;
+ VIR_DEBUG("Setting additional domain security label for monitor socket");
+ if (virSecurityManagerSetChardevLabel(driver->securityManager,
+ vm->def, NULL,
+ priv->monConfig) < 0)
+ goto cleanup;
+
/* Security manager labeled all devices, therefore
* if any operation from now on fails and we goto cleanup,
* where virSecurityManagerRestoreAllLabel() is called
@@ -5078,6 +5105,7 @@ int qemuProcessStart(virConnectPtr conn,
/* We jump here if we failed to start the VM for any reason, or
* if we failed to initialize the now running VM. kill it off and
* pretend we never started it */
+ VIR_FREE(tmppath);
VIR_FREE(nodeset);
virCommandFree(cmd);
VIR_FORCE_CLOSE(logfile);
@@ -5140,6 +5168,7 @@ void qemuProcessStop(virQEMUDriverPtr driver,
size_t i;
int logfile = -1;
char *timestamp;
+ char *tmppath = NULL;
char ebuf[1024];
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
@@ -5230,6 +5259,18 @@ void qemuProcessStop(virQEMUDriverPtr driver,
priv->monConfig = NULL;
}
+ ignore_value(virAsprintf(&tmppath, "%s/domain-%s",
+ cfg->libDir, vm->def->name));
+ if (tmppath)
+ virFileDeleteTree(tmppath);
+ VIR_FREE(tmppath);
+
+ ignore_value(virAsprintf(&tmppath, "%s/domain-%s",
+ cfg->channelTargetDir, vm->def->name));
+ if (tmppath)
+ virFileDeleteTree(tmppath);
+ VIR_FREE(tmppath);
+
ignore_value(virDomainChrDefForeach(vm->def,
false,
qemuProcessCleanupChardevDevice,
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-unix.args
b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-unix.args
index 43a34ced80ed..289b9d700b15 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-unix.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-unix.args
@@ -9,11 +9,12 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test
QEMU_AUDIO_DRV=none \
-usb \
-hda /dev/HostVG/QEMUGuest1 \
-chardev socket,id=charchannel0,path=\
-/tmp/QEMUGuest1.org.qemu.guest_agent.0,server,nowait \
+/tmp/domain-QEMUGuest1/org.qemu.guest_agent.0,server,nowait \
-device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,\
name=org.qemu.guest_agent.0 \
--chardev socket,id=charchannel1,path=/tmp/QEMUGuest1,server,nowait \
+-chardev \
+socket,id=charchannel1,path=/tmp/domain-QEMUGuest1/unknown.sock,server,nowait \
-device virtserialport,bus=virtio-serial0.0,nr=2,chardev=charchannel1,id=channel1 \
--chardev socket,id=charchannel2,path=/tmp/QEMUGuest1.ble,server,nowait \
+-chardev socket,id=charchannel2,path=/tmp/domain-QEMUGuest1/ble,server,nowait \
-device virtserialport,bus=virtio-serial0.0,nr=3,chardev=charchannel2,id=channel2,\
name=ble
--
2.5.0