static int qemuTeardownDiskPathDeny(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED, const char *path, size_t depth ATTRIBUTE_UNUSED, void *opaque) { qemuCgroupData *data = opaque; int rc; VIR_DEBUG("Process path %s for disk", path); rc = virCgroupDenyDevicePath(data->cgroup, path, VIR_CGROUP_DEVICE_RWM); virDomainAuditCgroupPath(data->vm, data->cgroup, "deny", path, "rwm", rc); if (rc < 0) { if (rc == -EACCES) { /* Get this for root squash NFS */ VIR_DEBUG("Ignoring EACCES for %s", path); } else { virReportSystemError(-rc, _("Unable to deny access for disk path %s"), path); return -1; } } return 0; }
int qemuTeardownImageCgroup(virDomainObjPtr vm, virStorageSourcePtr src) { qemuDomainObjPrivatePtr priv = vm->privateData; int perms = VIR_CGROUP_DEVICE_READ | VIR_CGROUP_DEVICE_WRITE | VIR_CGROUP_DEVICE_MKNOD; int ret; if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES)) return 0; if (!src->path || !virStorageSourceIsLocalStorage(src)) { VIR_DEBUG("Not updating cgroups for disk path '%s', type: %s", NULLSTR(src->path), virStorageTypeToString(src->type)); return 0; } VIR_DEBUG("Deny path %s", src->path); ret = virCgroupDenyDevicePath(priv->cgroup, src->path, perms, true); virDomainAuditCgroupPath(vm, priv->cgroup, "deny", src->path, virCgroupGetDevicePermsString(perms), ret == 0); return ret; }
int qemuTeardownRNGCgroup(virDomainObjPtr vm, virDomainRNGDefPtr rng) { qemuDomainObjPrivatePtr priv = vm->privateData; int rv; if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES)) return 0; if (rng->backend == VIR_DOMAIN_RNG_BACKEND_RANDOM) { VIR_DEBUG("Tearing down Cgroup ACL for RNG device"); rv = virCgroupDenyDevicePath(priv->cgroup, rng->source.file, VIR_CGROUP_DEVICE_RW, false); virDomainAuditCgroupPath(vm, priv->cgroup, "deny", rng->source.file, "rw", rv); if (rv < 0 && !virLastErrorIsSystemErrno(ENOENT)) return -1; } return 0; }
static int CVE_2013_6456_libvirt1_1_0_lxcDomainDetachDeviceHostdevMiscLive(virDomainObjPtr vm, virDomainDeviceDefPtr dev) { virLXCDomainObjPrivatePtr priv = vm->privateData; virDomainHostdevDefPtr def = NULL; int i, ret = -1; char *dst = NULL; if (!priv->initpid) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Cannot attach disk until init PID is known")); goto cleanup; } if ((i = virDomainHostdevFind(vm->def, dev->data.hostdev, &def)) < 0) { virReportError(VIR_ERR_OPERATION_FAILED, _("hostdev %s not found"), dev->data.hostdev->source.caps.u.misc.chardev); goto cleanup; } if (virAsprintf(&dst, "/proc/%llu/root/%s", (unsigned long long)priv->initpid, def->source.caps.u.misc.chardev) < 0) { virReportOOMError(); goto cleanup; } if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("devices cgroup isn't mounted")); goto cleanup; } VIR_DEBUG("Unlinking %s", dst); if (unlink(dst) < 0 && errno != ENOENT) { virDomainAuditHostdev(vm, def, "detach", false); virReportSystemError(errno, _("Unable to remove device %s"), dst); goto cleanup; } virDomainAuditHostdev(vm, def, "detach", true); if (virCgroupDenyDevicePath(priv->cgroup, def->source.caps.u.misc.chardev, VIR_CGROUP_DEVICE_RWM) != 0) VIR_WARN("cannot deny device %s for domain %s", def->source.caps.u.misc.chardev, vm->def->name); virDomainHostdevRemove(vm->def, i); virDomainHostdevDefFree(def); ret = 0; cleanup: VIR_FREE(dst); return ret; }
int qemuTeardownHostdevCgroup(virDomainObjPtr vm, virDomainHostdevDefPtr dev) { int ret = -1; qemuDomainObjPrivatePtr priv = vm->privateData; virDomainHostdevSubsysPCIPtr pcisrc = &dev->source.subsys.u.pci; virPCIDevicePtr pci = NULL; char *path = NULL; /* currently this only does something for PCI devices using vfio * for device assignment, but it is called for *all* hostdev * devices. */ if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES)) return 0; if (dev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) { switch (dev->source.subsys.type) { case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: if (pcisrc->backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) { int rv; pci = virPCIDeviceNew(pcisrc->addr.domain, pcisrc->addr.bus, pcisrc->addr.slot, pcisrc->addr.function); if (!pci) goto cleanup; if (!(path = virPCIDeviceGetIOMMUGroupDev(pci))) goto cleanup; VIR_DEBUG("Cgroup deny %s for PCI device assignment", path); rv = virCgroupDenyDevicePath(priv->cgroup, path, VIR_CGROUP_DEVICE_RWM); virDomainAuditCgroupPath(vm, priv->cgroup, "deny", path, "rwm", rv == 0); if (rv < 0) goto cleanup; } break; case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: /* nothing to tear down for USB */ break; default: break; } } ret = 0; cleanup: virPCIDeviceFree(pci); VIR_FREE(path); return ret; }
static int qemuSetImageCgroupInternal(virDomainObjPtr vm, virStorageSourcePtr src, bool deny, bool forceReadonly) { qemuDomainObjPrivatePtr priv = vm->privateData; int perms = VIR_CGROUP_DEVICE_READ; int ret; if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES)) return 0; if (!src->path || !virStorageSourceIsLocalStorage(src)) { VIR_DEBUG("Not updating cgroups for disk path '%s', type: %s", NULLSTR(src->path), virStorageTypeToString(src->type)); return 0; } if (deny) { perms |= VIR_CGROUP_DEVICE_WRITE | VIR_CGROUP_DEVICE_MKNOD; VIR_DEBUG("Deny path %s", src->path); ret = virCgroupDenyDevicePath(priv->cgroup, src->path, perms); } else { if (!src->readonly && !forceReadonly) perms |= VIR_CGROUP_DEVICE_WRITE; VIR_DEBUG("Allow path %s, perms: %s", src->path, virCgroupGetDevicePermsString(perms)); ret = virCgroupAllowDevicePath(priv->cgroup, src->path, perms); } virDomainAuditCgroupPath(vm, priv->cgroup, deny ? "deny" : "allow", src->path, virCgroupGetDevicePermsString(perms), ret == 0); /* Get this for root squash NFS */ if (ret < 0 && virLastErrorIsSystemErrno(EACCES)) { VIR_DEBUG("Ignoring EACCES for %s", src->path); virResetLastError(); ret = 0; } return ret; }
static int qemuTeardownChrSourceCgroup(virDomainObjPtr vm, virDomainChrSourceDefPtr source) { qemuDomainObjPrivatePtr priv = vm->privateData; int ret; if (source->type != VIR_DOMAIN_CHR_TYPE_DEV) return 0; VIR_DEBUG("Process path '%s' for device", source->data.file.path); ret = virCgroupDenyDevicePath(priv->cgroup, source->data.file.path, VIR_CGROUP_DEVICE_RW, false); virDomainAuditCgroupPath(vm, priv->cgroup, "deny", source->data.file.path, "rw", ret == 0); return ret; }
int qemuTeardownMemoryDevicesCgroup(virDomainObjPtr vm, virDomainMemoryDefPtr mem) { qemuDomainObjPrivatePtr priv = vm->privateData; int rv; if (mem->model != VIR_DOMAIN_MEMORY_MODEL_NVDIMM) return 0; if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES)) return 0; rv = virCgroupDenyDevicePath(priv->cgroup, mem->nvdimmPath, VIR_CGROUP_DEVICE_RWM, false); virDomainAuditCgroupPath(vm, priv->cgroup, "deny", mem->nvdimmPath, "rwm", rv); return rv; }
int qemuTeardownHostdevCgroup(virDomainObjPtr vm, virDomainHostdevDefPtr dev) { qemuDomainObjPrivatePtr priv = vm->privateData; char **path = NULL; size_t i, npaths = 0; int rv, ret = -1; /* currently this only does something for PCI devices using vfio * for device assignment, but it is called for *all* hostdev * devices. */ if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES)) return 0; if (dev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && dev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI && dev->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO && qemuDomainGetHostdevPath(vm->def, dev, true, &npaths, &path, NULL) < 0) goto cleanup; for (i = 0; i < npaths; i++) { VIR_DEBUG("Cgroup deny %s", path[i]); rv = virCgroupDenyDevicePath(priv->cgroup, path[i], VIR_CGROUP_DEVICE_RWM, false); virDomainAuditCgroupPath(vm, priv->cgroup, "deny", path[i], "rwm", rv); if (rv < 0) goto cleanup; } ret = 0; cleanup: for (i = 0; i < npaths; i++) VIR_FREE(path[i]); VIR_FREE(path); return ret; }
int qemuTeardownInputCgroup(virDomainObjPtr vm, virDomainInputDefPtr dev) { qemuDomainObjPrivatePtr priv = vm->privateData; int ret = 0; if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES)) return 0; switch (dev->type) { case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH: VIR_DEBUG("Process path '%s' for input device", dev->source.evdev); ret = virCgroupDenyDevicePath(priv->cgroup, dev->source.evdev, VIR_CGROUP_DEVICE_RWM, false); virDomainAuditCgroupPath(vm, priv->cgroup, "deny", dev->source.evdev, "rwm", ret); break; } return ret; }
static int qemuTeardownDiskPathDeny(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED, const char *path, size_t depth ATTRIBUTE_UNUSED, void *opaque) { virDomainObjPtr vm = opaque; qemuDomainObjPrivatePtr priv = vm->privateData; int ret; VIR_DEBUG("Process path %s for disk", path); ret = virCgroupDenyDevicePath(priv->cgroup, path, VIR_CGROUP_DEVICE_RWM); virDomainAuditCgroupPath(vm, priv->cgroup, "deny", path, "rwm", ret == 0); /* Get this for root squash NFS */ if (ret < 0 && virLastErrorIsSystemErrno(EACCES)) { VIR_DEBUG("Ignoring EACCES for %s", path); virResetLastError(); ret = 0; } return ret; }