[libvirt] Libvirt fails to apply security context to fd/node to USB device

Hi, I'm attempting to attach and expose a USB device (WiFi adapter for testing) to an LXC container with SELinux enabled. But when enabling the XML snippet, the container fails to start with this error: 2018-01-12 19:24:31.914+0000: 2181: error : virSecuritySELinuxSetFileconHelper:1182 : unable to set security context 'system_u:object_r:svirt_sandbox_file_t:s0:c139,c284' on '//var/run/libvirt/lxc/lxc_0.dev/bus/usb//dev/bus/usb/002/002': No such file or directory Failure in libvirt_lxc startup: unable to set security context 'system_u:object_r:svirt_sandbox_file_t:s0:c139,c284' on '//var/run/libvirt/lxc/lxc_0.dev/bus/usb//dev/bus/usb/002/002': No such file or directory The XML snippet for attaching USB device: <hostdev mode='subsystem' type='usb' managed='yes'> <source> <vendor id='0x05ac'/> <product id='0x1006'/> </source> <address type='usb' bus='2' port='2'/> </hostdev> SELinux snippet (using the dynamic label for the moment): <seclabel type='dynamic' model='selinux' relabel='yes'/> Running it on CentOS 7.2 and I've tried the distro from the package manager (1.3.3.3), as well as downloaded and compiled the latest stable from libvirt.org (3.10?) and came to the same error each time. Did a small dive into the code after realizing that the path just doesn't seem right. Path (seems to have an unusual and incorrect concatenation of folders) : //var/run/libvirt/lxc/lxc_0.dev/bus/usb//dev/bus/usb/002/002 "vroot" seems to be declared by the LXC controller (src/lxc/lxc_controller.c) as such: if (virAsprintf(&vroot, "/%s/%s.dev/bus/usb/", LXC_STATE_DIR, vmDef->name) < 0) goto cleanup; Then upon setting up security for all of the container's attached devices, we call virUSBDeviceNew to setup the attached USB device and give us the path to apply a context to. Since vroot is present, we get this weird path when running through this (src/util/virusb.c): if (virAsprintf(&dev->path, "%s" USB_DEVFS "%03d/%03d", vroot ? vroot : "", dev->bus, dev->dev) < 0) { virUSBDeviceFree(dev); return NULL; } Note: # define USB_DEVFS "/dev/bus/usb/" Should we just be blindly appending this definition if vroot is present, making the path incorrect? If this isn't a bug, I propose the following change: if (virAsprintf(&dev->path, "%s" "%03d/%03d", vroot ? vroot : USB_DEVFS, dev->bus, dev->dev) < 0) { virUSBDeviceFree(dev); return NULL; } Would kindly appreciate any feedback on whether this is a bug or maybe I'm missing something and is the reason why it's written this way. Thanks, Randy

On 01/16/2018 07:20 PM, Randy Aybar wrote:
Hi,
I'm attempting to attach and expose a USB device (WiFi adapter for testing) to an LXC container with SELinux enabled. But when enabling the XML snippet, the container fails to start with this error:
2018-01-12 19:24:31.914+0000: 2181: error : virSecuritySELinuxSetFileconHelper:1182 : unable to set security context 'system_u:object_r:svirt_sandbox_file_t:s0:c139,c284' on '//var/run/libvirt/lxc/lxc_0.dev/bus/usb//dev/bus/usb/002/002': No such file or directory
Failure in libvirt_lxc startup: unable to set security context 'system_u:object_r:svirt_sandbox_file_t:s0:c139,c284' on '//var/run/libvirt/lxc/lxc_0.dev/bus/usb//dev/bus/usb/002/002': No such file or directory
Yes, this is a libvirt bug. And your analysis is coorect. The problem is: 1) in virLXCControllerSetupHostdevSubsysUSB the first part of path is constructed: vroot = /var/run/libvirt/lxc/lxc_0.dev/bus/usb 2) then, virSecurityManagerSetHostdevLabel() is called, which subsequently calls virSecuritySELinuxSetHostdevSubsysLabel(). 3) The SELinuxSetHostdevSubsysLabel() calls virUSBDeviceNew(..,vroot) where vroot is the path from step 1). The virUSBDeviceNew then does: if (virAsprintf(&dev->path, "%s" USB_DEVFS "%03d/%03d", vroot ? vroot : "", dev->bus, dev->dev) < 0) { virUSBDeviceFree(dev); return NULL; } where USB_DEVFS is defined as: # define USB_DEVFS "/dev/bus/usb/" So in the end, dev->path contains the path that you're seeing. I think this the fix: diff --git a/src/util/virusb.c b/src/util/virusb.c index 6359235ff..99ee08657 100644 --- a/src/util/virusb.c +++ b/src/util/virusb.c @@ -343,9 +343,9 @@ virUSBDeviceNew(unsigned int bus, virUSBDeviceFree(dev); return NULL; } - if (virAsprintf(&dev->path, "%s" USB_DEVFS "%03d/%03d", - vroot ? vroot : "", - dev->bus, dev->dev) < 0) { + + if ((vroot && virAsprintf(&dev->path, "%s/%03d/%03d", vroot, dev->bus, dev->dev) < 0) || + (!vroot && virAsprintf(&dev->path, USB_DEVFS "%03d/%03d", dev->bus, dev->dev) < 0)) { virUSBDeviceFree(dev); return NULL; } (of course after breaking down the long lines). Can you please test it? Michal

