virSecurityManagerRestoreImageLabel;
virSecurityManagerRestoreInputLabel;
virSecurityManagerRestoreMemoryLabel;
+virSecurityManagerRestoreNetdevLabel;
virSecurityManagerRestoreSavedStateLabel;
virSecurityManagerRestoreTPMLabels;
virSecurityManagerSetAllLabel;
virSecurityManagerSetImageLabel;
virSecurityManagerSetInputLabel;
virSecurityManagerSetMemoryLabel;
+virSecurityManagerSetNetdevLabel;
virSecurityManagerSetProcessLabel;
virSecurityManagerSetSavedStateLabel;
virSecurityManagerSetSocketLabel;
g_autofree char *netdev_name = NULL;
g_autoptr(virConnect) conn = NULL;
virErrorPtr save_err = NULL;
+ bool teardownlabel = false;
/* If appropriate, grab a physical device from the configured
* network's pool of devices, or resolve bridge device name
&net->ifname) < 0)
goto cleanup;
+ if (qemuSecuritySetNetdevLabel(driver, vm, net) < 0)
+ goto cleanup;
+ teardownlabel = true;
break;
case VIR_DOMAIN_NET_TYPE_USER:
qemuDomainNetDeviceVportRemove(net);
}
+ if (teardownlabel &&
+ qemuSecurityRestoreNetdevLabel(driver, vm, net) < 0)
+ VIR_WARN("Unable to restore network device labelling on hotplug fail");
+
/* we had potentially pre-added the device to the domain
* device lists, if so we need to remove it (from def->nets
* and/or def->hostdevs) on failure
cfg->stateDir));
}
+ if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
+ if (qemuSecurityRestoreNetdevLabel(driver, vm, net) < 0)
+ VIR_WARN("Unable to restore security label on vhostuser char device");
+ }
+
qemuDomainNetDeviceVportRemove(net);
if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
return ret;
}
+int
+qemuSecuritySetNetdevLabel(virQEMUDriver *driver,
+ virDomainObj *vm,
+ virDomainNetDef *net)
+{
+ int ret = -1;
+ qemuDomainObjPrivate *priv = vm->privateData;
+ pid_t pid = -1;
+
+ if (qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))
+ pid = vm->pid;
+
+ if (virSecurityManagerTransactionStart(driver->securityManager) < 0)
+ goto cleanup;
+
+ if (virSecurityManagerSetNetdevLabel(driver->securityManager,
+ vm->def, net) < 0)
+ goto cleanup;
+
+ if (virSecurityManagerTransactionCommit(driver->securityManager,
+ pid, priv->rememberOwner) < 0)
+ goto cleanup;
+
+ ret = 0;
+ cleanup:
+ virSecurityManagerTransactionAbort(driver->securityManager);
+ return ret;
+}
+
+
+int
+qemuSecurityRestoreNetdevLabel(virQEMUDriver *driver,
+ virDomainObj *vm,
+ virDomainNetDef *net)
+{
+ int ret = -1;
+ qemuDomainObjPrivate *priv = vm->privateData;
+ pid_t pid = -1;
+
+ if (qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))
+ pid = vm->pid;
+
+ if (virSecurityManagerTransactionStart(driver->securityManager) < 0)
+ goto cleanup;
+
+ if (virSecurityManagerRestoreNetdevLabel(driver->securityManager,
+ vm->def, net) < 0)
+ goto cleanup;
+
+ if (virSecurityManagerTransactionCommit(driver->securityManager,
+ pid, priv->rememberOwner) < 0)
+ goto cleanup;
+
+ ret = 0;
+ cleanup:
+ virSecurityManagerTransactionAbort(driver->securityManager);
+ return ret;
+}
+
/*
* qemuSecurityStartVhostUserGPU:
virDomainObj *vm,
virDomainChrDef *chr);
+int qemuSecuritySetNetdevLabel(virQEMUDriver *driver,
+ virDomainObj *vm,
+ virDomainNetDef *net);
+
+int qemuSecurityRestoreNetdevLabel(virQEMUDriver *driver,
+ virDomainObj *vm,
+ virDomainNetDef *net);
+
int qemuSecurityStartVhostUserGPU(virQEMUDriver *driver,
virDomainObj *vm,
virCommand *cmd,
return reload_profile(mgr, def, NULL, false);
}
+static int
+AppArmorSetNetdevLabel(virSecurityManager *mgr,
+ virDomainDef *def,
+ virDomainNetDef *net)
+{
+ int ret = -1;
+ virSecurityLabelDef *secdef;
+ virDomainChrSourceDef *dev_source;
+ virDomainNetType actualType;
+
+ secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_APPARMOR_NAME);
+ if (!secdef)
+ return 0;
+
+ actualType = virDomainNetGetActualType(net);
+ if (actualType != VIR_DOMAIN_NET_TYPE_VHOSTUSER)
+ return 0;
+
+ dev_source = net->data.vhostuser;
+ switch ((virDomainChrType)dev_source->type) {
+ case VIR_DOMAIN_CHR_TYPE_UNIX:
+ ret = reload_profile(mgr, def, dev_source->data.file.path, true);
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_DEV:
+ case VIR_DOMAIN_CHR_TYPE_FILE:
+ case VIR_DOMAIN_CHR_TYPE_PTY:
+ case VIR_DOMAIN_CHR_TYPE_PIPE:
+ case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
+ case VIR_DOMAIN_CHR_TYPE_NULL:
+ case VIR_DOMAIN_CHR_TYPE_VC:
+ case VIR_DOMAIN_CHR_TYPE_STDIO:
+ case VIR_DOMAIN_CHR_TYPE_UDP:
+ case VIR_DOMAIN_CHR_TYPE_TCP:
+ case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
+ case VIR_DOMAIN_CHR_TYPE_NMDM:
+ case VIR_DOMAIN_CHR_TYPE_LAST:
+ ret = 0;
+ break;
+ }
+
+ return ret;
+}
+
+static int
+AppArmorRestoreNetdevLabel(virSecurityManager *mgr,
+ virDomainDef *def,
+ virDomainNetDef *net G_GNUC_UNUSED)
+{
+ virSecurityLabelDef *secdef;
+
+ secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_APPARMOR_NAME);
+ if (!secdef)
+ return 0;
+
+ return reload_profile(mgr, def, NULL, false);
+}
+
static int
AppArmorSetPathLabel(virSecurityManager *mgr,
virDomainDef *def,
.domainSetSecurityChardevLabel = AppArmorSetChardevLabel,
.domainRestoreSecurityChardevLabel = AppArmorRestoreChardevLabel,
+ .domainSetSecurityNetdevLabel = AppArmorSetNetdevLabel,
+ .domainRestoreSecurityNetdevLabel = AppArmorRestoreNetdevLabel,
+
.domainSetSecurityImageFDLabel = AppArmorSetFDLabel,
.domainSetSecurityTapFDLabel = AppArmorSetFDLabel,
virDomainDef *def);
typedef int (*virSecurityDomainRestoreTPMLabels) (virSecurityManager *mgr,
virDomainDef *def);
+typedef int (*virSecurityDomainSetNetdevLabel) (virSecurityManager *mgr,
+ virDomainDef *def,
+ virDomainNetDef *net);
+typedef int (*virSecurityDomainRestoreNetdevLabel) (virSecurityManager *mgr,
+ virDomainDef *def,
+ virDomainNetDef *net);
struct _virSecurityDriver {
virSecurityDomainSetTPMLabels domainSetSecurityTPMLabels;
virSecurityDomainRestoreTPMLabels domainRestoreSecurityTPMLabels;
+
+ virSecurityDomainSetNetdevLabel domainSetSecurityNetdevLabel;
+ virSecurityDomainRestoreNetdevLabel domainRestoreSecurityNetdevLabel;
};
virSecurityDriver *virSecurityDriverLookup(const char *name,
}
+int
+virSecurityManagerSetNetdevLabel(virSecurityManager *mgr,
+ virDomainDef *vm,
+ virDomainNetDef *net)
+{
+ int ret;
+
+ if (mgr->drv->domainSetSecurityNetdevLabel) {
+ virObjectLock(mgr);
+ ret = mgr->drv->domainSetSecurityNetdevLabel(mgr, vm, net);
+ virObjectUnlock(mgr);
+
+ return ret;
+ }
+
+ return 0;
+}
+
+
+int
+virSecurityManagerRestoreNetdevLabel(virSecurityManager *mgr,
+ virDomainDef *vm,
+ virDomainNetDef *net)
+{
+ int ret;
+
+ if (mgr->drv->domainRestoreSecurityNetdevLabel) {
+ virObjectLock(mgr);
+ ret = mgr->drv->domainRestoreSecurityNetdevLabel(mgr, vm, net);
+ virObjectUnlock(mgr);
+
+ return ret;
+ }
+
+ return 0;
+}
+
+
static int
cmpstringp(const void *p1, const void *p2)
{
int virSecurityManagerRestoreTPMLabels(virSecurityManager *mgr,
virDomainDef *vm);
+int virSecurityManagerSetNetdevLabel(virSecurityManager *mgr,
+ virDomainDef *vm,
+ virDomainNetDef *net);
+
+int virSecurityManagerRestoreNetdevLabel(virSecurityManager *mgr,
+ virDomainDef *vm,
+ virDomainNetDef *net);
+
typedef struct _virSecurityManagerMetadataLockState virSecurityManagerMetadataLockState;
struct _virSecurityManagerMetadataLockState {
size_t nfds; /* Captures size of both @fds and @paths */
}
+static int
+virSecurityStackDomainSetNetdevLabel(virSecurityManager *mgr,
+ virDomainDef *def,
+ virDomainNetDef *net)
+{
+ virSecurityStackData *priv = virSecurityManagerGetPrivateData(mgr);
+ virSecurityStackItem *item = priv->itemsHead;
+
+ for (; item; item = item->next) {
+ if (virSecurityManagerSetNetdevLabel(item->securityManager, def, net) < 0)
+ goto rollback;
+ }
+
+ return 0;
+
+ rollback:
+ for (item = item->prev; item; item = item->prev) {
+ if (virSecurityManagerRestoreNetdevLabel(item->securityManager,
+ def, net) < 0) {
+ VIR_WARN("Unable to restore netdev label after failed set label "
+ "call virDriver=%s driver=%s domain=%s",
+ virSecurityManagerGetVirtDriver(mgr),
+ virSecurityManagerGetDriver(item->securityManager),
+ def->name);
+ }
+ }
+ return -1;
+}
+
+
+static int
+virSecurityStackDomainRestoreNetdevLabel(virSecurityManager *mgr,
+ virDomainDef *def,
+ virDomainNetDef *net)
+{
+ virSecurityStackData *priv = virSecurityManagerGetPrivateData(mgr);
+ virSecurityStackItem *item = priv->itemsHead;
+ int rc = 0;
+
+ for (; item; item = item->next) {
+ if (virSecurityManagerRestoreNetdevLabel(item->securityManager,
+ def, net) < 0)
+ rc = -1;
+ }
+
+ return rc;
+}
+
+
virSecurityDriver virSecurityDriverStack = {
.privateDataLen = sizeof(virSecurityStackData),
.name = "stack",
.domainSetSecurityTPMLabels = virSecurityStackSetTPMLabels,
.domainRestoreSecurityTPMLabels = virSecurityStackRestoreTPMLabels,
+
+ .domainSetSecurityNetdevLabel = virSecurityStackDomainSetNetdevLabel,
+ .domainRestoreSecurityNetdevLabel = virSecurityStackDomainRestoreNetdevLabel,
};