diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
index e7b79579f91d184d2bcd1d3bb0f250105f9b3410..4e15d38463fe6a83ad31876f5fbdcc6206d26721 100644
--- a/src/conf/device_conf.c
+++ b/src/conf/device_conf.c
@@ -1,7 +1,7 @@
/*
* device_conf.c: device XML handling
*
- * Copyright (C) 2006-2012 Red Hat, Inc.
+ * Copyright (C) 2006-2015 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -55,12 +55,49 @@ VIR_ENUM_IMPL(virNetDevFeature,
"rdma",
"txudptnl")
-int virDevicePCIAddressIsValid(virDevicePCIAddressPtr addr)
+int virDevicePCIAddressIsValid(virDevicePCIAddressPtr addr,
+ bool report)
{
- /* PCI bus has 32 slots and 8 functions per slot */
- if (addr->slot >= 32 || addr->function >= 8)
+ if (addr->domain > 0xFFFF) {
+ if (report)
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid PCI address domain='0x%x', "
+ "must be <= 0xFFFF"),
+ addr->domain);
+ return 0;
+ }
+ if (addr->bus > 0xFF) {
+ if (report)
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid PCI address bus='0x%x', "
+ "must be <= 0xFF"),
+ addr->bus);
return 0;
- return addr->domain || addr->bus || addr->slot;
+ }
+ if (addr->slot > 0x1F) {
+ if (report)
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid PCI address slot='0x%x', "
+ "must be <= 0x1F"),
+ addr->slot);
+ return 0;
+ }
+ if (addr->function > 7) {
+ if (report)
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid PCI address function=0x%x, "
+ "must be <= 7"),
+ addr->function);
+ return 0;
+ }
+ if (!(addr->domain || addr->bus || addr->slot)) {
+ if (report)
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Invalid PCI address 0000:00:00, at least "
+ "one of domain, bus, or slot must be > 0"));
+ return 0;
+ }
+ return 1;
}
@@ -115,11 +152,8 @@ virDevicePCIAddressParseXML(xmlNodePtr node,
goto cleanup;
}
- if (!virDevicePCIAddressIsValid(addr)) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Insufficient specification for PCI address"));
+ if (!virDevicePCIAddressIsValid(addr, true))
goto cleanup;
- }
ret = 0;
diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
index 40a2b3df70a9e65a1e465e06bc8cd035cacb741a..85ce40f6831e766c8457bcc420de8d7b39c10d34 100644
--- a/src/conf/device_conf.h
+++ b/src/conf/device_conf.h
@@ -1,7 +1,7 @@
/*
* device_conf.h: device XML handling entry points
*
- * Copyright (C) 2006-2012 Red Hat, Inc.
+ * Copyright (C) 2006-2012, 2014-2015 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -81,7 +81,8 @@ typedef enum {
VIR_ENUM_DECL(virNetDevFeature)
-int virDevicePCIAddressIsValid(virDevicePCIAddressPtr addr);
+int virDevicePCIAddressIsValid(virDevicePCIAddressPtr addr,
+ bool report);
int virDevicePCIAddressParseXML(xmlNodePtr node,
virDevicePCIAddressPtr addr);
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index e4114f8210484207ed158f3cbc9cf7974586c936..18e626985c2e62f5ad65d596a7672b465c07bfca 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -3127,7 +3127,7 @@ int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
switch (info->type) {
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
- return virDevicePCIAddressIsValid(&info->addr.pci);
+ return virDevicePCIAddressIsValid(&info->addr.pci, false);
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
return 1;
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pci-bus-invalid.xml b/tests/qemuxml2argvdata/qemuxml2argv-pci-bus-invalid.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f6d0901580b91e39b6e9452848e6e5b2f2f0bb85
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-pci-bus-invalid.xml
@@ -0,0 +1,33 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219136
+ 219136
+ 1
+
+ hvm
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pci-domain-invalid.xml b/tests/qemuxml2argvdata/qemuxml2argv-pci-domain-invalid.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a42d796196207ef70a7381094f14d5980aa7af7a
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-pci-domain-invalid.xml
@@ -0,0 +1,33 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219136
+ 219136
+ 1
+
+ hvm
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pci-function-invalid.xml b/tests/qemuxml2argvdata/qemuxml2argv-pci-function-invalid.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c9ba5a396273c6f0cf5c94a079c285214b40ac5a
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-pci-function-invalid.xml
@@ -0,0 +1,33 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219136
+ 219136
+ 1
+
+ hvm
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-pci-slot-invalid.xml b/tests/qemuxml2argvdata/qemuxml2argv-pci-slot-invalid.xml
new file mode 100644
index 0000000000000000000000000000000000000000..09bab49a6558e4cd1a6259831985675512713fa7
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-pci-slot-invalid.xml
@@ -0,0 +1,33 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219136
+ 219136
+ 1
+
+ hvm
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index afd2ef3a9884cbc035858e439be6ebb47b0b0cde..25f5aa692fb5b9b9a5f1ed1367d08602a02eec17 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -1485,6 +1485,12 @@ mymain(void)
DO_TEST_PARSE_ERROR("tpm-no-backend-invalid", QEMU_CAPS_DEVICE,
QEMU_CAPS_DEVICE_TPM_PASSTHROUGH, QEMU_CAPS_DEVICE_TPM_TIS);
+
+ DO_TEST_PARSE_ERROR("pci-domain-invalid", QEMU_CAPS_DEVICE);
+ DO_TEST_PARSE_ERROR("pci-bus-invalid", QEMU_CAPS_DEVICE);
+ DO_TEST_PARSE_ERROR("pci-slot-invalid", QEMU_CAPS_DEVICE);
+ DO_TEST_PARSE_ERROR("pci-function-invalid", QEMU_CAPS_DEVICE);
+
DO_TEST("pci-autoadd-addr", QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE);
DO_TEST("pci-autoadd-idx", QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_PCI_BRIDGE);
DO_TEST("pci-many",