net/colo-compare: guard finalize against uninitialized state
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: 45942b79b9 ("net/colo-compare.c: Check that colo-compare is active")
Cc: peterx@redhat.com
Acked-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
@@ -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);
|
||||
|
||||
object_unref(OBJECT(s->iothread));
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user