render / rpms / libvirt

Forked from rpms/libvirt 7 months ago
Clone
7a3408
From b26bd9a4f71598c17a09b7148aa82773b480b8b5 Mon Sep 17 00:00:00 2001
7a3408
Message-Id: <b26bd9a4f71598c17a09b7148aa82773b480b8b5@dist-git>
7a3408
From: Laine Stump <laine@laine.org>
7a3408
Date: Sat, 8 Aug 2015 19:36:40 -0400
7a3408
Subject: [PATCH] conf: more useful error message when pci function is out of
7a3408
 range
7a3408
7a3408
If a pci address had a function number out of range, the error message
7a3408
would be:
7a3408
7a3408
  Insufficient specification for PCI address
7a3408
7a3408
which is logged by virDevicePCIAddressParseXML() after
7a3408
virDevicePCIAddressIsValid returns a failure.
7a3408
7a3408
This patch enhances virDevicePCIAddressIsValid() to optionally report
7a3408
the error itself (since it is the place that decides which part of the
7a3408
address is "invalid"), and uses that feature when calling from
7a3408
virDevicePCIAddressParseXML(), so that the error will be more useful,
7a3408
e.g.:
7a3408
7a3408
  Invalid PCI address function=0x8, must be <= 7
7a3408
7a3408
Previously, virDevicePCIAddressIsValid didn't check for the
7a3408
theoretical limits of domain or bus, only for slot or function. While
7a3408
adding log messages, we also correct that ommission. (The RNG for PCI
7a3408
addresses already enforces this limit, which by the way means that we
7a3408
can't add any negative tests for this - as far as I know our
7a3408
domainschematest has no provisions for passing XML that is supposed to
7a3408
fail).
7a3408
7a3408
Note that virDevicePCIAddressIsValid() can only check against the
7a3408
absolute maximum attribute values for *any* possible PCI controller,
7a3408
not for the actual maximums of the specific controller that this
7a3408
device is attaching to; fortunately there is later more specific
7a3408
validation for guest-side PCI addresses when building the set of
7a3408
assigned PCI addresses. For host-side PCI addresses (e.g. for
7a3408
<hostdev> and for network device pools), we rely on the error that
7a3408
will be logged when it is found that the device doesn't actually
7a3408
exist.
7a3408
7a3408
This resolves:
7a3408
7a3408
  https://bugzilla.redhat.com/show_bug.cgi?id=1004596
7a3408
7a3408
(cherry picked from commit f8fe8f03455783afcd62d79db7ce4120f514c629)
7a3408
7a3408
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
7a3408
---
7a3408
 src/conf/device_conf.c                             | 52 ++++++++++++++++++----
7a3408
 src/conf/device_conf.h                             |  5 ++-
7a3408
 src/conf/domain_conf.c                             |  2 +-
7a3408
 .../qemuxml2argv-pci-bus-invalid.xml               | 33 ++++++++++++++
7a3408
 .../qemuxml2argv-pci-domain-invalid.xml            | 33 ++++++++++++++
7a3408
 .../qemuxml2argv-pci-function-invalid.xml          | 33 ++++++++++++++
7a3408
 .../qemuxml2argv-pci-slot-invalid.xml              | 33 ++++++++++++++
7a3408
 tests/qemuxml2argvtest.c                           |  6 +++
7a3408
 8 files changed, 185 insertions(+), 12 deletions(-)
