util: cgroup: Allow ignoring EACCES in virCgroup(Allow|Deny)DevicePath

When adding disk images to ACL we may call those functions on NFS
shares. In that case we might get an EACCES, which isn't really relevant
since NFS would not hold a block device. This patch adds a flag that
allows to stop reporting an error on EACCES to avoid spaming logs.

Currently there's no functional change.
This commit is contained in:
Peter Krempa 2016-02-16 14:43:41 +01:00
parent 9cd5da710e
commit cf113e8d54
5 changed files with 59 additions and 26 deletions

View File

@ -331,7 +331,7 @@ virLXCSetupHostUSBDeviceCgroup(virUSBDevicePtr dev ATTRIBUTE_UNUSED,
VIR_DEBUG("Process path '%s' for USB device", path);
if (virCgroupAllowDevicePath(cgroup, path,
VIR_CGROUP_DEVICE_RWM) < 0)
VIR_CGROUP_DEVICE_RWM, false) < 0)
return -1;
return 0;
@ -347,7 +347,7 @@ virLXCTeardownHostUSBDeviceCgroup(virUSBDevicePtr dev ATTRIBUTE_UNUSED,
VIR_DEBUG("Process path '%s' for USB device", path);
if (virCgroupDenyDevicePath(cgroup, path,
VIR_CGROUP_DEVICE_RWM) < 0)
VIR_CGROUP_DEVICE_RWM, false) < 0)
return -1;
return 0;
@ -401,7 +401,7 @@ static int virLXCCgroupSetupDeviceACL(virDomainDefPtr def,
(def->disks[i]->src->readonly ?
VIR_CGROUP_DEVICE_READ :
VIR_CGROUP_DEVICE_RW) |
VIR_CGROUP_DEVICE_MKNOD) < 0)
VIR_CGROUP_DEVICE_MKNOD, false) < 0)
goto cleanup;
}
@ -414,7 +414,7 @@ static int virLXCCgroupSetupDeviceACL(virDomainDefPtr def,
def->fss[i]->src,
def->fss[i]->readonly ?
VIR_CGROUP_DEVICE_READ :
VIR_CGROUP_DEVICE_RW) < 0)
VIR_CGROUP_DEVICE_RW, false) < 0)
goto cleanup;
}
@ -448,14 +448,14 @@ static int virLXCCgroupSetupDeviceACL(virDomainDefPtr def,
if (virCgroupAllowDevicePath(cgroup,
hostdev->source.caps.u.storage.block,
VIR_CGROUP_DEVICE_RW |
VIR_CGROUP_DEVICE_MKNOD) < 0)
VIR_CGROUP_DEVICE_MKNOD, false) < 0)
goto cleanup;
break;
case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC:
if (virCgroupAllowDevicePath(cgroup,
hostdev->source.caps.u.misc.chardev,
VIR_CGROUP_DEVICE_RW |
VIR_CGROUP_DEVICE_MKNOD) < 0)
VIR_CGROUP_DEVICE_MKNOD, false) < 0)
goto cleanup;
break;
default:

View File

@ -4646,7 +4646,8 @@ lxcDomainDetachDeviceDiskLive(virDomainObjPtr vm,
}
virDomainAuditDisk(vm, def->src, NULL, "detach", true);
if (virCgroupDenyDevicePath(priv->cgroup, src, VIR_CGROUP_DEVICE_RWM) != 0)
if (virCgroupDenyDevicePath(priv->cgroup, src,
VIR_CGROUP_DEVICE_RWM, false) != 0)
VIR_WARN("cannot deny device %s for domain %s",
src, vm->def->name);
@ -4822,7 +4823,8 @@ lxcDomainDetachDeviceHostdevStorageLive(virDomainObjPtr vm,
}
virDomainAuditHostdev(vm, def, "detach", true);
if (virCgroupDenyDevicePath(priv->cgroup, def->source.caps.u.storage.block, VIR_CGROUP_DEVICE_RWM) != 0)
if (virCgroupDenyDevicePath(priv->cgroup, def->source.caps.u.storage.block,
VIR_CGROUP_DEVICE_RWM, false) != 0)
VIR_WARN("cannot deny device %s for domain %s",
def->source.caps.u.storage.block, vm->def->name);
@ -4871,7 +4873,8 @@ lxcDomainDetachDeviceHostdevMiscLive(virDomainObjPtr vm,
}
virDomainAuditHostdev(vm, def, "detach", true);
if (virCgroupDenyDevicePath(priv->cgroup, def->source.caps.u.misc.chardev, VIR_CGROUP_DEVICE_RWM) != 0)
if (virCgroupDenyDevicePath(priv->cgroup, def->source.caps.u.misc.chardev,
VIR_CGROUP_DEVICE_RWM, false) != 0)
VIR_WARN("cannot deny device %s for domain %s",
def->source.caps.u.misc.chardev, vm->def->name);

