- Apply io-remove-io-watch-if-TLS-channel-is-closed.patch

- Apply migration-Add-migration-prefix-to-functions-in-target.patch
- Apply migration-Move-more-initializations-to-migrate_init.patch
- Apply migration-Add-save_prepare-handler-to-struct-SaveVMHandlers.patch
- Apply vfio-migration-Block-VFIO-migration-with-postcopy-migration.patch
This commit is contained in:
eabdullin 2023-11-07 13:07:11 +03:00
parent f5f57d5618
commit 15d00ca921
6 changed files with 506 additions and 1 deletions

View File

@ -0,0 +1,80 @@
From 10be627d2b5ec2d6b3dce045144aa739eef678b4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Tue, 20 Jun 2023 09:45:34 +0100
Subject: [PATCH] io: remove io watch if TLS channel is closed during handshake
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The TLS handshake make take some time to complete, during which time an
I/O watch might be registered with the main loop. If the owner of the
I/O channel invokes qio_channel_close() while the handshake is waiting
to continue the I/O watch must be removed. Failing to remove it will
later trigger the completion callback which the owner is not expecting
to receive. In the case of the VNC server, this results in a SEGV as
vnc_disconnect_start() tries to shutdown a client connection that is
already gone / NULL.
CVE-2023-3354
Reported-by: jiangyegen <jiangyegen@huawei.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
include/io/channel-tls.h | 1 +
io/channel-tls.c | 18 ++++++++++++------
2 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/include/io/channel-tls.h b/include/io/channel-tls.h
index 5672479e9eb6..26c67f17e2d3 100644
--- a/include/io/channel-tls.h
+++ b/include/io/channel-tls.h
@@ -48,6 +48,7 @@ struct QIOChannelTLS {
QIOChannel *master;
QCryptoTLSSession *session;
QIOChannelShutdown shutdown;
+ guint hs_ioc_tag;
};
/**
diff --git a/io/channel-tls.c b/io/channel-tls.c
index 9805dd0a3f64..847d5297c339 100644
--- a/io/channel-tls.c
+++ b/io/channel-tls.c
@@ -198,12 +198,13 @@ static void qio_channel_tls_handshake_task(QIOChannelTLS *ioc,
}
trace_qio_channel_tls_handshake_pending(ioc, status);
- qio_channel_add_watch_full(ioc->master,
- condition,
- qio_channel_tls_handshake_io,
- data,
- NULL,
- context);
+ ioc->hs_ioc_tag =
+ qio_channel_add_watch_full(ioc->master,
+ condition,
+ qio_channel_tls_handshake_io,
+ data,
+ NULL,
+ context);
}
}
@@ -218,6 +219,7 @@ static gboolean qio_channel_tls_handshake_io(QIOChannel *ioc,
QIOChannelTLS *tioc = QIO_CHANNEL_TLS(
qio_task_get_source(task));
+ tioc->hs_ioc_tag = 0;
g_free(data);
qio_channel_tls_handshake_task(tioc, task, context);
@@ -378,6 +380,10 @@ static int qio_channel_tls_close(QIOChannel *ioc,
{
QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
+ if (tioc->hs_ioc_tag) {
+ g_clear_handle_id(&tioc->hs_ioc_tag, g_source_remove);
+ }
+
return qio_channel_close(tioc->master, errp);
}

View File

@ -0,0 +1,113 @@
From 38c482b4778595ee337761f73ec0730d6c47b404 Mon Sep 17 00:00:00 2001
From: Avihai Horon <avihaih@nvidia.com>
Date: Wed, 6 Sep 2023 18:08:48 +0300
Subject: [PATCH] migration: Add migration prefix to functions in target.c
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The functions in target.c are not static, yet they don't have a proper
migration prefix. Add such prefix.
Signed-off-by: Avihai Horon <avihaih@nvidia.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Cédric Le Goater <clg@redhat.com>
---
migration/migration.c | 6 +++---
migration/migration.h | 4 ++--
migration/savevm.c | 2 +-
migration/target.c | 8 ++++----
4 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/migration/migration.c b/migration/migration.c
index 5528acb65e0f..92866a8f49d3 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -1021,7 +1021,7 @@ static void fill_source_migration_info(MigrationInfo *info)
populate_time_info(info, s);
populate_ram_info(info, s);
populate_disk_info(info);
- populate_vfio_info(info);
+ migration_populate_vfio_info(info);
break;
case MIGRATION_STATUS_COLO:
info->has_status = true;
@@ -1030,7 +1030,7 @@ static void fill_source_migration_info(MigrationInfo *info)
case MIGRATION_STATUS_COMPLETED:
populate_time_info(info, s);
populate_ram_info(info, s);
- populate_vfio_info(info);
+ migration_populate_vfio_info(info);
break;
case MIGRATION_STATUS_FAILED:
info->has_status = true;
@@ -1638,7 +1638,7 @@ static bool migrate_prepare(MigrationState *s, bool blk, bool blk_inc,
*/
memset(&ram_counters, 0, sizeof(ram_counters));
memset(&compression_counters, 0, sizeof(compression_counters));
- reset_vfio_bytes_transferred();
+ migration_reset_vfio_bytes_transferred();
return true;
}
diff --git a/migration/migration.h b/migration/migration.h
index 6eea18db3675..c5695de21496 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -505,8 +505,8 @@ void migration_consume_urgent_request(void);
bool migration_rate_limit(void);
void migration_cancel(const Error *error);
-void populate_vfio_info(MigrationInfo *info);
-void reset_vfio_bytes_transferred(void);
+void migration_populate_vfio_info(MigrationInfo *info);
+void migration_reset_vfio_bytes_transferred(void);
void postcopy_temp_page_reset(PostcopyTmpPage *tmp_page);
#endif
diff --git a/migration/savevm.c b/migration/savevm.c
index 83088fc3f8..05db79bfad 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -1620,7 +1620,7 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp)
migrate_init(ms);
memset(&ram_counters, 0, sizeof(ram_counters));
memset(&compression_counters, 0, sizeof(compression_counters));
- reset_vfio_bytes_transferred();
+ migration_reset_vfio_bytes_transferred();
ms->to_dst_file = f;
qemu_mutex_unlock_iothread();
diff --git a/migration/target.c b/migration/target.c
index f39c9a8d8877..a6ffa9a5ce31 100644
--- a/migration/target.c
+++ b/migration/target.c
@@ -15,7 +15,7 @@
#endif
#ifdef CONFIG_VFIO
-void populate_vfio_info(MigrationInfo *info)
+void migration_populate_vfio_info(MigrationInfo *info)
{
if (vfio_mig_active()) {
info->vfio = g_malloc0(sizeof(*info->vfio));
@@ -23,16 +23,16 @@ void populate_vfio_info(MigrationInfo *info)
}
}
-void reset_vfio_bytes_transferred(void)
+void migration_reset_vfio_bytes_transferred(void)
{
vfio_reset_bytes_transferred();
}
#else
-void populate_vfio_info(MigrationInfo *info)
+void migration_populate_vfio_info(MigrationInfo *info)
{
}
-void reset_vfio_bytes_transferred(void)
+void migration_reset_vfio_bytes_transferred(void)
{
}
#endif