7a3408
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-bus-invalid.xml
7a3408
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-domain-invalid.xml
7a3408
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-function-invalid.xml
7a3408
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-pci-slot-invalid.xml
7a3408
7a3408
diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
7a3408
index 98808e2..5bf903c 100644
7a3408
--- a/src/conf/device_conf.c
7a3408
+++ b/src/conf/device_conf.c
7a3408
@@ -1,7 +1,7 @@
7a3408
 /*
7a3408
  * device_conf.c: device XML handling
7a3408
  *
7a3408
- * Copyright (C) 2006-2012 Red Hat, Inc.
7a3408
+ * Copyright (C) 2006-2015 Red Hat, Inc.
7a3408
  *
7a3408
  * This library is free software; you can redistribute it and/or
7a3408
  * modify it under the terms of the GNU Lesser General Public
7a3408
@@ -53,12 +53,49 @@ VIR_ENUM_IMPL(virNetDevFeature,
7a3408
               "ntuple",
7a3408
               "rxhash")
7a3408
 
7a3408
-int virDevicePCIAddressIsValid(virDevicePCIAddressPtr addr)
7a3408
+int virDevicePCIAddressIsValid(virDevicePCIAddressPtr addr,
7a3408
+                               bool report)
7a3408
 {
7a3408
-    /* PCI bus has 32 slots and 8 functions per slot */
7a3408
-    if (addr->slot >= 32 || addr->function >= 8)
7a3408
+    if (addr->domain > 0xFFFF) {
7a3408
+        if (report)
7a3408
+            virReportError(VIR_ERR_XML_ERROR,
7a3408
+                           _("Invalid PCI address domain='0x%x', "
7a3408
+                             "must be <= 0xFFFF"),
7a3408
+                           addr->domain);
7a3408
         return 0;
7a3408
-    return addr->domain || addr->bus || addr->slot;
7a3408
+    }
7a3408
+    if (addr->bus > 0xFF) {
7a3408
+        if (report)
7a3408
+            virReportError(VIR_ERR_XML_ERROR,
7a3408
+                           _("Invalid PCI address bus='0x%x', "
7a3408
+                             "must be <= 0xFF"),
7a3408
+                           addr->bus);
7a3408
+        return 0;
7a3408
+    }
7a3408
+    if (addr->slot > 0x1F) {
7a3408
+        if (report)
7a3408
+            virReportError(VIR_ERR_XML_ERROR,
7a3408
+                           _("Invalid PCI address slot='0x%x', "
7a3408
+                             "must be <= 0x1F"),
7a3408
+                           addr->slot);
7a3408
+        return 0;
7a3408
+    }
7a3408
+    if (addr->function > 7) {
7a3408
+        if (report)
7a3408
+            virReportError(VIR_ERR_XML_ERROR,
7a3408
+                           _("Invalid PCI address function=0x%x, "
7a3408
+                             "must be <= 7"),
7a3408
+                           addr->function);
7a3408
+        return 0;
7a3408
+    }
7a3408
+    if (!(addr->domain || addr->bus || addr->slot)) {
7a3408
+        if (report)
7a3408
+            virReportError(VIR_ERR_XML_ERROR, "%s",
7a3408
+                           _("Invalid PCI address 0000:00:00, at least "
7a3408
+                             "one of domain, bus, or slot must be > 0"));
7a3408
+        return 0;
7a3408
+    }
7a3408
+    return 1;
7a3408
 }
7a3408
 
7a3408
 
7a3408
@@ -113,11 +150,8 @@ virDevicePCIAddressParseXML(xmlNodePtr node,
7a3408
         goto cleanup;
7a3408
 
7a3408
     }
7a3408
-    if (!virDevicePCIAddressIsValid(addr)) {
7a3408
-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
7a3408
-                       _("Insufficient specification for PCI address"));
7a3408
+    if (!virDevicePCIAddressIsValid(addr, true))
7a3408
         goto cleanup;
7a3408
-    }
7a3408
 
7a3408
     ret = 0;
7a3408
 