View File

@ -77,7 +77,7 @@ qemuSetImageCgroupInternal(virDomainObjPtr vm,
VIR_DEBUG("Deny path %s", src->path);
ret = virCgroupDenyDevicePath(priv->cgroup, src->path, perms);
ret = virCgroupDenyDevicePath(priv->cgroup, src->path, perms, false);
} else {
if (!src->readonly && !forceReadonly)
perms |= VIR_CGROUP_DEVICE_WRITE;
@ -85,7 +85,7 @@ qemuSetImageCgroupInternal(virDomainObjPtr vm,
VIR_DEBUG("Allow path %s, perms: %s",
src->path, virCgroupGetDevicePermsString(perms));
ret = virCgroupAllowDevicePath(priv->cgroup, src->path, perms);
ret = virCgroupAllowDevicePath(priv->cgroup, src->path, perms, false);
}
virDomainAuditCgroupPath(vm, priv->cgroup,
@ -162,7 +162,7 @@ qemuSetupChrSourceCgroup(virDomainObjPtr vm,
VIR_DEBUG("Process path '%s' for device", source->data.file.path);
ret = virCgroupAllowDevicePath(priv->cgroup, source->data.file.path,
VIR_CGROUP_DEVICE_RW);
VIR_CGROUP_DEVICE_RW, false);
virDomainAuditCgroupPath(vm, priv->cgroup, "allow",
source->data.file.path, "rw", ret == 0);
@ -209,7 +209,7 @@ qemuSetupInputCgroup(virDomainObjPtr vm,
case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH:
VIR_DEBUG("Process path '%s' for input device", dev->source.evdev);
ret = virCgroupAllowDevicePath(priv->cgroup, dev->source.evdev,
VIR_CGROUP_DEVICE_RW);
VIR_CGROUP_DEVICE_RW, false);
virDomainAuditCgroupPath(vm, priv->cgroup, "allow", dev->source.evdev, "rw", ret == 0);
break;
}
@ -229,7 +229,7 @@ qemuSetupHostUSBDeviceCgroup(virUSBDevicePtr dev ATTRIBUTE_UNUSED,
VIR_DEBUG("Process path '%s' for USB device", path);
ret = virCgroupAllowDevicePath(priv->cgroup, path,
VIR_CGROUP_DEVICE_RW);
VIR_CGROUP_DEVICE_RW, false);
virDomainAuditCgroupPath(vm, priv->cgroup, "allow", path, "rw", ret == 0);
return ret;
@ -249,7 +249,7 @@ qemuSetupHostSCSIDeviceCgroup(virSCSIDevicePtr dev ATTRIBUTE_UNUSED,
ret = virCgroupAllowDevicePath(priv->cgroup, path,
virSCSIDeviceGetReadonly(dev) ?
VIR_CGROUP_DEVICE_READ :
VIR_CGROUP_DEVICE_RW);
VIR_CGROUP_DEVICE_RW, false);
virDomainAuditCgroupPath(vm, priv->cgroup, "allow", path,
virSCSIDeviceGetReadonly(dev) ? "r" : "rw", ret == 0);
@ -298,7 +298,7 @@ qemuSetupHostdevCgroup(virDomainObjPtr vm,
VIR_DEBUG("Cgroup allow %s for PCI device assignment", path);
rv = virCgroupAllowDevicePath(priv->cgroup, path,
VIR_CGROUP_DEVICE_RW);
VIR_CGROUP_DEVICE_RW, false);
virDomainAuditCgroupPath(vm, priv->cgroup,
"allow", path, "rw", rv == 0);
if (rv < 0)
@ -407,7 +407,7 @@ qemuTeardownHostdevCgroup(virDomainObjPtr vm,
VIR_DEBUG("Cgroup deny %s for PCI device assignment", path);
rv = virCgroupDenyDevicePath(priv->cgroup, path,
VIR_CGROUP_DEVICE_RWM);
VIR_CGROUP_DEVICE_RWM, false);
virDomainAuditCgroupPath(vm, priv->cgroup,
"deny", path, "rwm", rv == 0);
if (rv < 0)
@ -591,7 +591,7 @@ qemuSetupDevicesCgroup(virQEMUDriverPtr driver,
}
rv = virCgroupAllowDevicePath(priv->cgroup, deviceACL[i],
VIR_CGROUP_DEVICE_RW);
VIR_CGROUP_DEVICE_RW, false);
virDomainAuditCgroupPath(vm, priv->cgroup, "allow", deviceACL[i], "rw", rv == 0);
if (rv < 0 &&
!virLastErrorIsSystemErrno(ENOENT))
@ -622,7 +622,7 @@ qemuSetupDevicesCgroup(virQEMUDriverPtr driver,
VIR_DEBUG("Setting Cgroup ACL for RNG device");
rv = virCgroupAllowDevicePath(priv->cgroup,
vm->def->rngs[i]->source.file,
VIR_CGROUP_DEVICE_RW);
VIR_CGROUP_DEVICE_RW, false);
virDomainAuditCgroupPath(vm, priv->cgroup, "allow",
vm->def->rngs[i]->source.file,
"rw", rv == 0);

