[PATCH] test_driver: support VIR_DOMAIN_AFFECT_LIVE in testUpdateDeviceFlags()
by John Levon
Pick up some more of the qemu_driver.c code so this function supports
both CONFIG and LIVE updates.
Note that qemuDomainUpdateDeviceFlags() passed vm->def to
virDomainDeviceDefParse() for the VIR_DOMAIN_AFFECT_CONFIG case, which
is technically incorrect; in the test driver code we'll fix this.
Signed-off-by: John Levon <john.levon(a)nutanix.com>
---
src/test/test_driver.c | 54 +++++++++++++++++++++++++++++-------------
1 file changed, 37 insertions(+), 17 deletions(-)
diff --git a/…
[View More]src/test/test_driver.c b/src/test/test_driver.c
index 712bb20563..da682da9ad 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -10239,10 +10239,10 @@ testDomainAttachDevice(virDomainPtr domain, const char *xml)
static int
-testDomainUpdateDeviceConfig(virDomainDef *vmdef,
- virDomainDeviceDef *dev,
- unsigned int parse_flags,
- virDomainXMLOption *xmlopt)
+testDomainUpdateDevice(virDomainDef *vmdef,
+ virDomainDeviceDef *dev,
+ unsigned int parse_flags,
+ virDomainXMLOption *xmlopt)
{
virDomainDiskDef *newDisk;
virDomainDeviceDef oldDev = { .type = dev->type };
@@ -10316,12 +10316,16 @@ testDomainUpdateDeviceFlags(virDomainPtr dom,
testDriver *driver = dom->conn->privateData;
virDomainObj *vm = NULL;
virObjectEvent *event = NULL;
+ virDomainDef *def = NULL;
+ virDomainDef *persistentDef = NULL;
g_autoptr(virDomainDef) vmdef = NULL;
- g_autoptr(virDomainDeviceDef) dev = NULL;
+ g_autoptr(virDomainDeviceDef) dev_live = NULL;
+ g_autoptr(virDomainDeviceDef) dev_config = NULL;
int ret = -1;
unsigned int parse_flags = 0;
- virCheckFlags(VIR_DOMAIN_AFFECT_CONFIG, -1);
+ virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+ VIR_DOMAIN_AFFECT_CONFIG, -1);
if (!(vm = testDomObjFromDomain(dom)))
goto cleanup;
@@ -10337,9 +10341,24 @@ testDomainUpdateDeviceFlags(virDomainPtr dom,
parse_flags |= VIR_DOMAIN_DEF_PARSE_INACTIVE;
}
- if (!(dev = virDomainDeviceDefParse(xml, vm->def, driver->xmlopt,
- NULL, parse_flags))) {
- goto endjob;
+ /*
+ * NB: this has diverged from qemuDomainUpdateDeviceFlags(), which uses
+ * vm->def in both cases; technically the qemu driver should do the same.
+ */
+ if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0)
+ goto cleanup;
+
+ if (def) {
+ if (!(dev_live = virDomainDeviceDefParse(xml, def, driver->xmlopt,
+ NULL, parse_flags)))
+ goto endjob;
+ }
+
+ if (persistentDef) {
+ if (!(dev_config = virDomainDeviceDefParse(xml, persistentDef,
+ driver->xmlopt, NULL,
+ parse_flags)))
+ goto endjob;
}
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
@@ -10350,18 +10369,19 @@ testDomainUpdateDeviceFlags(virDomainPtr dom,
/* virDomainDefCompatibleDevice call is delayed until we know the
* device we're going to update. */
- if ((ret = testDomainUpdateDeviceConfig(vmdef, dev,
- parse_flags,
- driver->xmlopt)) < 0)
+ if ((ret = testDomainUpdateDevice(vmdef, dev_config,
+ parse_flags,
+ driver->xmlopt)) < 0)
goto endjob;
}
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
- ret = -1;
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("live update of device '%1$s' is not supported"),
- virDomainDeviceTypeToString(dev->type));
- goto endjob;
+ /* virDomainDefCompatibleDevice call is delayed until we know the
+ * device we're going to update. */
+ if ((ret = testDomainUpdateDevice(def, dev_live,
+ parse_flags,
+ driver->xmlopt)) < 0)
+ goto endjob;
}
if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
--
2.34.1
[View Less]
9 months, 2 weeks
[PATCH] conf: Fix out-of-bounds write during cleanup of virDomainNumaDefNodeDistanceParseXML
by Rayhan Faizel
mem_nodes[i].ndistances is written outside the loop causing an out-of-bounds
write leading to heap corruption.
While we are at it, the entire cleanup portion can be removed as it can be
handled in virDomainNumaFree. One instance of VIR_FREE is also removed and
replaced with g_autofree.
This patch also adds a testcase which would be picked up by ASAN, if this
portion regresses.
Fixes: 742494eed8dbdde8b1d05a306032334e6226beea
Signed-off-by: Rayhan Faizel <rayhan.faizel(a)gmail.com>
---
…
[View More]src/conf/numa_conf.c | 30 ++++++-------------
...ance-nonexistent-sibling.x86_64-latest.err | 1 +
.../cpu-numa-distance-nonexistent-sibling.xml | 29 ++++++++++++++++++
tests/qemuxmlconftest.c | 1 +
4 files changed, 40 insertions(+), 21 deletions(-)
create mode 100644 tests/qemuxmlconfdata/cpu-numa-distance-nonexistent-sibling.x86_64-latest.err
create mode 100644 tests/qemuxmlconfdata/cpu-numa-distance-nonexistent-sibling.xml
diff --git a/src/conf/numa_conf.c b/src/conf/numa_conf.c
index d8120de6d2..0a0e2911f7 100644
--- a/src/conf/numa_conf.c
+++ b/src/conf/numa_conf.c
@@ -343,8 +343,7 @@ virDomainNumaFree(virDomainNuma *numa)
virBitmapFree(numa->mem_nodes[i].cpumask);
virBitmapFree(numa->mem_nodes[i].nodeset);
- if (numa->mem_nodes[i].ndistances > 0)
- g_free(numa->mem_nodes[i].distances);
+ g_free(numa->mem_nodes[i].distances);
g_free(numa->mem_nodes[i].caches);
}
@@ -685,9 +684,8 @@ virDomainNumaDefNodeDistanceParseXML(virDomainNuma *def,
xmlXPathContextPtr ctxt,
unsigned int cur_cell)
{
- int ret = -1;
int sibling;
- xmlNodePtr *nodes = NULL;
+ g_autofree xmlNodePtr *nodes = NULL;
size_t i, ndistances = def->nmem_nodes;
if (ndistances == 0)
@@ -698,12 +696,12 @@ virDomainNumaDefNodeDistanceParseXML(virDomainNuma *def,
return 0;
if ((sibling = virXPathNodeSet("./distances[1]/sibling", ctxt, &nodes)) < 0)
- goto cleanup;
+ return -1;
if (sibling == 0) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("NUMA distances defined without siblings"));
- goto cleanup;
+ return -1;
}
for (i = 0; i < sibling; i++) {
@@ -713,19 +711,19 @@ virDomainNumaDefNodeDistanceParseXML(virDomainNuma *def,
if (virXMLPropUInt(nodes[i], "id", 10, VIR_XML_PROP_REQUIRED,
&sibling_id) < 0)
- goto cleanup;
+ return -1;
/* The "id" needs to be within numa/cell range */
if (sibling_id >= ndistances) {
virReportError(VIR_ERR_XML_ERROR,
_("'sibling_id %1$d' does not refer to a valid cell within NUMA 'cell id %2$d'"),
sibling_id, cur_cell);
- goto cleanup;
+ return -1;
}
if (virXMLPropUInt(nodes[i], "value", 10, VIR_XML_PROP_REQUIRED,
&sibling_value) < 0)
- goto cleanup;
+ return -1;
/* Assure LOCAL_DISTANCE <= "value" <= UNREACHABLE
* and correct LOCAL_DISTANCE setting if such applies.
@@ -739,7 +737,7 @@ virDomainNumaDefNodeDistanceParseXML(virDomainNuma *def,
virReportError(VIR_ERR_XML_ERROR,
_("'value %1$d' is invalid for 'sibling id %2$d' under NUMA 'cell id %3$d'"),
sibling_value, sibling_id, cur_cell);
- goto cleanup;
+ return -1;
}
/* Apply the local / remote distance */
@@ -770,17 +768,7 @@ virDomainNumaDefNodeDistanceParseXML(virDomainNuma *def,
rdist[cur_cell].value = sibling_value;
}
- ret = 0;
-
- cleanup:
- if (ret < 0) {
- for (i = 0; i < ndistances; i++)
- VIR_FREE(def->mem_nodes[i].distances);
- def->mem_nodes[i].ndistances = 0;
- }
- VIR_FREE(nodes);
-
- return ret;
+ return 0;
}
diff --git a/tests/qemuxmlconfdata/cpu-numa-distance-nonexistent-sibling.x86_64-latest.err b/tests/qemuxmlconfdata/cpu-numa-distance-nonexistent-sibling.x86_64-latest.err
new file mode 100644
index 0000000000..4866ff5e80
--- /dev/null
+++ b/tests/qemuxmlconfdata/cpu-numa-distance-nonexistent-sibling.x86_64-latest.err
@@ -0,0 +1 @@
+XML error: 'sibling_id 2' does not refer to a valid cell within NUMA 'cell id 1'
diff --git a/tests/qemuxmlconfdata/cpu-numa-distance-nonexistent-sibling.xml b/tests/qemuxmlconfdata/cpu-numa-distance-nonexistent-sibling.xml
new file mode 100644
index 0000000000..62a6c32fbe
--- /dev/null
+++ b/tests/qemuxmlconfdata/cpu-numa-distance-nonexistent-sibling.xml
@@ -0,0 +1,29 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>16</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc'>hvm</type>
+ <boot dev='network'/>
+ </os>
+ <cpu>
+ <topology sockets='2' dies='1' cores='4' threads='2'/>
+ <numa>
+ <cell id='1' cpus='8-15' memory='109550' unit='KiB'>
+ <distances>
+ <sibling id='2' value='10'/>
+ </distances>
+ </cell>
+ <cell id='0' cpus='0-7' memory='109550' unit='KiB'/>
+ </numa>
+ </cpu>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
+ </devices>
+</domain>
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index 4a711fceeb..af49934c33 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -2160,6 +2160,7 @@ mymain(void)
DO_TEST_CAPS_LATEST_PARSE_ERROR("cpu-numa3");
DO_TEST_CAPS_LATEST("cpu-numa-disjoint");
DO_TEST_CAPS_LATEST("cpu-numa-memshared");
+ DO_TEST_CAPS_LATEST_PARSE_ERROR("cpu-numa-distance-nonexistent-sibling");
/* host-model cpu expansion depends on the cpu reported by qemu and thus
* we invoke it for all real capability dumps we have */
--
2.34.1
[View Less]
9 months, 2 weeks
[PATCH 0/2] qemu: support logging config for swtpm
by Daniel P. Berrangé
When debugging guest problems with TPMs it is helpful to be able to
have full swtpm logging. This isn't possible currently and manually
restarting the swtpm process of a running guest is disruptive.
Daniel P. Berrangé (2):
conf: add support for 'debug' parameter on TPM emulator
qemu: set swtpm log level parameter
docs/formatdomain.rst | 6 ++++--
src/conf/domain_conf.c | 7 +++++++
src/conf/domain_conf.h | 1 +
src/conf/…
[View More]schemas/domaincommon.rng | 5 +++++
src/qemu/qemu_tpm.c | 6 +++++-
tests/qemuxmlconfdata/tpm-emulator-tpm2.xml | 2 +-
6 files changed, 23 insertions(+), 4 deletions(-)
--
2.45.1
[View Less]
9 months, 2 weeks
[PATCH v2 0/8] ch: support restore with network devices
by Purna Pavan Chandra
Current ch driver supports restore only for domains without any network
configuration defined. This was because libvirt explicitly passes network fds
and CH did not had support to restore with new net FDS. This support has been
added recently, https://github.com/cloud-hypervisor/cloud-hypervisor/pull/6402
The changes in this patch series includes moving to socket communication for
restore api, create new net fds and pass them via SCM_RIGHTS to CH.
New changes in v2:
* Reword of few commints
* …
[View More]Add version checks in save/restore validations
* Add use_timeout in chSocketRecv
* Address Praveen Paladugu's comments
v1: https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/thread/PT...
Purna Pavan Chandra (8):
ch: report response message instead of just code
ch: Pass net ids explicitly during vm creation
ch: refactor chProcessAddNetworkDevices
ch: support poll with -1 in chSocketRecv
ch: use monitor socket fd to send restore request
ch: refactor virCHMonitorSaveVM
ch: support restore with net devices
ch: kill CH process if restore fails
src/ch/ch_capabilities.c | 6 +
src/ch/ch_capabilities.h | 1 +
src/ch/ch_driver.c | 29 +++--
src/ch/ch_monitor.c | 62 +++++++----
src/ch/ch_monitor.h | 6 +-
src/ch/ch_process.c | 233 +++++++++++++++++++++++++++++++--------
6 files changed, 254 insertions(+), 83 deletions(-)
--
2.34.1
[View Less]
9 months, 2 weeks
[PATCH] conf: Fix out-of-bounds write during cleanup of virDomainNumaDefNodeDistanceParseXML
by Rayhan Faizel
mem_nodes[i].ndistances is written outside the loop causing an out-of-bounds
write leading to heap corruption.
While we are at it, the entire cleanup portion can be removed as it can be
handled in virDomainNumaFree. One instance of VIR_FREE is also removed and
replaced with g_autofree.
This patch also adds a testcase which would be picked up by ASAN, if this
portion regresses.
Signed-off-by: Rayhan Faizel <rayhan.faizel(a)gmail.com>
---
src/conf/numa_conf.c | …
[View More]30 ++++++-------------
...ance-nonexistent-sibling.x86_64-latest.err | 1 +
.../cpu-numa-distance-nonexistent-sibling.xml | 29 ++++++++++++++++++
tests/qemuxmlconftest.c | 1 +
4 files changed, 40 insertions(+), 21 deletions(-)
create mode 100644 tests/qemuxmlconfdata/cpu-numa-distance-nonexistent-sibling.x86_64-latest.err
create mode 100644 tests/qemuxmlconfdata/cpu-numa-distance-nonexistent-sibling.xml
diff --git a/src/conf/numa_conf.c b/src/conf/numa_conf.c
index d8120de6d2..0a0e2911f7 100644
--- a/src/conf/numa_conf.c
+++ b/src/conf/numa_conf.c
@@ -343,8 +343,7 @@ virDomainNumaFree(virDomainNuma *numa)
virBitmapFree(numa->mem_nodes[i].cpumask);
virBitmapFree(numa->mem_nodes[i].nodeset);
- if (numa->mem_nodes[i].ndistances > 0)
- g_free(numa->mem_nodes[i].distances);
+ g_free(numa->mem_nodes[i].distances);
g_free(numa->mem_nodes[i].caches);
}
@@ -685,9 +684,8 @@ virDomainNumaDefNodeDistanceParseXML(virDomainNuma *def,
xmlXPathContextPtr ctxt,
unsigned int cur_cell)
{
- int ret = -1;
int sibling;
- xmlNodePtr *nodes = NULL;
+ g_autofree xmlNodePtr *nodes = NULL;
size_t i, ndistances = def->nmem_nodes;
if (ndistances == 0)
@@ -698,12 +696,12 @@ virDomainNumaDefNodeDistanceParseXML(virDomainNuma *def,
return 0;
if ((sibling = virXPathNodeSet("./distances[1]/sibling", ctxt, &nodes)) < 0)
- goto cleanup;
+ return -1;
if (sibling == 0) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("NUMA distances defined without siblings"));
- goto cleanup;
+ return -1;
}
for (i = 0; i < sibling; i++) {
@@ -713,19 +711,19 @@ virDomainNumaDefNodeDistanceParseXML(virDomainNuma *def,
if (virXMLPropUInt(nodes[i], "id", 10, VIR_XML_PROP_REQUIRED,
&sibling_id) < 0)
- goto cleanup;
+ return -1;
/* The "id" needs to be within numa/cell range */
if (sibling_id >= ndistances) {
virReportError(VIR_ERR_XML_ERROR,
_("'sibling_id %1$d' does not refer to a valid cell within NUMA 'cell id %2$d'"),
sibling_id, cur_cell);
- goto cleanup;
+ return -1;
}
if (virXMLPropUInt(nodes[i], "value", 10, VIR_XML_PROP_REQUIRED,
&sibling_value) < 0)
- goto cleanup;
+ return -1;
/* Assure LOCAL_DISTANCE <= "value" <= UNREACHABLE
* and correct LOCAL_DISTANCE setting if such applies.
@@ -739,7 +737,7 @@ virDomainNumaDefNodeDistanceParseXML(virDomainNuma *def,
virReportError(VIR_ERR_XML_ERROR,
_("'value %1$d' is invalid for 'sibling id %2$d' under NUMA 'cell id %3$d'"),
sibling_value, sibling_id, cur_cell);
- goto cleanup;
+ return -1;
}
/* Apply the local / remote distance */
@@ -770,17 +768,7 @@ virDomainNumaDefNodeDistanceParseXML(virDomainNuma *def,
rdist[cur_cell].value = sibling_value;
}
- ret = 0;
-
- cleanup:
- if (ret < 0) {
- for (i = 0; i < ndistances; i++)
- VIR_FREE(def->mem_nodes[i].distances);
- def->mem_nodes[i].ndistances = 0;
- }
- VIR_FREE(nodes);
-
- return ret;
+ return 0;
}
diff --git a/tests/qemuxmlconfdata/cpu-numa-distance-nonexistent-sibling.x86_64-latest.err b/tests/qemuxmlconfdata/cpu-numa-distance-nonexistent-sibling.x86_64-latest.err
new file mode 100644
index 0000000000..4866ff5e80
--- /dev/null
+++ b/tests/qemuxmlconfdata/cpu-numa-distance-nonexistent-sibling.x86_64-latest.err
@@ -0,0 +1 @@
+XML error: 'sibling_id 2' does not refer to a valid cell within NUMA 'cell id 1'
diff --git a/tests/qemuxmlconfdata/cpu-numa-distance-nonexistent-sibling.xml b/tests/qemuxmlconfdata/cpu-numa-distance-nonexistent-sibling.xml
new file mode 100644
index 0000000000..62a6c32fbe
--- /dev/null
+++ b/tests/qemuxmlconfdata/cpu-numa-distance-nonexistent-sibling.xml
@@ -0,0 +1,29 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>16</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc'>hvm</type>
+ <boot dev='network'/>
+ </os>
+ <cpu>
+ <topology sockets='2' dies='1' cores='4' threads='2'/>
+ <numa>
+ <cell id='1' cpus='8-15' memory='109550' unit='KiB'>
+ <distances>
+ <sibling id='2' value='10'/>
+ </distances>
+ </cell>
+ <cell id='0' cpus='0-7' memory='109550' unit='KiB'/>
+ </numa>
+ </cpu>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
+ </devices>
+</domain>
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index 4a711fceeb..af49934c33 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -2160,6 +2160,7 @@ mymain(void)
DO_TEST_CAPS_LATEST_PARSE_ERROR("cpu-numa3");
DO_TEST_CAPS_LATEST("cpu-numa-disjoint");
DO_TEST_CAPS_LATEST("cpu-numa-memshared");
+ DO_TEST_CAPS_LATEST_PARSE_ERROR("cpu-numa-distance-nonexistent-sibling");
/* host-model cpu expansion depends on the cpu reported by qemu and thus
* we invoke it for all real capability dumps we have */
--
2.34.1
[View Less]
9 months, 2 weeks
[PATCH] test_driver: add testUpdateDeviceFlags implementation
by John Levon
Add basic coverage of device update; for now, only support disk updates
until other types are needed or tested.
Signed-off-by: John Levon <john.levon(a)nutanix.com>
---
src/test/test_driver.c | 127 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 127 insertions(+)
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 40fb8a467d..213fbdbccb 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -41,6 +41,7 @@
#include "domain_conf.h"
#include "…
[View More]domain_driver.h"
#include "domain_event.h"
+#include "domain_postparse.h"
#include "domain_validate.h"
#include "network_event.h"
#include "snapshot_conf.h"
@@ -10237,6 +10238,131 @@ testDomainAttachDevice(virDomainPtr domain, const char *xml)
}
+static int
+testDomainUpdateDeviceConfig(virDomainDef *vmdef,
+ virDomainDeviceDef *dev,
+ unsigned int parse_flags,
+ virDomainXMLOption *xmlopt)
+{
+ virDomainDiskDef *newDisk;
+ virDomainDeviceDef oldDev = { .type = dev->type };
+ int pos;
+
+ switch (dev->type) {
+ case VIR_DOMAIN_DEVICE_DISK:
+ newDisk = dev->data.disk;
+ if ((pos = virDomainDiskIndexByName(vmdef, newDisk->dst, false)) < 0) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("target %1$s doesn't exist."), newDisk->dst);
+ return -1;
+ }
+
+ oldDev.data.disk = vmdef->disks[pos];
+ if (virDomainDefCompatibleDevice(vmdef, dev, &oldDev,
+ VIR_DOMAIN_DEVICE_ACTION_UPDATE,
+ false) < 0)
+ return -1;
+
+ virDomainDiskDefFree(vmdef->disks[pos]);
+ vmdef->disks[pos] = newDisk;
+ dev->data.disk = NULL;
+ break;
+
+ // TODO: support these here once tested.
+ case VIR_DOMAIN_DEVICE_GRAPHICS:
+ case VIR_DOMAIN_DEVICE_NET:
+ case VIR_DOMAIN_DEVICE_MEMORY:
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+ _("persistent update of device '%1$s' is not supported by test driver"),
+ virDomainDeviceTypeToString(dev->type));
+ return -1;
+
+ case VIR_DOMAIN_DEVICE_FS:
+ case VIR_DOMAIN_DEVICE_INPUT:
+ case VIR_DOMAIN_DEVICE_SOUND:
+ case VIR_DOMAIN_DEVICE_VIDEO:
+ case VIR_DOMAIN_DEVICE_WATCHDOG:
+ case VIR_DOMAIN_DEVICE_HUB:
+ case VIR_DOMAIN_DEVICE_SMARTCARD:
+ case VIR_DOMAIN_DEVICE_MEMBALLOON:
+ case VIR_DOMAIN_DEVICE_NVRAM:
+ case VIR_DOMAIN_DEVICE_RNG:
+ case VIR_DOMAIN_DEVICE_SHMEM:
+ case VIR_DOMAIN_DEVICE_LEASE:
+ case VIR_DOMAIN_DEVICE_HOSTDEV:
+ case VIR_DOMAIN_DEVICE_CONTROLLER:
+ case VIR_DOMAIN_DEVICE_REDIRDEV:
+ case VIR_DOMAIN_DEVICE_CHR:
+ case VIR_DOMAIN_DEVICE_NONE:
+ case VIR_DOMAIN_DEVICE_TPM:
+ case VIR_DOMAIN_DEVICE_PANIC:
+ case VIR_DOMAIN_DEVICE_IOMMU:
+ case VIR_DOMAIN_DEVICE_VSOCK:
+ case VIR_DOMAIN_DEVICE_AUDIO:
+ case VIR_DOMAIN_DEVICE_CRYPTO:
+ case VIR_DOMAIN_DEVICE_LAST:
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+ _("persistent update of device '%1$s' is not supported"),
+ virDomainDeviceTypeToString(dev->type));
+ return -1;
+ }
+
+ if (virDomainDefPostParse(vmdef, parse_flags, xmlopt, NULL) < 0)
+ return -1;
+
+ return 0;
+}
+
+
+static int
+testDomainUpdateDeviceFlags(virDomainPtr dom,
+ const char *xml,
+ unsigned int flags)
+{
+ testDriver *driver = dom->conn->privateData;
+ virDomainObj *vm = NULL;
+ g_autoptr(virDomainDef) vmdef = NULL;
+ g_autoptr(virDomainDeviceDef) dev = NULL;
+ int ret = -1;
+ unsigned int parse_flags = 0;
+
+ virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
+ VIR_DOMAIN_AFFECT_CONFIG |
+ VIR_DOMAIN_DEVICE_MODIFY_FORCE, -1);
+
+ if (!(vm = testDomObjFromDomain(dom)))
+ goto cleanup;
+
+ if (virDomainObjBeginJob(vm, VIR_JOB_MODIFY) < 0)
+ goto cleanup;
+
+ if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
+ goto endjob;
+
+ if ((flags & VIR_DOMAIN_AFFECT_CONFIG) &&
+ !(flags & VIR_DOMAIN_AFFECT_LIVE))
+ parse_flags |= VIR_DOMAIN_DEF_PARSE_INACTIVE;
+
+ if (!(dev = virDomainDeviceDefParse(xml, vm->def, driver->xmlopt,
+ NULL, parse_flags)))
+ goto endjob;
+
+ /* virDomainDefCompatibleDevice call is delayed until we know the
+ * device we're going to update. */
+ if ((ret = testDomainUpdateDeviceConfig(vm->def, dev,
+ parse_flags,
+ driver->xmlopt)) < 0)
+ goto endjob;
+
+ endjob:
+ virDomainObjEndJob(vm);
+
+ cleanup:
+ virDomainObjEndAPI(&vm);
+ return ret;
+}
+
+
/* search for a hostdev matching dev and detach it */
static int
testDomainDetachPrepHostdev(virDomainObj *vm,
@@ -10456,6 +10582,7 @@ static virHypervisorDriver testHypervisorDriver = {
.domainAttachDevice = testDomainAttachDevice, /* 10.0.0 */
.domainAttachDeviceFlags = testDomainAttachDeviceFlags, /* 10.0.0 */
.domainDetachDeviceAlias = testDomainDetachDeviceAlias, /* 10.0.0 */
+ .domainUpdateDeviceFlags = testDomainUpdateDeviceFlags, /* 10.6.0 */
.domainCreateXML = testDomainCreateXML, /* 0.1.4 */
.domainCreateXMLWithFiles = testDomainCreateXMLWithFiles, /* 5.7.0 */
.domainLookupByID = testDomainLookupByID, /* 0.1.1 */
--
2.34.1
[View Less]
9 months, 2 weeks
[PATCH v2] tests: Move domainEventState initialization to qemuTestDriverInit
by Rayhan Faizel
Under the test environment, driver->domainEventState is uninitialized. If a
disk gets dropped, it will attempt to queue an event which will cause a
segmentation fault. This crash does not occur during normal use.
This patch moves driver->domainEventState initialization from qemuhotplugtest
to qemuTestDriverInit in testutilsqemu (Credit goes to Michal Privoznik as he
had already provided the diff).
An additional test case is added to test dropping of disks with startupPolicy
set as …
[View More]optional.
Signed-off-by: Rayhan Faizel <rayhan.faizel(a)gmail.com>
---
As the patch title has completely changed,
v1: https://lists.libvirt.org/archives/list/devel@lists.libvirt.org/thread/44...
[Changes in v2]
- Move domainEventState initialization instead of adding a NULL check
tests/qemuhotplugtest.c | 3 --
...tuppolicy-optional-drop.x86_64-latest.args | 33 ++++++++++++++++
...rtuppolicy-optional-drop.x86_64-latest.xml | 38 +++++++++++++++++++
.../disk-startuppolicy-optional-drop.xml | 23 +++++++++++
tests/qemuxmlconftest.c | 1 +
tests/testutilsqemu.c | 4 ++
6 files changed, 99 insertions(+), 3 deletions(-)
create mode 100644 tests/qemuxmlconfdata/disk-startuppolicy-optional-drop.x86_64-latest.args
create mode 100644 tests/qemuxmlconfdata/disk-startuppolicy-optional-drop.x86_64-latest.xml
create mode 100644 tests/qemuxmlconfdata/disk-startuppolicy-optional-drop.xml
diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c
index d935ad58ed..f707121c47 100644
--- a/tests/qemuhotplugtest.c
+++ b/tests/qemuhotplugtest.c
@@ -501,9 +501,6 @@ mymain(void)
virEventRegisterDefaultImpl();
- if (!(driver.domainEventState = virObjectEventStateNew()))
- return EXIT_FAILURE;
-
driver.lockManager = virLockManagerPluginNew("nop", "qemu",
driver.config->configBaseDir,
0);
diff --git a/tests/qemuxmlconfdata/disk-startuppolicy-optional-drop.x86_64-latest.args b/tests/qemuxmlconfdata/disk-startuppolicy-optional-drop.x86_64-latest.args
new file mode 100644
index 0000000000..13ddbc1a5d
--- /dev/null
+++ b/tests/qemuxmlconfdata/disk-startuppolicy-optional-drop.x86_64-latest.args
@@ -0,0 +1,33 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1 \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.local/share \
+XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.cache \
+XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
+/usr/bin/qemu-system-x86_64 \
+-name guest=QEMUGuest1,debug-threads=on \
+-S \
+-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-QEMUGuest1/master-key.aes"}' \
+-machine pc,usb=off,dump-guest-core=off,memory-backend=pc.ram,acpi=off \
+-accel tcg \
+-cpu qemu64 \
+-m size=219136k \
+-object '{"qom-type":"memory-backend-ram","id":"pc.ram","size":224395264}' \
+-overcommit mem-lock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-boot strict=on \
+-device '{"driver":"piix3-usb-uhci","id":"usb","bus":"pci.0","addr":"0x1.0x2"}' \
+-device '{"driver":"lsi","id":"scsi0","bus":"pci.0","addr":"0x2"}' \
+-audiodev '{"id":"audio1","driver":"none"}' \
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxmlconfdata/disk-startuppolicy-optional-drop.x86_64-latest.xml b/tests/qemuxmlconfdata/disk-startuppolicy-optional-drop.x86_64-latest.xml
new file mode 100644
index 0000000000..27d0639109
--- /dev/null
+++ b/tests/qemuxmlconfdata/disk-startuppolicy-optional-drop.x86_64-latest.xml
@@ -0,0 +1,38 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <cpu mode='custom' match='exact' check='none'>
+ <model fallback='forbid'>qemu64</model>
+ </cpu>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
+ <disk type='volume' device='disk'>
+ <driver name='qemu'/>
+ <source pool='inactive' volume='inactive' startupPolicy='optional'/>
+ <target dev='sda' bus='scsi'/>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <controller type='usb' index='0' model='piix3-uhci'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'/>
+ <controller type='scsi' index='0' model='lsilogic'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
+ </controller>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <audio id='1' type='none'/>
+ <memballoon model='none'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxmlconfdata/disk-startuppolicy-optional-drop.xml b/tests/qemuxmlconfdata/disk-startuppolicy-optional-drop.xml
new file mode 100644
index 0000000000..c6c59978c6
--- /dev/null
+++ b/tests/qemuxmlconfdata/disk-startuppolicy-optional-drop.xml
@@ -0,0 +1,23 @@
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
+ <disk type='volume' device='disk'>
+ <source pool='inactive' volume='inactive' startupPolicy='optional'/>
+ <target dev='sda'/>
+ </disk>
+ <memballoon model='none'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index 4a711fceeb..2a495cc892 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -2947,6 +2947,7 @@ mymain(void)
DO_TEST_CAPS_LATEST_FAILURE("disk-network-iscsi-zero-hosts-invalid")
DO_TEST_CAPS_LATEST_PARSE_ERROR("hostdev-scsi-vhost-rawio-invalid")
DO_TEST_CAPS_LATEST_PARSE_ERROR("hostdev-scsi-vhost-sgio-invalid")
+ DO_TEST_CAPS_LATEST("disk-startuppolicy-optional-drop")
/* check that all input files were actually used here */
if (testConfXMLCheck(existingTestCases) < 0)
diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c
index d70850cb5d..ee6cae218a 100644
--- a/tests/testutilsqemu.c
+++ b/tests/testutilsqemu.c
@@ -236,6 +236,7 @@ void qemuTestDriverFree(virQEMUDriver *driver)
virObjectUnref(driver->caps);
virObjectUnref(driver->config);
virObjectUnref(driver->securityManager);
+ virObjectUnref(driver->domainEventState);
g_clear_object(&driver->nbdkitCapsCache);
virCPUDefFree(cpuDefault);
@@ -369,6 +370,9 @@ int qemuTestDriverInit(virQEMUDriver *driver)
if (!(driver->securityManager = virSecurityManagerNewStack(mgr)))
goto error;
+ if (!(driver->domainEventState = virObjectEventStateNew()))
+ goto error;
+
qemuTestSetHostCPU(driver, driver->hostarch, NULL);
VIR_FREE(cfg->vncTLSx509certdir);
--
2.34.1
[View Less]
9 months, 2 weeks
[PATCH v1] security_manager: Ensure top lock is acquired before nested locks
by hongmianquan
We need to ensure top lock is acquired before nested lock. Otherwise deadlock
issues may arise. We have the stack security driver, which internally manages
other security drivers, we call them "top" and "nested".
We call virSecurityStackPreFork() to lock the top one, and it also locks
and then unlocks the nested drivers prior to fork. Then in qemuSecurityPostFork(),
it unlocks the top one, but not the nested ones. Thus, if one of the nested
drivers ("dac" or "selinux") is still locked, it will …
[View More]cause a deadlock.
We discovered this case: the nested list obtained through the qemuSecurityGetNested()
will be locked for subsequent use, such as in virQEMUDriverCreateCapabilities(),
where the nested list is locked using qemuSecurityGetDOI, but the top one is not locked beforehand.
The problem stack is as follows:
libvirtd thread1 libvirtd thread2 child libvirtd
| | |
| | |
virsh capabilities qemuProcessLanuch |
| | |
| lock top |
| | |
lock nested | |
| | |
| fork------------------->|(held nested lock)
| | |
| | |
unlock nested unlock top unlock top
|
|
qemuSecuritySetSocketLabel
|
|
lock nested (deadlock)
In this commit, we ensure that the top lock is acquired before the nested lock,
so during fork, it's not possible for another task to acquire the nested lock.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1303031
Signed-off-by: hongmianquan <hongmianquan(a)bytedance.com>
---
src/libvirt_private.syms | 3 ++-
src/qemu/qemu_conf.c | 9 ++++++++-
src/qemu/qemu_driver.c | 16 +++++++++-------
src/qemu/qemu_security.h | 2 ++
src/security/security_manager.c | 22 ++++++++++++++++++++++
src/security/security_manager.h | 2 ++
6 files changed, 45 insertions(+), 9 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index bac4a8a366..39cdb90772 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1806,7 +1806,8 @@ virSecurityManagerTransactionAbort;
virSecurityManagerTransactionCommit;
virSecurityManagerTransactionStart;
virSecurityManagerVerify;
-
+virSecurityManagerStackLock;
+virSecurityManagerStackUnlock;
# security/security_util.h
virSecurityXATTRNamespaceDefined;
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 4050a82341..21f0739fd5 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1380,6 +1380,9 @@ virCaps *virQEMUDriverCreateCapabilities(virQEMUDriver *driver)
return NULL;
}
+ /* Ensure top lock is acquired before nested locks */
+ qemuSecurityStackLock(driver->securityManager);
+
/* access sec drivers and create a sec model for each one */
if (!(sec_managers = qemuSecurityGetNested(driver->securityManager)))
return NULL;
@@ -1402,8 +1405,10 @@ virCaps *virQEMUDriverCreateCapabilities(virQEMUDriver *driver)
lbl = qemuSecurityGetBaseLabel(sec_managers[i], virtTypes[j]);
type = virDomainVirtTypeToString(virtTypes[j]);
if (lbl &&
- virCapabilitiesHostSecModelAddBaseLabel(sm, type, lbl) < 0)
+ virCapabilitiesHostSecModelAddBaseLabel(sm, type, lbl) < 0) {
+ qemuSecurityStackUnlock(driver->securityManager);
return NULL;
+ }
}
VIR_DEBUG("Initialized caps for security driver \"%s\" with "
@@ -1412,6 +1417,8 @@ virCaps *virQEMUDriverCreateCapabilities(virQEMUDriver *driver)
caps->host.numa = virCapabilitiesHostNUMANewHost();
caps->host.cpu = virQEMUDriverGetHostCPU(driver);
+
+ qemuSecurityStackUnlock(driver->securityManager);
return g_steal_pointer(&caps);
}
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index fc1704f4fc..c980a0990f 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -560,7 +560,6 @@ qemuStateInitialize(bool privileged,
bool autostart = true;
size_t i;
const char *defsecmodel = NULL;
- g_autofree virSecurityManager **sec_managers = NULL;
g_autoptr(virIdentity) identity = virIdentityGetCurrent();
qemu_driver = g_new0(virQEMUDriver, 1);
@@ -835,11 +834,8 @@ qemuStateInitialize(bool privileged,
if (!qemu_driver->qemuCapsCache)
goto error;
- if (!(sec_managers = qemuSecurityGetNested(qemu_driver->securityManager)))
- goto error;
-
- if (sec_managers[0] != NULL)
- defsecmodel = qemuSecurityGetModel(sec_managers[0]);
+ if (qemu_driver->securityManager != NULL)
+ defsecmodel = qemuSecurityGetModel(qemu_driver->securityManager);
if (!(qemu_driver->xmlopt = virQEMUDriverCreateXMLConf(qemu_driver,
defsecmodel)))
@@ -5663,7 +5659,12 @@ static int qemuDomainGetSecurityLabelList(virDomainPtr dom,
ret = 0;
} else {
int len = 0;
- virSecurityManager ** mgrs = qemuSecurityGetNested(driver->securityManager);
+ virSecurityManager ** mgrs = NULL;
+
+ /* Ensure top lock is acquired before nested locks */
+ qemuSecurityStackLock(driver->securityManager);
+
+ mgrs = qemuSecurityGetNested(driver->securityManager);
if (!mgrs)
goto cleanup;
@@ -5688,6 +5689,7 @@ static int qemuDomainGetSecurityLabelList(virDomainPtr dom,
}
cleanup:
+ qemuSecurityStackUnlock(driver->securityManager);
virDomainObjEndAPI(&vm);
return ret;
}
diff --git a/src/qemu/qemu_security.h b/src/qemu/qemu_security.h
index 41da33debc..19fcb3c939 100644
--- a/src/qemu/qemu_security.h
+++ b/src/qemu/qemu_security.h
@@ -151,3 +151,5 @@ int qemuSecurityCommandRun(virQEMUDriver *driver,
#define qemuSecuritySetTapFDLabel virSecurityManagerSetTapFDLabel
#define qemuSecurityStackAddNested virSecurityManagerStackAddNested
#define qemuSecurityVerify virSecurityManagerVerify
+#define qemuSecurityStackLock virSecurityManagerStackLock
+#define qemuSecurityStackUnlock virSecurityManagerStackUnlock
\ No newline at end of file
diff --git a/src/security/security_manager.c b/src/security/security_manager.c
index 24f2f3d3dc..c49c4f708f 100644
--- a/src/security/security_manager.c
+++ b/src/security/security_manager.c
@@ -989,6 +989,28 @@ virSecurityManagerGetNested(virSecurityManager *mgr)
return list;
}
+/*
+ * Usually called before virSecurityManagerGetNested().
+ * We need to ensure locking the stack security manager before
+ * locking the nested security manager to maintain the correct
+ * synchronization state.
+ * It must be followed by a call virSecurityManagerStackUnlock().
+ */
+void
+virSecurityManagerStackLock(virSecurityManager *mgr)
+{
+ if (STREQ("stack", mgr->drv->name))
+ virObjectLock(mgr);
+}
+
+
+void
+virSecurityManagerStackUnlock(virSecurityManager *mgr)
+{
+ if (STREQ("stack", mgr->drv->name))
+ virObjectUnlock(mgr);
+}
+
/**
* virSecurityManagerDomainSetPathLabel:
diff --git a/src/security/security_manager.h b/src/security/security_manager.h
index a416af3215..bb6d22bc31 100644
--- a/src/security/security_manager.h
+++ b/src/security/security_manager.h
@@ -158,6 +158,8 @@ int virSecurityManagerSetTapFDLabel(virSecurityManager *mgr,
char *virSecurityManagerGetMountOptions(virSecurityManager *mgr,
virDomainDef *vm);
virSecurityManager ** virSecurityManagerGetNested(virSecurityManager *mgr);
+void virSecurityManagerStackLock(virSecurityManager *mgr);
+void virSecurityManagerStackUnlock(virSecurityManager *mgr);
typedef enum {
VIR_SECURITY_DOMAIN_IMAGE_LABEL_BACKING_CHAIN = 1 << 0,
--
2.11.0
[View Less]
9 months, 2 weeks
Re: [PATCH v1] security_manager: Ensure top lock is acquired before
nested locks
by ByteDance
Yes, we have recently encountered this issue, and it is exactly the same as the scenario described in the bug report. We investigated the code and found this potential problem. The issue occurs when collecting information through the ‘virsh capabilities' while concurrently creating vm. The higher the frequency and concurrency, the more likely the issue will reproduce. We believe this is a very rare bug; our environment has been running for three years, and we've only encountered this issue once.…
[View More] To successfully reproduce the problem, we constructed a test case by adding a sleep between the lock nested and unlock. But we still need to try to fix this issue, even though the probability is very low.
[View Less]
9 months, 2 weeks
[PATCH v2] conf: Fix rawio/sgio checks for non-scsi hostdev devices
by Rayhan Faizel
The current hostdev parsing logic sets rawio or sgio even if the hostdev type
is not 'scsi'. The rawio field in virDomainHostdevSubsysSCSI overlaps with
wwpn field in virDomainHostdevSubsysSCSIVHost, consequently setting a bogus
pointer value such as 0x1 or 0x2 from virDomainHostdevSubsysSCSIVHost's
point of view. This leads to a segmentation fault when it attempts to free
wwpn.
While setting sgio does not appear to crash, it shares the same flawed logic
as setting rawio.
Instead, we ensure …
[View More]these are set only after the hostdev type check succeeds.
This patch also adds two test cases to exercise both scenarios.
Fixes: bdb95b520c53f9bacc6504fc51381bac4813be38
Signed-off-by: Rayhan Faizel <rayhan.faizel(a)gmail.com>
---
[Changes in v2]
- Reworked fix to use temporary variables instead of xpath queries.
- Added comments for future reference.
- Mention fixed commit.
src/conf/domain_conf.c | 26 +++++++++---
...scsi-vhost-rawio-invalid.x86_64-latest.err | 1 +
.../hostdev-scsi-vhost-rawio-invalid.xml | 41 +++++++++++++++++++
...-scsi-vhost-sgio-invalid.x86_64-latest.err | 1 +
.../hostdev-scsi-vhost-sgio-invalid.xml | 41 +++++++++++++++++++
tests/qemuxmlconftest.c | 2 +
6 files changed, 106 insertions(+), 6 deletions(-)
create mode 100644 tests/qemuxmlconfdata/hostdev-scsi-vhost-rawio-invalid.x86_64-latest.err
create mode 100644 tests/qemuxmlconfdata/hostdev-scsi-vhost-rawio-invalid.xml
create mode 100644 tests/qemuxmlconfdata/hostdev-scsi-vhost-sgio-invalid.x86_64-latest.err
create mode 100644 tests/qemuxmlconfdata/hostdev-scsi-vhost-sgio-invalid.xml
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 334152c4ff..7033b4e9fe 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -6220,6 +6220,8 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
virDomainHostdevSubsysMediatedDev *mdevsrc = &def->source.subsys.u.mdev;
virTristateBool managed;
g_autofree char *model = NULL;
+ virDomainDeviceSGIO sgio;
+ virTristateBool rawio;
int rv;
/* @managed can be read from the xml document - it is always an
@@ -6259,7 +6261,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
if ((rv = virXMLPropEnum(node, "sgio",
virDomainDeviceSGIOTypeFromString,
VIR_XML_PROP_NONZERO,
- &scsisrc->sgio)) < 0) {
+ &sgio)) < 0) {
return -1;
}
@@ -6269,18 +6271,30 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
_("sgio is only supported for scsi host device"));
return -1;
}
+
+ /* Set sgio only after checking if hostdev type is 'scsi' to avoid
+ * clobbering other union structures.
+ */
+ scsisrc->sgio = sgio;
}
if ((rv = virXMLPropTristateBool(node, "rawio",
VIR_XML_PROP_NONE,
- &scsisrc->rawio)) < 0) {
+ &rawio)) < 0) {
return -1;
}
- if (rv > 0 && def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) {
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("rawio is only supported for scsi host device"));
- return -1;
+ if (rv > 0) {
+ if (def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("rawio is only supported for scsi host device"));
+ return -1;
+ }
+
+ /* Set rawio only after checking if hostdev type is 'scsi' to avoid
+ * clobbering other union structures.
+ */
+ scsisrc->rawio = rawio;
}
if (def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV &&
diff --git a/tests/qemuxmlconfdata/hostdev-scsi-vhost-rawio-invalid.x86_64-latest.err b/tests/qemuxmlconfdata/hostdev-scsi-vhost-rawio-invalid.x86_64-latest.err
new file mode 100644
index 0000000000..ddaf449658
--- /dev/null
+++ b/tests/qemuxmlconfdata/hostdev-scsi-vhost-rawio-invalid.x86_64-latest.err
@@ -0,0 +1 @@
+XML error: rawio is only supported for scsi host device
diff --git a/tests/qemuxmlconfdata/hostdev-scsi-vhost-rawio-invalid.xml b/tests/qemuxmlconfdata/hostdev-scsi-vhost-rawio-invalid.xml
new file mode 100644
index 0000000000..80760ab941
--- /dev/null
+++ b/tests/qemuxmlconfdata/hostdev-scsi-vhost-rawio-invalid.xml
@@ -0,0 +1,41 @@
+<domain type='qemu'>
+ <name>QEMUGuest2</name>
+ <uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest2'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <controller type='scsi' index='0' model='virtio-scsi'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
+ </controller>
+ <controller type='usb' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+ </controller>
+ <controller type='ide' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'/>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <hostdev mode='subsystem' type='scsi_host' rawio='yes'>
+ <source protocol='vhost' wwpn='naa.5123456789abcde0'/>
+ </hostdev>
+ <memballoon model='virtio'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
+ </memballoon>
+ </devices>
+</domain>
diff --git a/tests/qemuxmlconfdata/hostdev-scsi-vhost-sgio-invalid.x86_64-latest.err b/tests/qemuxmlconfdata/hostdev-scsi-vhost-sgio-invalid.x86_64-latest.err
new file mode 100644
index 0000000000..32256aad1c
--- /dev/null
+++ b/tests/qemuxmlconfdata/hostdev-scsi-vhost-sgio-invalid.x86_64-latest.err
@@ -0,0 +1 @@
+XML error: sgio is only supported for scsi host device
diff --git a/tests/qemuxmlconfdata/hostdev-scsi-vhost-sgio-invalid.xml b/tests/qemuxmlconfdata/hostdev-scsi-vhost-sgio-invalid.xml
new file mode 100644
index 0000000000..c549bddc1d
--- /dev/null
+++ b/tests/qemuxmlconfdata/hostdev-scsi-vhost-sgio-invalid.xml
@@ -0,0 +1,41 @@
+<domain type='qemu'>
+ <name>QEMUGuest2</name>
+ <uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid>
+ <memory unit='KiB'>219100</memory>
+ <currentMemory unit='KiB'>219100</currentMemory>
+ <vcpu placement='static'>1</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest2'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+ </disk>
+ <controller type='scsi' index='0' model='virtio-scsi'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
+ </controller>
+ <controller type='usb' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
+ </controller>
+ <controller type='ide' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+ </controller>
+ <controller type='pci' index='0' model='pci-root'/>
+ <input type='mouse' bus='ps2'/>
+ <input type='keyboard' bus='ps2'/>
+ <hostdev mode='subsystem' type='scsi_host' sgio='filtered'>
+ <source protocol='vhost' wwpn='naa.5123456789abcde0'/>
+ </hostdev>
+ <memballoon model='virtio'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
+ </memballoon>
+ </devices>
+</domain>
diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c
index 8e0d47c6fd..1236ed5df1 100644
--- a/tests/qemuxmlconftest.c
+++ b/tests/qemuxmlconftest.c
@@ -2993,6 +2993,8 @@ mymain(void)
DO_TEST_CAPS_LATEST("sound-device-virtio")
DO_TEST_CAPS_LATEST_FAILURE("disk-network-iscsi-zero-hosts-invalid")
+ DO_TEST_CAPS_LATEST_PARSE_ERROR("hostdev-scsi-vhost-rawio-invalid")
+ DO_TEST_CAPS_LATEST_PARSE_ERROR("hostdev-scsi-vhost-sgio-invalid")
/* check that all input files were actually used here */
if (testConfXMLCheck(existingTestCases) < 0)
--
2.34.1
[View Less]
9 months, 2 weeks