[libvirt] [PATCH] Honor blacklist for modprobe command

https://bugzilla.redhat.com/show_bug.cgi?id=1045124 When loading modules, libvirt does not honor the modprobe blacklist. By adding a "-b" to the modprobe command libvirt will fail to load a module if it's on the blacklist Check if the failure to load a driver was due to it being on the blacklist using the output of a "modprobe -c" searching for "blacklist <driver_Name>" where driver_Name is possibly a modified string of the input driver changing all '-' into '_' since that's what modprobe does. Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/util/virpci.c | 48 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/src/util/virpci.c b/src/util/virpci.c index e2d222e..18b85f2 100644 --- a/src/util/virpci.c +++ b/src/util/virpci.c @@ -979,6 +979,10 @@ virPCIProbeStubDriver(const char *driver) { char *drvpath = NULL; bool probed = false; + size_t i; + char *drvblklst = NULL; + char *outbuf = NULL; + virCommandPtr cmd = NULL; recheck: if (virPCIDriverDir(&drvpath, driver) == 0 && virFileExists(drvpath)) { @@ -990,18 +994,49 @@ recheck: VIR_FREE(drvpath); if (!probed) { - const char *const probecmd[] = { MODPROBE, driver, NULL }; + cmd = virCommandNewArgList(MODPROBE, "-b", driver, NULL); probed = true; - if (virRun(probecmd, NULL) < 0) { + if (virCommandRun(cmd, NULL) < 0) { char ebuf[1024]; VIR_WARN("failed to load driver %s: %s", driver, virStrerror(errno, ebuf, sizeof(ebuf))); - return -1; + goto cleanup; } + virCommandFree(cmd); + cmd = NULL; goto recheck; } + /* All error path code - purpose is to determine whether the failure + * occurs because device is on blacklist in order to add an error + * message to help detect why load failed + */ + if (virAsprintfQuiet(&drvblklst, "blacklist %s", driver) < 0) + goto cleanup; + + /* Although driver may have dash, 'modprobe -c' adjusts to use underscore */ + for (i = 0; i < drvblklst[i]; i++) + if (drvblklst[i] == '-') + drvblklst[i] = '_'; + + cmd = virCommandNewArgList(MODPROBE, "-c", NULL); + virCommandSetOutputBuffer(cmd, &outbuf); + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; + + /* Find driver on blacklist? */ + if (strstr(outbuf, drvblklst)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to load PCI stub module %s: " + "administratively prohibited"), + driver); + } + +cleanup: + virCommandFree(cmd); + VIR_FREE(drvblklst); + VIR_FREE(outbuf); return -1; } @@ -1313,9 +1348,10 @@ virPCIDeviceDetach(virPCIDevicePtr dev, virPCIDeviceList *inactiveDevs) { if (virPCIProbeStubDriver(dev->stubDriver) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Failed to load PCI stub module %s"), - dev->stubDriver); + if (virGetLastError() == NULL) + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to load PCI stub module %s"), + dev->stubDriver); return -1; } -- 1.8.4.2