View File

@ -2986,19 +2986,26 @@ virCgroupAllowDevice(virCgroupPtr group, char type, int major, int minor,
* @group: The cgroup to allow the device for
* @path: the device to allow
* @perms: Bitwise or of VIR_CGROUP_DEVICE permission bits to allow
* @ignoreEacces: Ignore lack of permission (mostly for NFS mounts)
*
* Queries the type of device and its major/minor number, and
* adds that to the cgroup ACL
*
* Returns: 0 on success, 1 if path exists but is not a device, or
* -1 on error
* Returns: 0 on success, 1 if path exists but is not a device or is not
* accesible, or * -1 on error
*/
int
virCgroupAllowDevicePath(virCgroupPtr group, const char *path, int perms)
virCgroupAllowDevicePath(virCgroupPtr group,
const char *path,
int perms,
bool ignoreEacces)
{
struct stat sb;
if (stat(path, &sb) < 0) {
if (errno == EACCES && ignoreEacces)
return 1;
virReportSystemError(errno,
_("Path '%s' is not accessible"),
path);
@ -3064,12 +3071,32 @@ virCgroupDenyDevice(virCgroupPtr group, char type, int major, int minor,
}
/**
* virCgroupDenyDevicePath:
*
* @group: The cgroup to deny the device for
* @path: the device to deny
* @perms: Bitwise or of VIR_CGROUP_DEVICE permission bits to allow
* @ignoreEacces: Ignore lack of permission (mostly for NFS mounts)
*
* Queries the type of device and its major/minor number, and
* removes it from the cgroup ACL
*
* Returns: 0 on success, 1 if path exists but is not a device or is not
* accessible, or -1 on error.
*/
int
virCgroupDenyDevicePath(virCgroupPtr group, const char *path, int perms)
virCgroupDenyDevicePath(virCgroupPtr group,
const char *path,
int perms,
bool ignoreEacces)
{
struct stat sb;
if (stat(path, &sb) < 0) {
if (errno == EACCES && ignoreEacces)
return 1;
virReportSystemError(errno,
_("Path '%s' is not accessible"),
path);
@ -4637,7 +4664,8 @@ virCgroupAllowDevice(virCgroupPtr group ATTRIBUTE_UNUSED,
int
virCgroupAllowDevicePath(virCgroupPtr group ATTRIBUTE_UNUSED,
const char *path ATTRIBUTE_UNUSED,
int perms ATTRIBUTE_UNUSED)
int perms ATTRIBUTE_UNUSED,
bool ignoreEaccess ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s",
_("Control groups not supported on this platform"));

View File

@ -222,7 +222,8 @@ int virCgroupAllowDevice(virCgroupPtr group,
int perms);
int virCgroupAllowDevicePath(virCgroupPtr group,
const char *path,
int perms);
int perms,
bool ignoreEacces);
int virCgroupDenyDevice(virCgroupPtr group,
char type,
@ -231,7 +232,8 @@ int virCgroupDenyDevice(virCgroupPtr group,
int perms);
int virCgroupDenyDevicePath(virCgroupPtr group,
const char *path,
int perms);
int perms,
bool ignoreEacces);
int
virCgroupGetPercpuStats(virCgroupPtr group,