View File

@ -0,0 +1,158 @@
From 08fc4cb51774f763dcc6fd74637aa9e00eb6a0ba Mon Sep 17 00:00:00 2001
From: Avihai Horon <avihaih@nvidia.com>
Date: Wed, 6 Sep 2023 18:08:51 +0300
Subject: [PATCH] migration: Add .save_prepare() handler to struct
SaveVMHandlers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add a new .save_prepare() handler to struct SaveVMHandlers. This handler
is called early, even before migration starts, and can be used by
devices to perform early checks.
Refactor migrate_init() to be able to return errors and call
.save_prepare() from there.
Suggested-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Avihai Horon <avihaih@nvidia.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Cédric Le Goater <clg@redhat.com>
---
include/migration/register.h | 5 +++++
migration/migration.c | 15 +++++++++++++--
migration/migration.h | 2 +-
migration/savevm.c | 29 ++++++++++++++++++++++++++++-
migration/savevm.h | 1 +
5 files changed, 48 insertions(+), 4 deletions(-)
diff --git a/include/migration/register.h b/include/migration/register.h
index 90914f32f50c..2b12c6adeca7 100644
--- a/include/migration/register.h
+++ b/include/migration/register.h
@@ -20,6 +20,11 @@ typedef struct SaveVMHandlers {
/* This runs inside the iothread lock. */
SaveStateHandler *save_state;
+ /*
+ * save_prepare is called early, even before migration starts, and can be
+ * used to perform early checks.
+ */
+ int (*save_prepare)(void *opaque, Error **errp);
void (*save_cleanup)(void *opaque);
int (*save_live_complete_postcopy)(QEMUFile *f, void *opaque);
int (*save_live_complete_precopy)(QEMUFile *f, void *opaque);
diff --git a/migration/migration.c b/migration/migration.c
index ce01a3ba6af7..d61e5727429a 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -1389,8 +1389,15 @@ bool migration_is_active(MigrationState *s)
s->state == MIGRATION_STATUS_POSTCOPY_ACTIVE);
}
-void migrate_init(MigrationState *s)
+int migrate_init(MigrationState *s, Error **errp)
{
+ int ret;
+
+ ret = qemu_savevm_state_prepare(errp);
+ if (ret) {
+ return ret;
+ }
+
/*
* Reinitialise all migration state, except
* parameters/capabilities that the user set, and
@@ -1429,6 +1436,8 @@ void migrate_init(MigrationState *s)
memset(&ram_counters, 0, sizeof(ram_counters));
memset(&compression_counters, 0, sizeof(compression_counters));
migration_reset_vfio_bytes_transferred();
+
+ return 0;
}
int migrate_add_blocker_internal(Error *reason, Error **errp)
@@ -1638,7 +1647,9 @@ static bool migrate_prepare(MigrationState *s, bool blk, bool blk_inc,
migrate_set_block_incremental(s, true);
}
- migrate_init(s);
+ if (migrate_init(s, errp)) {
+ return false;
+ }
return true;
}
diff --git a/migration/migration.h b/migration/migration.h
index c5695de21496..c390500604b6 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -465,7 +465,7 @@ void migrate_fd_connect(MigrationState *s, Error *error_in);
bool migration_is_setup_or_active(int state);
bool migration_is_running(int state);
-void migrate_init(MigrationState *s);
+int migrate_init(MigrationState *s, Error **errp);
bool migration_is_blocked(Error **errp);
/* True if outgoing migration has entered postcopy phase */
bool migration_in_postcopy(void);
diff --git a/migration/savevm.c b/migration/savevm.c
index e14efeced0fb..bb3e99194c60 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -1231,6 +1231,30 @@ bool qemu_savevm_state_guest_unplug_pending(void)
return false;
}
+int qemu_savevm_state_prepare(Error **errp)
+{
+ SaveStateEntry *se;
+ int ret;
+
+ QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
+ if (!se->ops || !se->ops->save_prepare) {
+ continue;
+ }
+ if (se->ops->is_active) {
+ if (!se->ops->is_active(se->opaque)) {
+ continue;
+ }
+ }
+
+ ret = se->ops->save_prepare(se->opaque, errp);
+ if (ret < 0) {
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
void qemu_savevm_state_setup(QEMUFile *f)
{
MigrationState *ms = migrate_get_current();
@@ -1617,7 +1641,10 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp)
return -EINVAL;
}
- migrate_init(ms);
+ ret = migrate_init(ms, errp);
+ if (ret) {
+ return ret;
+ }
ms->to_dst_file = f;
qemu_mutex_unlock_iothread();
diff --git a/migration/savevm.h b/migration/savevm.h
index e894bbc14331..74669733dd63 100644
--- a/migration/savevm.h
+++ b/migration/savevm.h
@@ -31,6 +31,7 @@
bool qemu_savevm_state_blocked(Error **errp);
void qemu_savevm_non_migratable_list(strList **reasons);
+int qemu_savevm_state_prepare(Error **errp);
void qemu_savevm_state_setup(QEMUFile *f);
bool qemu_savevm_state_guest_unplug_pending(void);
int qemu_savevm_state_resume_prepare(MigrationState *s);

View File

@ -0,0 +1,68 @@
From f543aa222da183ac37424d1ea3a65e5fb6202732 Mon Sep 17 00:00:00 2001
From: Avihai Horon <avihaih@nvidia.com>
Date: Wed, 6 Sep 2023 18:08:50 +0300
Subject: [PATCH] migration: Move more initializations to migrate_init()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Initialization of mig_stats, compression_counters and VFIO bytes
transferred is hard-coded in migration code path and snapshot code path.
Make the code cleaner by initializing them in migrate_init().
Suggested-by: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Avihai Horon <avihaih@nvidia.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Cédric Le Goater <clg@redhat.com>
---
migration/migration.c | 14 +++++++-------
migration/savevm.c | 3 ---
2 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/migration/migration.c b/migration/migration.c
index 92866a8f49d3..ce01a3ba6af7 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -1422,6 +1422,13 @@ void migrate_init(MigrationState *s)
s->iteration_initial_bytes = 0;
s->threshold_size = 0;
s->switchover_acked = false;
+ /*
+ * set mig_stats compression_counters memory to zero for a
+ * new migration
+ */
+ memset(&ram_counters, 0, sizeof(ram_counters));
+ memset(&compression_counters, 0, sizeof(compression_counters));
+ migration_reset_vfio_bytes_transferred();
}
int migrate_add_blocker_internal(Error *reason, Error **errp)
@@ -1632,13 +1639,6 @@ static bool migrate_prepare(MigrationState *s, bool blk, bool blk_inc,
}
migrate_init(s);
- /*
- * set ram_counters compression_counters memory to zero for a
- * new migration
- */
- memset(&ram_counters, 0, sizeof(ram_counters));
- memset(&compression_counters, 0, sizeof(compression_counters));
- migration_reset_vfio_bytes_transferred();
return true;
}
diff --git a/migration/savevm.c b/migration/savevm.c
index 5bf8b59a7dfc..e14efeced0fb 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -1618,9 +1618,6 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp)
}
migrate_init(ms);
- memset(&ram_counters, 0, sizeof(ram_counters));
- memset(&compression_counters, 0, sizeof(compression_counters));
- migration_reset_vfio_bytes_transferred();
ms->to_dst_file = f;
qemu_mutex_unlock_iothread();

