On 30.04.24 11:06, Vladimir Sementsov-Ogievskiy wrote:
On 29.04.24 22:32, Peter Xu wrote:
On Mon, Apr 29, 2024 at 10:14:24PM +0300, Vladimir Sementsov-Ogievskiy wrote:
It's bad idea to leave critical section with error object freed, but
s->error still set, this theoretically may lead to use-after-free
crash. Let's avoid it.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@yandex-team.ru>
---
migration/migration.c | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/migration/migration.c b/migration/migration.c
index 0d26db47f7..58fd5819bc 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -732,9 +732,19 @@ static void process_incoming_migration_bh(void *opaque)
migration_incoming_state_destroy();
}
+static void migrate_error_free(MigrationState *s)
+{
+ QEMU_LOCK_GUARD(&s->error_mutex);
+ if (s->error) {
+ error_free(s->error);
+ s->error = NULL;
+ }
+}
+
static void coroutine_fn
process_incoming_migration_co(void *opaque)
{
+ MigrationState *s = migrate_get_current();
MigrationIncomingState *mis = migration_incoming_get_current();
PostcopyState ps;
int ret;
@@ -779,11 +789,9 @@ process_incoming_migration_co(void *opaque)
}
if (ret < 0) {
- MigrationState *s = migrate_get_current();
-
if (migrate_has_error(s)) {
WITH_QEMU_LOCK_GUARD(&s->error_mutex) {
- error_report_err(s->error);
+ error_report_err(error_copy(s->error));
This looks like a bugfix, agreed.
}
}
error_report("load of migration failed: %s", strerror(-ret));
@@ -801,6 +809,7 @@ fail:
MIGRATION_STATUS_FAILED);
migration_incoming_state_destroy();
+ migrate_error_free(s);
Would migration_incoming_state_destroy() be a better place?
Hmm. But we want to call migration_incoming_state_destroy() in case when
exit-on-error=false too. And in this case we want to keep the error for further
query-migrate commands.
Actually, I think we shouldn't care about freeing the error for exit() case. I
think, we skip a lot of other cleanups which we normally do in main() in case
of this exit().
One thing weird is we actually reuses MigrationState*'s error for incoming
too, but so far it looks ok as long as QEMU can't be both src & dst. Then
calling migrate_error_free even in incoming_state_destroy() looks ok.
This patch still looks like containing two changes. Better split them (or
just fix the bug only)?
Thanks,
exit(EXIT_FAILURE);
}
@@ -1433,15 +1442,6 @@ bool migrate_has_error(MigrationState *s)
return qatomic_read(&s->error);
}
-static void migrate_error_free(MigrationState *s)
-{
- QEMU_LOCK_GUARD(&s->error_mutex);
- if (s->error) {
- error_free(s->error);
- s->error = NULL;
- }
-}
-
static void migrate_fd_error(MigrationState *s, const Error *error)
{
assert(s->to_dst_file == NULL);
--
2.34.1
--
Best regards,
Vladimir