[libvirt] [PATCH v2 2/3] qemu: Handle device mapper targets properly

Michal Privoznik mprivozn at redhat.com
Mon Mar 26 15:22:01 UTC 2018


On 03/26/2018 05:17 PM, Peter Krempa wrote:
> On Mon, Mar 26, 2018 at 16:43:02 +0200, Michal Privoznik wrote:
>> https://bugzilla.redhat.com/show_bug.cgi?id=1557769
>>
>> Problem with device mapper targets is that there can be several
>> other devices 'hidden' behind them. For instance, /dev/dm-1 can
>> consist of /dev/sda, /dev/sdb and /dev/sdc. Therefore, when
>> setting up devices CGroup and namespaces we have to take this
>> into account.
>>
>> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
>> ---
>>  libvirt.spec.in        |  2 ++
>>  src/qemu/qemu_cgroup.c | 42 ++++++++++++++++++++++++++++++---
>>  src/qemu/qemu_domain.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 105 insertions(+), 3 deletions(-)
>>
>> diff --git a/libvirt.spec.in b/libvirt.spec.in
>> index b55a947ec9..ebfac10866 100644
>> --- a/libvirt.spec.in
>> +++ b/libvirt.spec.in
>> @@ -796,6 +796,8 @@ Requires: gzip
>>  Requires: bzip2
>>  Requires: lzop
>>  Requires: xz
>> +# For mpath devices
>> +Requires: device-mapper
>>      %if 0%{?fedora} || 0%{?rhel} > 7
>>  Requires: systemd-container
>>      %endif
>> diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
>> index b604edb31c..e17b3d21b5 100644
>> --- a/src/qemu/qemu_cgroup.c
>> +++ b/src/qemu/qemu_cgroup.c
>> @@ -37,6 +37,7 @@
>>  #include "virtypedparam.h"
>>  #include "virnuma.h"
>>  #include "virsystemd.h"
>> +#include "virdevmapper.h"
>>  
>>  #define VIR_FROM_THIS VIR_FROM_QEMU
>>  
>> @@ -60,7 +61,13 @@ qemuSetupImagePathCgroup(virDomainObjPtr vm,
>>  {
>>      qemuDomainObjPrivatePtr priv = vm->privateData;
>>      int perms = VIR_CGROUP_DEVICE_READ;
>> -    int ret;
>> +    unsigned int *maj = NULL;
>> +    unsigned int *min = NULL;
>> +    size_t nmaj = 0;
>> +    size_t i;
>> +    char *devPath = NULL;
>> +    int rv;
>> +    int ret = -1;
>>  
>>      if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_DEVICES))
>>          return 0;
>> @@ -71,12 +78,41 @@ qemuSetupImagePathCgroup(virDomainObjPtr vm,
>>      VIR_DEBUG("Allow path %s, perms: %s",
>>                path, virCgroupGetDevicePermsString(perms));
>>  
>> -    ret = virCgroupAllowDevicePath(priv->cgroup, path, perms, true);
>> +    rv = virCgroupAllowDevicePath(priv->cgroup, path, perms, true);
>>  
>>      virDomainAuditCgroupPath(vm, priv->cgroup, "allow", path,
>>                               virCgroupGetDevicePermsString(perms),
>> -                             ret);
>> +                             rv);
>> +    if (rv < 0)
>> +        goto cleanup;
>>  
>> +    if (virDevMapperGetTargets(path, &maj, &min, &nmaj) < 0 &&
>> +        errno != ENOSYS && errno != EBADF) {
>> +        virReportSystemError(errno,
>> +                             _("Unable to get devmapper targets for %s"),
>> +                             path);
>> +        goto cleanup;
>> +    }
>> +
>> +    for (i = 0; i < nmaj; i++) {
>> +        if (virAsprintf(&devPath, "/dev/block/%u:%u", maj[i], min[i]) < 0)
>> +            goto cleanup;
> 
> So since this path will not help that much in the audit logs ...
> 
>> +
>> +        rv = virCgroupAllowDevicePath(priv->cgroup, devPath, perms, true);
> 
> ... you probably should use virCgroupAllowDevice ...
> 
>> +
>> +        virDomainAuditCgroupPath(vm, priv->cgroup, "allow", devPath,
>> +                                 virCgroupGetDevicePermsString(perms),
>> +                                 rv);
> 
> ... and add an equivalent of virDomainAuditCgroupMajor that takes both
> major:minor similarly to virDomainAuditCgroupMajor.
> 
>> +        if (rv < 0)
>> +            goto cleanup;
>> +        VIR_FREE(devPath);
>> +    }
>> +
>> +    ret = 0;
>> + cleanup:
>> +    VIR_FREE(devPath);
>> +    VIR_FREE(min);
>> +    VIR_FREE(maj);
>>      return ret;
>>  }
>>  
>> diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
>> index 580e0f830d..5f56324502 100644
>> --- a/src/qemu/qemu_domain.c
>> +++ b/src/qemu/qemu_domain.c
>> @@ -54,6 +54,7 @@
>>  #include "secret_util.h"
>>  #include "logging/log_manager.h"
>>  #include "locking/domain_lock.h"
>> +#include "virdevmapper.h"
>>  
>>  #ifdef MAJOR_IN_MKDEV
>>  # include <sys/mkdev.h>
>> @@ -10108,6 +10109,11 @@ qemuDomainSetupDisk(virQEMUDriverConfigPtr cfg ATTRIBUTE_UNUSED,
>>  {
>>      virStorageSourcePtr next;
>>      char *dst = NULL;
>> +    unsigned int *maj = NULL;
>> +    unsigned int *min = NULL;
>> +    size_t nmaj = 0;
>> +    char *devPath = NULL;
>> +    size_t i;
>>      int ret = -1;
>>  
>>      for (next = disk->src; virStorageSourceIsBacking(next); next = next->backingStore) {
>> @@ -10118,10 +10124,31 @@ qemuDomainSetupDisk(virQEMUDriverConfigPtr cfg ATTRIBUTE_UNUSED,
>>  
>>          if (qemuDomainCreateDevice(next->path, data, false) < 0)
>>              goto cleanup;
>> +
>> +        if (virDevMapperGetTargets(next->path, &maj, &min, &nmaj) < 0 &&
>> +            errno != ENOSYS && errno != EBADF) {
>> +            virReportSystemError(errno,
>> +                                 _("Unable to get mpath targets for %s"),
>> +                                 next->path);
>> +            goto cleanup;
>> +        }
>> +
>> +        for (i = 0; i < nmaj; i++) {
>> +            if (virAsprintf(&devPath, "/dev/block/%u:%u", maj[i], min[i]) < 0)
>> +                goto cleanup;
>> +
>> +            if (qemuDomainCreateDevice(devPath, data, false) < 0)
>> +                goto cleanup;
> 
> So now that I see this new version, this part starts looking suspicious
> to me. Since this did not care much that the path changed, is it really
> necessary to create the /dev/ entries in the container?
> 
> Looks like even device mapper is returning them as the node
> specificator, so I'd presume it really does not matter if they are
> present.
> 
> More specifically we can't really reverse engineer from the major:minor
> numbers which actual path the user used so it should not really be
> necessary for it to be present in the container.

Yes, looks like I was too eager trying to fix this bug. I've rebuilt
libvirt without qemu_domain.c change (so only CGroup code was modified)
and the bug still did not reproduce. So I guess namespace changes are
not necessary after all. I'll drop them.

Michal




More information about the libvir-list mailing list