On Tue, Jan 28, 2014 at 07:00:16PM -0500, John Ferlan wrote:
https://bugzilla.redhat.com/show_bug.cgi?id=1045124
When loading modules, libvirt does not honor the modprobe blacklist. By adding a "-b" to the modprobe command libvirt will fail to load a module if it's on the blacklist
Check if the failure to load a driver was due to it being on the blacklist using the output of a "modprobe -c" searching for "blacklist <driver_Name>" where driver_Name is possibly a modified string of the input driver changing all '-' into '_' since that's what modprobe does.
Signed-off-by: John Ferlan <jferlan@redhat.com> --- src/util/virpci.c | 48 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-)
diff --git a/src/util/virpci.c b/src/util/virpci.c index e2d222e..18b85f2 100644 --- a/src/util/virpci.c +++ b/src/util/virpci.c @@ -979,6 +979,10 @@ virPCIProbeStubDriver(const char *driver) { char *drvpath = NULL; bool probed = false; + size_t i; + char *drvblklst = NULL; + char *outbuf = NULL; + virCommandPtr cmd = NULL;
recheck: if (virPCIDriverDir(&drvpath, driver) == 0 && virFileExists(drvpath)) { @@ -990,18 +994,49 @@ recheck: VIR_FREE(drvpath);
if (!probed) { - const char *const probecmd[] = { MODPROBE, driver, NULL }; + cmd = virCommandNewArgList(MODPROBE, "-b", driver, NULL); probed = true; - if (virRun(probecmd, NULL) < 0) { + if (virCommandRun(cmd, NULL) < 0) { char ebuf[1024]; VIR_WARN("failed to load driver %s: %s", driver, virStrerror(errno, ebuf, sizeof(ebuf))); - return -1; + goto cleanup; } + virCommandFree(cmd); + cmd = NULL;
goto recheck; }
+ /* All error path code - purpose is to determine whether the failure + * occurs because device is on blacklist in order to add an error + * message to help detect why load failed + */ + if (virAsprintfQuiet(&drvblklst, "blacklist %s", driver) < 0) + goto cleanup; + + /* Although driver may have dash, 'modprobe -c' adjusts to use underscore */ + for (i = 0; i < drvblklst[i]; i++) + if (drvblklst[i] == '-') + drvblklst[i] = '_'; + + cmd = virCommandNewArgList(MODPROBE, "-c", NULL); + virCommandSetOutputBuffer(cmd, &outbuf); + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; + + /* Find driver on blacklist? */ + if (strstr(outbuf, drvblklst)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Failed to load PCI stub module %s: " + "administratively prohibited"), + driver); + } + +cleanup: + virCommandFree(cmd); + VIR_FREE(drvblklst); + VIR_FREE(outbuf); return -1; }
This is getting complex enough that I think we ought introduce a src/util/virkmod.{c,h} and have some helper APIs in there for loading and unload modules. eg virKModLoad, virKModUnload etc Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 01/29/2014 05:40 AM, Daniel P. Berrange wrote:
On Tue, Jan 28, 2014 at 07:00:16PM -0500, John Ferlan wrote:
This is getting complex enough that I think we ought introduce a src/util/virkmod.{c,h} and have some helper APIs in there for loading and unload modules. eg virKModLoad, virKModUnload etc
This change is for a bz indicating we weren't honoring when a device was on the blacklist (adding a -b to our modprobe)... The additional or more complext part was to use the -c was to determine whether that failure was because the device was already added, but put on the blacklist. Without that check "any" failure (whether the device doesn't exist or whether it's on the blacklist) gets the "Failed to load PCI stub module %s" message which may not help understand why the device cannot be used. The bug report was related towards "vfio-pci". Not disagreeing that load/unload isn't a desirable feature, but it seems out of the scope of the bug report. John

On Wed, Jan 29, 2014 at 06:32:42AM -0500, John Ferlan wrote:
On 01/29/2014 05:40 AM, Daniel P. Berrange wrote:
On Tue, Jan 28, 2014 at 07:00:16PM -0500, John Ferlan wrote:
This is getting complex enough that I think we ought introduce a src/util/virkmod.{c,h} and have some helper APIs in there for loading and unload modules. eg virKModLoad, virKModUnload etc
This change is for a bz indicating we weren't honoring when a device was on the blacklist (adding a -b to our modprobe)... The additional or more complext part was to use the -c was to determine whether that failure was because the device was already added, but put on the blacklist. Without that check "any" failure (whether the device doesn't exist or whether it's on the blacklist) gets the "Failed to load PCI stub module %s" message which may not help understand why the device cannot be used. The bug report was related towards "vfio-pci".
Not disagreeing that load/unload isn't a desirable feature, but it seems out of the scope of the bug report.
This code you're changing though is about module loading if I'm not mistaken. I'm saying that in improving the error reporting for this module loading, we should split the code out of this function into a standalone function. Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
participants (2)
-
Daniel P. Berrange
-
John Ferlan