On 8/13/21 11:36 PM, Jim Fehlig wrote:
Attaching a newly created vhostuser port to a VM fails due to an
apparmor denial
internal error: unable to execute QEMU command 'chardev-add': Failed
to bind socket to /run/openvswitch/vhu838c4d29-c9: Permission denied
In the case of a net device type VIR_DOMAIN_NET_TYPE_VHOSTUSER, the
underlying chardev is not labeled in qemuDomainAttachNetDevice prior
to calling qemuMonitorAttachCharDev. Label the chardev before calling
qemuMonitorAttachCharDev, and restore the label when removing the
net device.
Signed-off-by: Jim Fehlig <jfehlig(a)suse.com>
---
src/qemu/qemu_hotplug.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index c00e8a7852..42e7997112 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1467,6 +1467,11 @@ qemuDomainAttachNetDevice(virQEMUDriver *driver,
}
if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
+ virDomainChrDef chr = { .source = net->data.vhostuser };
+
+ if (qemuSecuritySetChardevLabel(driver, vm, &chr) < 0)
+ goto cleanup;
+
if (qemuMonitorAttachCharDev(priv->mon, charDevAlias, net->data.vhostuser)
< 0) {
ignore_value(qemuDomainObjExitMonitor(driver, vm));
virDomainAuditNet(vm, NULL, net, "attach", false);
@@ -4692,6 +4697,8 @@ qemuDomainRemoveNetDevice(virQEMUDriver *driver,
}
if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
+ virDomainChrDef chr = { .source = net->data.vhostuser };
+
/* vhostuser has a chardev too */
if (qemuMonitorDetachCharDev(priv->mon, charDevAlias) < 0) {
/* well, this is a messy situation. Guest visible PCI device has
@@ -4699,6 +4706,8 @@ qemuDomainRemoveNetDevice(virQEMUDriver *driver,
* to just ignore the error and carry on.
*/
}
+ if (qemuSecurityRestoreChardevLabel(driver, vm, &chr) < 0)
+ VIR_WARN("Unable to restore security label on vhostuser char
device");
} else if (actualType == VIR_DOMAIN_NET_TYPE_VDPA) {
int vdpafdset = -1;
g_autoptr(qemuMonitorFdsets) fdsets = NULL;
What an interesting bug. Previously we assumed that the UNIX socket is
created with broad enough permissions so that QEMU can connect to it. I
mean, when a VM is starting up nor DAC nor SELinux drivers care about
VHOSTUSER. It's AppArmor driver that cares. And it makes sense.
But, what's problematic here is that upon attach the socket perms will
be changed (because both DAC and SELinux drivers implement
domainSetSecurityChardevLabel callback). And since sockets can't have
XATTRs libvirt won't remember its original labels and thus subsequent
restore changes owner to root:root.
So I think we should address this inconsistency in behavior. But I don't
know how :-(
Also, looking at the code itself - please move qemuSecurity* calls
outside of the monitor code. I mean, qemuDomainAttachNetDevice() has a
section that prepares interfaces before calling
qemuDomainObjEnterMonitor(). That looks like a better place to call
qemuSecuritySetChardevLabel(). Similarly, the restore in detach path
should be done outside of monitor handling code.
Oh, a side note - don't forget that hotplug can fail and thus the
seclabel should be restored if it was set. If you want to look around
for inspiration, we usually use teardownlabel variable for that.
Michal