From: Marc-André Lureau <[email protected]>
colo_compare_finalize() assumes the object was fully set up by
colo_compare_complete(), but a bare object_new() followed by
object_unref() skips the complete callback entirely.
This causes two crashes:
- qemu_mutex_destroy on the static event_mtx which was never
initialized (colo_compare_active is false)
- qemu_bh_delete(NULL) and iothread dereference when s->iothread
is NULL
Guard the event_mtx teardown with colo_compare_active, and the
iothread-dependent cleanup with an s->iothread NULL check.
Fixes: 45942b79b9f8 ("net/colo-compare.c: Check that colo-compare is active")
Cc: [email protected]
Acked-by: Peter Xu <[email protected]>
Signed-off-by: Marc-André Lureau <[email protected]>
---
net/colo-compare.c | 31 +++++++++++++++----------------
1 file changed, 15 insertions(+), 16 deletions(-)
diff --git a/net/colo-compare.c b/net/colo-compare.c
index abc1326b704..823b8aa323c 100644
--- a/net/colo-compare.c
+++ b/net/colo-compare.c
@@ -1416,7 +1416,7 @@ static void colo_compare_finalize(Object *obj)
break;
}
}
- if (QTAILQ_EMPTY(&net_compares)) {
+ if (colo_compare_active && QTAILQ_EMPTY(&net_compares)) {
colo_compare_active = false;
qemu_mutex_destroy(&event_mtx);
qemu_cond_destroy(&event_complete_cond);
@@ -1431,30 +1431,29 @@ static void colo_compare_finalize(Object *obj)
}
colo_compare_timer_del(s);
+ g_clear_pointer(&s->event_bh, qemu_bh_delete);
- qemu_bh_delete(s->event_bh);
+ if (s->iothread) {
+ AioContext *ctx = iothread_get_aio_context(s->iothread);
- AioContext *ctx = iothread_get_aio_context(s->iothread);
- AIO_WAIT_WHILE(ctx, !s->out_sendco.done);
- if (s->notify_dev) {
- AIO_WAIT_WHILE(ctx, !s->notify_sendco.done);
- }
+ AIO_WAIT_WHILE(ctx, !s->out_sendco.done);
+ if (s->notify_dev) {
+ AIO_WAIT_WHILE(ctx, !s->notify_sendco.done);
+ }
+
+ /* Release all unhandled packets after compare thread exited */
+ g_queue_foreach(&s->conn_list, colo_flush_packets, s);
+ AIO_WAIT_WHILE(NULL, !s->out_sendco.done);
- /* Release all unhandled packets after compare thead exited */
- g_queue_foreach(&s->conn_list, colo_flush_packets, s);
- AIO_WAIT_WHILE(NULL, !s->out_sendco.done);
+ object_unref(OBJECT(s->iothread));
+ }
g_queue_clear(&s->conn_list);
g_queue_clear(&s->out_sendco.send_list);
if (s->notify_dev) {
g_queue_clear(&s->notify_sendco.send_list);
}
-
- if (s->connection_track_table) {
- g_hash_table_destroy(s->connection_track_table);
- }
-
- object_unref(OBJECT(s->iothread));
+ g_clear_pointer(&s->connection_track_table, g_hash_table_destroy);
g_free(s->pri_indev);
g_free(s->sec_indev);
--
2.54.0