Our monitor locking and cleanup code is weird as it allows to remove the monitor object pointer while we are in the monitor. Additionally EVERY api is using the vm private data after @vm was unlocked. This leads to an unpleasant situation, where when qemu crashes during a monitor session while a command is executed (and locks are down), the priv->mon pointer gets cleared (@vm is unlocked). The next monitor call then crashes on commands that did not check if the monitor is non-NULL. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1209813 and few other possible crashes --- Since this is a workaround rather than a proper fix I'd normally not go this way, but untangling the monitor mess won't be easy so I'll fix the symptoms first. src/qemu/qemu_monitor.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor.h | 12 +++++------- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 2b0e1a5..e8403be 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -1171,6 +1171,12 @@ qemuMonitorUpdateVideoMemorySize(qemuMonitorPtr mon, int ret = -1; char *path = NULL; + if (!mon) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("monitor must not be NULL")); + return -1; + } + if (mon->json) { ret = qemuMonitorFindObjectPath(mon, "/", videoName, &path); if (ret < 0) { @@ -1886,6 +1892,12 @@ qemuMonitorBlockStatsUpdateCapacity(qemuMonitorPtr mon, { VIR_DEBUG("mon=%p, stats=%p, backing=%d", mon, stats, backingChain); + if (!mon) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("monitor must not be NULL")); + return -1; + } + if (!mon->json) { virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", _("block capacity/size info requires JSON monitor")); @@ -3246,6 +3258,12 @@ qemuMonitorAddObject(qemuMonitorPtr mon, mon, type, objalias, props); int ret = -1; + if (!mon) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("monitor must not be NULL")); + return -1; + } + if (mon->json) { ret = qemuMonitorJSONAddObject(mon, type, objalias, props); } else { @@ -3265,6 +3283,12 @@ qemuMonitorDelObject(qemuMonitorPtr mon, VIR_DEBUG("mon=%p objalias=%s", mon, objalias); int ret = -1; + if (!mon) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("monitor must not be NULL")); + return -1; + } + if (mon->json) ret = qemuMonitorJSONDelObject(mon, objalias); else @@ -3453,6 +3477,12 @@ qemuMonitorBlockCommit(qemuMonitorPtr mon, const char *device, "bandwidth=%llu", mon, device, top, base, NULLSTR(backingName), bandwidth); + if (!mon) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("monitor must not be NULL")); + return -1; + } + if (mon->json) ret = qemuMonitorJSONBlockCommit(mon, device, top, base, backingName, bandwidth); @@ -3482,6 +3512,12 @@ qemuMonitorDiskNameLookup(qemuMonitorPtr mon, virStorageSourcePtr top, virStorageSourcePtr target) { + if (!mon) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("monitor must not be NULL")); + return NULL; + } + if (!mon->json) { virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", _("JSON monitor is required")); @@ -3592,6 +3628,12 @@ qemuMonitorBlockJob(qemuMonitorPtr mon, mon, device, NULLSTR(base), NULLSTR(backingName), bandwidth, mode, modern); + if (!mon) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("monitor must not be NULL")); + return -1; + } + if (mon->json) ret = qemuMonitorJSONBlockJob(mon, device, base, backingName, bandwidth, mode, modern); diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index a3514cf..7e62139 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -246,7 +246,7 @@ void qemuMonitorSetOptions(qemuMonitorPtr mon, virJSONValuePtr options) int qemuMonitorUpdateVideoMemorySize(qemuMonitorPtr mon, virDomainVideoDefPtr video, const char *videName) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); + ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); int qemuMonitorHMPCommandWithFd(qemuMonitorPtr mon, const char *cmd, int scm_fd, @@ -381,7 +381,7 @@ int qemuMonitorGetAllBlockStatsInfo(qemuMonitorPtr mon, int qemuMonitorBlockStatsUpdateCapacity(qemuMonitorPtr mon, virHashTablePtr stats, bool backingChain) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + ATTRIBUTE_NONNULL(2); int qemuMonitorGetBlockExtent(qemuMonitorPtr mon, const char *dev_name, @@ -730,15 +730,13 @@ int qemuMonitorBlockCommit(qemuMonitorPtr mon, const char *base, const char *backingName, unsigned long long bandwidth) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) - ATTRIBUTE_NONNULL(4); + ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); bool qemuMonitorSupportsActiveCommit(qemuMonitorPtr mon); char *qemuMonitorDiskNameLookup(qemuMonitorPtr mon, const char *device, virStorageSourcePtr top, virStorageSourcePtr target) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) - ATTRIBUTE_NONNULL(4); + ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, const char *cmd, @@ -774,7 +772,7 @@ int qemuMonitorBlockJobInfo(qemuMonitorPtr mon, const char *device, virDomainBlockJobInfoPtr info, unsigned long long *bandwidth) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); + ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); int qemuMonitorOpenGraphics(qemuMonitorPtr mon, const char *protocol, -- 2.3.5 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list