View File

@ -0,0 +1,69 @@
From bf7ef7a2da3e61dc104f26c679c9465e3fbe7dde Mon Sep 17 00:00:00 2001
From: Avihai Horon <avihaih@nvidia.com>
Date: Wed, 6 Sep 2023 18:08:52 +0300
Subject: [PATCH] vfio/migration: Block VFIO migration with postcopy migration
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
VFIO migration is not compatible with postcopy migration. A VFIO device
in the destination can't handle page faults for pages that have not been
sent yet.
Doing such migration will cause the VM to crash in the destination:
qemu-system-x86_64: VFIO_MAP_DMA failed: Bad address
qemu-system-x86_64: vfio_dma_map(0x55a28c7659d0, 0xc0000, 0xb000, 0x7f1b11a00000) = -14 (Bad address)
qemu: hardware error: vfio: DMA mapping failed, unable to continue
To prevent this, block VFIO migration with postcopy migration.
Reported-by: Yanghang Liu <yanghliu@redhat.com>
Signed-off-by: Avihai Horon <avihaih@nvidia.com>
Tested-by: Yanghang Liu <yanghliu@redhat.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Cédric Le Goater <clg@redhat.com>
---
hw/vfio/migration.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c
index 71855468fe98..20994dc1d60b 100644
--- a/hw/vfio/migration.c
+++ b/hw/vfio/migration.c
@@ -335,6 +335,27 @@ static bool vfio_precopy_supported(VFIODevice *vbasedev)
/* ---------------------------------------------------------------------- */
+static int vfio_save_prepare(void *opaque, Error **errp)
+{
+ VFIODevice *vbasedev = opaque;
+
+ /*
+ * Snapshot doesn't use postcopy, so allow snapshot even if postcopy is on.
+ */
+ if (runstate_check(RUN_STATE_SAVE_VM)) {
+ return 0;
+ }
+
+ if (migrate_postcopy_ram()) {
+ error_setg(
+ errp, "%s: VFIO migration is not supported with postcopy migration",
+ vbasedev->name);
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
static int vfio_save_setup(QEMUFile *f, void *opaque)
{
VFIODevice *vbasedev = opaque;
@@ -640,6 +661,7 @@ static bool vfio_switchover_ack_needed(void *opaque)
}
static const SaveVMHandlers savevm_vfio_handlers = {
+ .save_prepare = vfio_save_prepare,
.save_setup = vfio_save_setup,
.save_cleanup = vfio_save_cleanup,
.state_pending_estimate = vfio_state_pending_estimate,

View File

@ -149,7 +149,7 @@ Obsoletes: %{name}-block-ssh <= %{epoch}:%{version} \
Summary: QEMU is a machine emulator and virtualizer
Name: qemu-kvm
Version: 8.0.0
Release: 13%{?rcrel}%{?dist}%{?cc_suffix}
Release: 16%{?rcrel}%{?dist}%{?cc_suffix}.1.alma.1
# Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
# Epoch 15 used for RHEL 8
# Epoch 17 used for RHEL 9 (due to release versioning offset in RHEL 8.5)
@ -548,6 +548,16 @@ Patch192: kvm-vdpa-move-vhost_vdpa_set_vring_ready-to-the-caller.patch
Patch193: kvm-vdpa-remove-net-cvq-migration-blocker.patch
# Patches were taken from upstream and backported to apply cleanly:
# https://github.com/qemu/qemu/commit/10be627d2b5ec2d6b3dce045144aa739eef678b4.patch
Patch1001: io-remove-io-watch-if-TLS-channel-is-closed.patch
# https://github.com/qemu/qemu/commit/38c482b4778595ee337761f73ec0730d6c47b404.patch
Patch1002: migration-Add-migration-prefix-to-functions-in-target.patch
# https://github.com/qemu/qemu/commit/f543aa222da183ac37424d1ea3a65e5fb6202732.patch
Patch1003: migration-Move-more-initializations-to-migrate_init.patch
# https://github.com/qemu/qemu/commit/08fc4cb51774f763dcc6fd74637aa9e00eb6a0ba.patch
Patch1004: migration-Add-save_prepare-handler-to-struct-SaveVMHandlers.patch
# https://github.com/qemu/qemu/commit/bf7ef7a2da3e61dc104f26c679c9465e3fbe7dde.patch
Patch1005: vfio-migration-Block-VFIO-migration-with-postcopy-migration.patch
%if %{have_clang}
BuildRequires: clang
@ -1609,6 +1619,13 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \
%endif
%changelog
* Tue Nov 07 2023 Eduard Abdullin <eabdullin@almalinux.org> - 8.0.0-16.1.alma.1
- Apply io-remove-io-watch-if-TLS-channel-is-closed.patch
- Apply migration-Add-migration-prefix-to-functions-in-target.patch
- Apply migration-Move-more-initializations-to-migrate_init.patch
- Apply migration-Add-save_prepare-handler-to-struct-SaveVMHandlers.patch
- Apply vfio-migration-Block-VFIO-migration-with-postcopy-migration.patch
* Thu Aug 24 2023 Miroslav Rezanina <mrezanin@redhat.com> - 8.0.0-13
- kvm-vdpa-return-errno-in-vhost_vdpa_get_vring_group-erro.patch [RHEL-923]
- kvm-vdpa-move-CVQ-isolation-check-to-net_init_vhost_vdpa.patch [RHEL-923]