7a3408
diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
7a3408
index 7ea90f6..d3d3739 100644
7a3408
--- a/src/conf/device_conf.h
7a3408
+++ b/src/conf/device_conf.h
7a3408
@@ -1,7 +1,7 @@
7a3408
 /*
7a3408
  * device_conf.h: device XML handling entry points
7a3408
  *
7a3408
- * Copyright (C) 2006-2012 Red Hat, Inc.
7a3408
+ * Copyright (C) 2006-2012, 2014-2015 Red Hat, Inc.
7a3408
  *
7a3408
  * This library is free software; you can redistribute it and/or
7a3408
  * modify it under the terms of the GNU Lesser General Public
7a3408
@@ -79,7 +79,8 @@ typedef enum {
7a3408
 
7a3408
 VIR_ENUM_DECL(virNetDevFeature)
7a3408
 
7a3408
-int virDevicePCIAddressIsValid(virDevicePCIAddressPtr addr);
7a3408
+int virDevicePCIAddressIsValid(virDevicePCIAddressPtr addr,
7a3408
+                               bool report);
7a3408
 
7a3408
 int virDevicePCIAddressParseXML(xmlNodePtr node,
7a3408
                                 virDevicePCIAddressPtr addr);
7a3408
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
7a3408
index 54d0651..aa1b860 100644
7a3408
--- a/src/conf/domain_conf.c
7a3408
+++ b/src/conf/domain_conf.c
7a3408
@@ -3095,7 +3095,7 @@ int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
7a3408
 
7a3408
     switch (info->type) {
7a3408
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
7a3408
-        return virDevicePCIAddressIsValid(&info->addr.pci);
7a3408
+        return virDevicePCIAddressIsValid(&info->addr.pci, false);
7a3408
 
7a3408
     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
7a3408
         return 1;
7a3408
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pci-bus-invalid.xml b/tests/qemuxml2argvdata/qemuxml2argv-pci-bus-invalid.xml
7a3408
new file mode 100644
7a3408
index 0000000..f6d0901
7a3408
--- /dev/null
7a3408
+++ b/tests/qemuxml2argvdata/qemuxml2argv-pci-bus-invalid.xml
7a3408
@@ -0,0 +1,33 @@
7a3408
+<domain type='qemu'>
7a3408
+  <name>QEMUGuest1</name>
7a3408
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
7a3408
+  <memory unit='KiB'>219136</memory>
7a3408
+  <currentMemory unit='KiB'>219136</currentMemory>
7a3408
+  <vcpu placement='static'>1</vcpu>
7a3408
+  <os>
7a3408
+    <type arch='i686' machine='pc'>hvm</type>
7a3408
+    <boot dev='hd'/>
7a3408
+  </os>
7a3408
+  <clock offset='utc'/>
7a3408
+  <on_poweroff>destroy</on_poweroff>
7a3408
+  <on_reboot>restart</on_reboot>
7a3408
+  <on_crash>destroy</on_crash>
7a3408
+  <devices>
7a3408
+    <emulator>/usr/bin/qemu</emulator>
7a3408
+    <disk type='block' device='disk'>
7a3408
+      <driver name='qemu' type='raw'/>
7a3408
+      <source dev='/dev/HostVG/QEMUGuest1'/>
7a3408
+      <target dev='hda' bus='ide'/>
7a3408
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
7a3408
+    </disk>
7a3408
+    <controller type='usb' index='0'/>
7a3408
+    <controller type='ide' index='0'/>
7a3408
+    <controller type='pci' index='0' model='pci-root'/>
7a3408
+    <interface type='user'>
7a3408
+      <mac address='00:11:22:33:44:55'/>
7a3408
+      <model type='rtl8139'/>
7a3408
+      <address type='pci' domain='0x0000' bus='0x100' slot='0x05' function='0x0'/>
7a3408
+    </interface>
7a3408
+    <memballoon model='none'/>
7a3408
+  </devices>
7a3408
+</domain>
7a3408
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pci-domain-invalid.xml b/tests/qemuxml2argvdata/qemuxml2argv-pci-domain-invalid.xml
7a3408
new file mode 100644
7a3408
index 0000000..a42d796
7a3408
--- /dev/null
7a3408
+++ b/tests/qemuxml2argvdata/qemuxml2argv-pci-domain-invalid.xml
7a3408
@@ -0,0 +1,33 @@
7a3408
+<domain type='qemu'>
7a3408
+  <name>QEMUGuest1</name>
7a3408
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
7a3408
+  <memory unit='KiB'>219136</memory>
7a3408
+  <currentMemory unit='KiB'>219136</currentMemory>
7a3408
+  <vcpu placement='static'>1</vcpu>
7a3408
+  <os>
7a3408
+    <type arch='i686' machine='pc'>hvm</type>
7a3408
+    <boot dev='hd'/>
7a3408
+  </os>
7a3408
+  <clock offset='utc'/>
7a3408
+  <on_poweroff>destroy</on_poweroff>
7a3408
+  <on_reboot>restart</on_reboot>
7a3408
+  <on_crash>destroy</on_crash>
7a3408
+  <devices>
7a3408
+    <emulator>/usr/bin/qemu</emulator>
7a3408
+    <disk type='block' device='disk'>
7a3408
+      <driver name='qemu' type='raw'/>
7a3408
+      <source dev='/dev/HostVG/QEMUGuest1'/>
7a3408
+      <target dev='hda' bus='ide'/>
7a3408
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
7a3408
+    </disk>
7a3408
+    <controller type='usb' index='0'/>
7a3408
+    <controller type='ide' index='0'/>
7a3408
+    <controller type='pci' index='0' model='pci-root'/>
7a3408
+    <interface type='user'>
7a3408
+      <mac address='00:11:22:33:44:55'/>
7a3408
+      <model type='rtl8139'/>
7a3408
+      <address type='pci' domain='0x10000' bus='0x00' slot='0x05' function='0x0'/>
7a3408
+    </interface>
7a3408
+    <memballoon model='none'/>
7a3408
+  </devices>
7a3408
+</domain>
7a3408
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pci-function-invalid.xml b/tests/qemuxml2argvdata/qemuxml2argv-pci-function-invalid.xml
7a3408
new file mode 100644
7a3408
index 0000000..c9ba5a3
7a3408
--- /dev/null
7a3408
+++ b/tests/qemuxml2argvdata/qemuxml2argv-pci-function-invalid.xml
7a3408
@@ -0,0 +1,33 @@
7a3408
+<domain type='qemu'>
7a3408
+  <name>QEMUGuest1</name>
7a3408
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
7a3408
+  <memory unit='KiB'>219136</memory>
7a3408
+  <currentMemory unit='KiB'>219136</currentMemory>
7a3408
+  <vcpu placement='static'>1</vcpu>
7a3408
+  <os>
7a3408
+    <type arch='i686' machine='pc'>hvm</type>
7a3408
+    <boot dev='hd'/>
7a3408
+  </os>
7a3408
+  <clock offset='utc'/>
7a3408
+  <on_poweroff>destroy</on_poweroff>
7a3408
+  <on_reboot>restart</on_reboot>
7a3408
+  <on_crash>destroy</on_crash>
7a3408
+  <devices>
7a3408
+    <emulator>/usr/bin/qemu</emulator>
7a3408
+    <disk type='block' device='disk'>
7a3408
+      <driver name='qemu' type='raw'/>
7a3408
+      <source dev='/dev/HostVG/QEMUGuest1'/>
7a3408
+      <target dev='hda' bus='ide'/>
7a3408
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
7a3408
+    </disk>
7a3408
+    <controller type='usb' index='0'/>
7a3408
+    <controller type='ide' index='0'/>
7a3408
+    <controller type='pci' index='0' model='pci-root'/>
7a3408
+    <interface type='user'>
7a3408
+      <mac address='00:11:22:33:44:55'/>
7a3408
+      <model type='rtl8139'/>
7a3408
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x8'/>
7a3408
+    </interface>
7a3408
+    <memballoon model='none'/>
7a3408
+  </devices>
7a3408
+</domain>
7a3408
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pci-slot-invalid.xml b/tests/qemuxml2argvdata/qemuxml2argv-pci-slot-invalid.xml
7a3408
new file mode 100644
7a3408
index 0000000..09bab49
7a3408
--- /dev/null
7a3408
+++ b/tests/qemuxml2argvdata/qemuxml2argv-pci-slot-invalid.xml
7a3408
@@ -0,0 +1,33 @@
7a3408
+<domain type='qemu'>
7a3408
+  <name>QEMUGuest1</name>
7a3408
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
7a3408
+  <memory unit='KiB'>219136</memory>
7a3408
+  <currentMemory unit='KiB'>219136</currentMemory>
7a3408
+  <vcpu placement='static'>1</vcpu>
7a3408
+  <os>
7a3408
+    <type arch='i686' machine='pc'>hvm</type>
7a3408
+    <boot dev='hd'/>
7a3408
+  </os>
7a3408
+  <clock offset='utc'/>
7a3408
+  <on_poweroff>destroy</on_poweroff>
7a3408
+  <on_reboot>restart</on_reboot>
7a3408
+  <on_crash>destroy</on_crash>
7a3408
+  <devices>
7a3408
+    <emulator>/usr/bin/qemu</emulator>
7a3408
+    <disk type='block' device='disk'>
7a3408
+      <driver name='qemu' type='raw'/>
7a3408
+      <source dev='/dev/HostVG/QEMUGuest1'/>
7a3408
+      <target dev='hda' bus='ide'/>
7a3408
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
7a3408
+    </disk>
7a3408
+    <controller type='usb' index='0'/>
7a3408
+    <controller type='ide' index='0'/>
7a3408
+    <controller type='pci' index='0' model='pci-root'/>
7a3408
+    <interface type='user'>
7a3408
+      <mac address='00:11:22:33:44:55'/>
7a3408
+      <model type='rtl8139'/>
7a3408
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x20' function='0x0'/>
7a3408
+    </interface>
7a3408
+    <memballoon model='none'/>
7a3408
+  </devices>
7a3408
+</domain>
7a3408
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
7a3408
index 4290c06..c2657d7 100644
7a3408
--- a/tests/qemuxml2argvtest.c
7a3408
+++ b/tests/qemuxml2argvtest.c
7a3408
@@ -1480,6 +1480,12 @@ mymain(void)
7a3408
     DO_TEST_PARSE_ERROR("tpm-no-backend-invalid", QEMU_CAPS_DEVICE,
7a3408
                         QEMU_CAPS_DEVICE_TPM_PASSTHROUGH, QEMU_CAPS_DEVICE_TPM_TIS);
7a3408
 
7a3408
+
7a3408
+    DO_TEST_PARSE_ERROR("pci-domain-invalid", QEMU_CAPS_DEVICE);
7a3408
+    DO_TEST_PARSE_ERROR("pci-bus-invalid", QEMU_CAPS_DEVICE);
7a3408
+    DO_TEST_PARSE_ERROR("pci-slot-invalid", QEMU_CAPS_DEVICE);
7a3408
+    DO_TEST_PARSE_ERROR("pci-function-invalid", QEMU_CAPS_DEVICE);
7a3408
+
7a3408
     DO_TEST("pci-autoadd-addr", QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE);
7a3408
     DO_TEST("pci-autoadd-idx", QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE);
7a3408
     DO_TEST("pci-many",
7a3408
-- 
7a3408
2.5.0
7a3408