Hi Michael, Thanks for looking at the submission. I've made the proposed changes and can verify that the fix works. :) There error has gone away with the container starting. Below is a snippet of the device node from the intermediate mount namespace that eventually ends up target container's mount namespace: $ sudo nsenter -t 7397 -m # ls -laZ /var/run/libvirt/lxc/lxc_0.dev/bus/usb/001/002 crwx------. 1 root root system_u:object_r:svirt_sandbox_file_t:s0:c600,c910 189, 1 Jan 23 14:55 /var/run/libvirt/lxc/lxc_0.dev/bus/usb/001/002 Thanks, Randy ________________________________ From: Michal Privoznik <mprivozn@redhat.com> Sent: Friday, January 19, 2018 11:19 AM To: Randy Aybar; libvir-list@redhat.com Subject: Re: [libvirt] Libvirt fails to apply security context to fd/node to USB device On 01/16/2018 07:20 PM, Randy Aybar wrote:
Hi,
I'm attempting to attach and expose a USB device (WiFi adapter for testing) to an LXC container with SELinux enabled. But when enabling the XML snippet, the container fails to start with this error:
2018-01-12 19:24:31.914+0000: 2181: error : virSecuritySELinuxSetFileconHelper:1182 : unable to set security context 'system_u:object_r:svirt_sandbox_file_t:s0:c139,c284' on '//var/run/libvirt/lxc/lxc_0.dev/bus/usb//dev/bus/usb/002/002': No such file or directory
Failure in libvirt_lxc startup: unable to set security context 'system_u:object_r:svirt_sandbox_file_t:s0:c139,c284' on '//var/run/libvirt/lxc/lxc_0.dev/bus/usb//dev/bus/usb/002/002': No such file or directory
Yes, this is a libvirt bug. And your analysis is coorect. The problem is: 1) in virLXCControllerSetupHostdevSubsysUSB the first part of path is constructed: vroot = /var/run/libvirt/lxc/lxc_0.dev/bus/usb 2) then, virSecurityManagerSetHostdevLabel() is called, which subsequently calls virSecuritySELinuxSetHostdevSubsysLabel(). 3) The SELinuxSetHostdevSubsysLabel() calls virUSBDeviceNew(..,vroot) where vroot is the path from step 1). The virUSBDeviceNew then does: if (virAsprintf(&dev->path, "%s" USB_DEVFS "%03d/%03d", vroot ? vroot : "", dev->bus, dev->dev) < 0) { virUSBDeviceFree(dev); return NULL; } where USB_DEVFS is defined as: # define USB_DEVFS "/dev/bus/usb/" So in the end, dev->path contains the path that you're seeing. I think this the fix: diff --git a/src/util/virusb.c b/src/util/virusb.c index 6359235ff..99ee08657 100644 --- a/src/util/virusb.c +++ b/src/util/virusb.c @@ -343,9 +343,9 @@ virUSBDeviceNew(unsigned int bus, virUSBDeviceFree(dev); return NULL; } - if (virAsprintf(&dev->path, "%s" USB_DEVFS "%03d/%03d", - vroot ? vroot : "", - dev->bus, dev->dev) < 0) { + + if ((vroot && virAsprintf(&dev->path, "%s/%03d/%03d", vroot, dev->bus, dev->dev) < 0) || + (!vroot && virAsprintf(&dev->path, USB_DEVFS "%03d/%03d", dev->bus, dev->dev) < 0)) { virUSBDeviceFree(dev); return NULL; } (of course after breaking down the long lines). Can you please test it? Michal
participants (2)
-
Michal Privoznik
-
Randy Aybar