[PATCH 3/4] virdevmapper: Don't use libdevmapper to obtain dependencies

Marc Hartmayer mhartmay at linux.ibm.com
Thu Aug 6 13:45:27 UTC 2020


On Tue, Aug 04, 2020 at 11:39 PM +0200, Andrea Bolognani <abologna at redhat.com> wrote:
> On Mon, 2020-07-27 at 10:31 +0200, Michal Privoznik wrote:
>> CVE-2020-14339
>> 
>> When building domain's private /dev in a namespace, libdevmapper
>> is consulted for getting full dependency tree of domain's disks.
>> The reason is that for a multipath devices all dependent devices
>> must be created in the namespace and allowed in CGroups.
>> 
>> However, this approach is very fragile as building of namespace
>> happens in the forked off child process, after mass close of FDs
>> and just before dropping privileges and execing QEMU. And it so
>> happens that when calling libdevmapper APIs, one of them opens
>> /dev/mapper/control and saves the FD into a global variable. The
>> FD is kept open until the lib is unlinked or dm_lib_release() is
>> called explicitly. We are doing neither.
>> 
>> However, the virDevMapperGetTargets() function is called also
>> from libvirtd (when setting up CGroups) and thus has to be thread
>> safe. Unfortunately, libdevmapper APIs are not thread safe (nor
>> async signal safe) and thus we can't use them. Reimplement what
>> libdevmapper would do using plain C (ioctl()-s, /proc/devices
>> parsing, /dev/mapper dirwalking, and so on).
>> 
>> Fixes: a30078cb832646177defd256e77c632905f1e6d0
>> Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1858260
>> 
>> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
>> Reviewed-by: Daniel P. Berrangé <berrange at redhat.com>
>> ---
>>  po/POTFILES.in          |   1 +
>>  src/util/virdevmapper.c | 304 ++++++++++++++++++++++++++++------------
>>  2 files changed, 219 insertions(+), 86 deletions(-)
>
> This patch broke libvirt in Debian for certain setups.
>
> With AppArmor enabled (the default), the error is
>
>   $ virsh start cirros
>   error: Failed to start domain cirros
>   error: internal error: Process exited prior to exec: libvirt:
>   error : Cannot delete directory '/run/libvirt/qemu/1-cirros.dev':
>   Device or resource busy
>
> If I disable AppArmor by passing security='' on the kernel command
> line, the error message changes to
>
>   $ virsh start cirros
>   error: Failed to start domain cirros
>   error: internal error: Process exited prior to exec: libvirt:
>   QEMU Driver error : Unable to get devmapper targets for
>   /var/lib/libvirt/images/cirros.qcow2: Success
>
> An effective workaround is to set namespaces=[] in qemu.conf, but
> that's of course not something that we want users doing :)
>
> The underlying issue seems to be caused by the fact that, on a Debian
> installation that uses plain partitions instead of LVM, /proc/devices
> doesn't contain an entry for device-mapper right after boot, which...
>
>>  static int
>>  virDevMapperOnceInit(void)
>>  {
>> -    /* Ideally, we would not need this. But libdevmapper prints
>> -     * error messages to stderr by default. Sad but true. */
>> -    dm_log_with_errno_init(virDevMapperDummyLogger);
>> +    g_autofree char *buf = NULL;
>> +    VIR_AUTOSTRINGLIST lines = NULL;
>> +    size_t i;
>> +
>> +    if (virFileReadAll(PROC_DEVICES, BUF_SIZE, &buf) < 0)
>> +        return -1;
>> +
>> +    lines = virStringSplit(buf, "\n", 0);
>> +    if (!lines)
>> +        return -1;
>> +
>> +    for (i = 0; lines[i]; i++) {
>> +        g_autofree char *dev = NULL;
>> +        unsigned int maj;
>> +
>> +        if (sscanf(lines[i], "%u %ms\n", &maj, &dev) == 2 &&
>> +            STREQ(dev, DM_NAME)) {
>> +            virDMMajor = maj;
>> +            break;
>> +        }
>> +    }
>> +
>> +    if (!lines[i]) {
>> +        virReportError(VIR_ERR_INTERNAL_ERROR,
>> +                       _("Unable to find major for %s"),
>> +                       DM_NAME);
>> +        return -1;
>> +    }
>
> ... this code expects.
>
> Running
>
>   $ sudo dmsetup info
>   No devices found

We see the same problem as mentioned by Andrea. The host kernel
configuration used:

…
CONFIG_BLK_DEV_DM_BUILTIN=y
CONFIG_BLK_DEV_DM=m
…

As soon as we load the kernel module ‘dm-mod‘ everything works because
then ‘device-mapper‘ is listed in /proc/devices.

>
> causes the entry to appear, and from that moment on guest startup
> will work as expected regardless of whether or not AppArmor is
> enabled.
>
> I hope the information above can help someone who's familiar with the
> code figure out a fix. I'll provide more if needed, just ask! I can
> also provide prebuilt .deb files for 6.6.0 that consistently trigger
> the issue when added to a bog standard Debian testing installation.
>
> -- 
> Andrea Bolognani / Red Hat / Virtualization
>
-- 
Kind regards / Beste Grüße
   Marc Hartmayer

IBM Deutschland Research & Development GmbH
Vorsitzender des Aufsichtsrats: Gregor Pillen 
Geschäftsführung: Dirk Wittkopp
Sitz der Gesellschaft: Böblingen
Registergericht: Amtsgericht Stuttgart, HRB 243294





More information about the libvir-list mailing list