Compare commits

...

No commits in common. "c8-stream-rhel" and "stream-virt-rhel-rhel-8.9.0" have entirely different histories.

392 changed files with 6 additions and 9228 deletions

8
.gitignore vendored
View File

@ -1,5 +1,5 @@
/qemu-5.2.0-rc2.tar.xz
/qemu-5.2.0.tar.xz
/qemu-6.0.0.tar.xz
/qemu-6.2.0.tar.xz
SOURCES/qemu-6.2.0.tar.xz
SOURCES/tests_data_acpi_pc_SSDT.dimmpxm
SOURCES/tests_data_acpi_q35_FACP.slic
SOURCES/tests_data_acpi_q35_SSDT.dimmpxm
SOURCES/tests_data_acpi_virt_SSDT.memhp

View File

@ -1,5 +0,0 @@
68cd61a466170115b88817e2d52db2cd7a92f43a SOURCES/qemu-6.2.0.tar.xz
c4b34092bc5af1ba7febfca1477320fb024e8acd SOURCES/tests_data_acpi_pc_SSDT.dimmpxm
19349e3517143bd1af56a5444e927ba37a111f72 SOURCES/tests_data_acpi_q35_FACP.slic
4632d10ae8cedad4d5d760ed211f83f0dc81005d SOURCES/tests_data_acpi_q35_SSDT.dimmpxm
ef12eed43cc357fb134db6fa3c7ffc83e222a97d SOURCES/tests_data_acpi_virt_SSDT.memhp

View File

@ -1,181 +0,0 @@
From 440ee491240f2f02f9a6082d8aad98d88c1039dd Mon Sep 17 00:00:00 2001
From: Thomas Huth <thuth@redhat.com>
Date: Mon, 15 Jan 2024 14:00:04 +0100
Subject: [PATCH 1/5] MAINTAINERS: split out s390x sections
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 348: s390x: Provide some more useful information if decryption of a PV image fails
RH-Jira: RHEL-18214
RH-Acked-by: Jon Maloy <jmaloy@redhat.com>
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
RH-Commit: [1/5] a71a3c11922481f97c36570e361088d17474e481
JIRA: https://issues.redhat.com/browse/RHEL-18214
commit 56e34834029c7c6862cb0095d95ad83c50485f88
Author: Cornelia Huck <cohuck@redhat.com>
Date: Wed Dec 22 11:55:48 2021 +0100
MAINTAINERS: split out s390x sections
Split out some more specialized devices etc., so that we can build
smarter lists of people to be put on cc: in the future.
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Acked-by: David Hildenbrand <david@redhat.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Acked-by: Thomas Huth <thuth@redhat.com>
Acked-by: Halil Pasic <pasic@linux.ibm.com>
Acked-by: Eric Farman <farman@linux.ibm.com>
Message-Id: <20211222105548.356852-1-cohuck@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
MAINTAINERS | 85 ++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 74 insertions(+), 11 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 7543eb4d59..b893206fc3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -297,7 +297,6 @@ M: David Hildenbrand <david@redhat.com>
S: Maintained
F: target/s390x/
F: target/s390x/tcg
-F: target/s390x/cpu_models_*.[ch]
F: hw/s390x/
F: disas/s390.c
F: tests/tcg/s390x/
@@ -396,16 +395,10 @@ M: Halil Pasic <pasic@linux.ibm.com>
M: Christian Borntraeger <borntraeger@de.ibm.com>
S: Supported
F: target/s390x/kvm/
-F: target/s390x/ioinst.[ch]
F: target/s390x/machine.c
F: target/s390x/sigp.c
-F: target/s390x/cpu_features*.[ch]
-F: target/s390x/cpu_models.[ch]
F: hw/s390x/pv.c
F: include/hw/s390x/pv.h
-F: hw/intc/s390_flic.c
-F: hw/intc/s390_flic_kvm.c
-F: include/hw/s390x/s390_flic.h
F: gdb-xml/s390*.xml
T: git https://github.com/borntraeger/qemu.git s390-next
L: qemu-s390x@nongnu.org
@@ -1529,12 +1522,8 @@ S390 Virtio-ccw
M: Halil Pasic <pasic@linux.ibm.com>
M: Christian Borntraeger <borntraeger@de.ibm.com>
S: Supported
-F: hw/char/sclp*.[hc]
-F: hw/char/terminal3270.c
F: hw/s390x/
F: include/hw/s390x/
-F: hw/watchdog/wdt_diag288.c
-F: include/hw/watchdog/wdt_diag288.h
F: configs/devices/s390x-softmmu/default.mak
F: tests/avocado/machine_s390_ccw_virtio.py
T: git https://github.com/borntraeger/qemu.git s390-next
@@ -1559,6 +1548,37 @@ F: hw/s390x/s390-pci*
F: include/hw/s390x/s390-pci*
L: qemu-s390x@nongnu.org
+S390 channel subsystem
+M: Halil Pasic <pasic@linux.ibm.com>
+M: Christian Borntraeger <borntraeger@linux.ibm.com>
+S: Supported
+F: hw/s390x/ccw-device.[ch]
+F: hw/s390x/css.c
+F: hw/s390x/css-bridge.c
+F: include/hw/s390x/css.h
+F: include/hw/s390x/css-bridge.h
+F: include/hw/s390x/ioinst.h
+F: target/s390x/ioinst.c
+L: qemu-s390x@nongnu.org
+
+S390 CPU models
+M: David Hildenbrand <david@redhat.com>
+S: Maintained
+F: target/s390x/cpu_features*.[ch]
+F: target/s390x/cpu_models.[ch]
+L: qemu-s390x@nongnu.org
+
+S390 SCLP-backed devices
+M: Halil Pasic <pasic@linux.ibm.com>
+M: Christian Borntraeger <borntraeger@linux.ibm.com>
+S: Supported
+F: include/hw/s390x/event-facility.h
+F: include/hw/s390x/sclp.h
+F: hw/char/sclp*.[hc]
+F: hw/s390x/event-facility.c
+F: hw/s390x/sclp*.c
+L: qemu-s390x@nongnu.org
+
X86 Machines
------------
PC
@@ -1956,6 +1976,7 @@ M: Halil Pasic <pasic@linux.ibm.com>
S: Supported
F: hw/s390x/virtio-ccw*.[hc]
F: hw/s390x/vhost-vsock-ccw.c
+F: hw/s390x/vhost-user-fs-ccw.c
T: git https://gitlab.com/cohuck/qemu.git s390-next
T: git https://github.com/borntraeger/qemu.git s390-next
L: qemu-s390x@nongnu.org
@@ -2294,6 +2315,48 @@ F: hw/timer/mips_gictimer.c
F: include/hw/intc/mips_gic.h
F: include/hw/timer/mips_gictimer.h
+S390 3270 device
+M: Halil Pasic <pasic@linux.ibm.com>
+M: Christian Borntraeger <borntraeger@linux.ibm.com>
+S: Odd fixes
+F: include/hw/s390x/3270-ccw.h
+F: hw/char/terminal3270.c
+F: hw/s390x/3270-ccw.c
+L: qemu-s390x@nongnu.org
+
+S390 diag 288 watchdog
+M: Halil Pasic <pasic@linux.ibm.com>
+M: Christian Borntraeger <borntraeger@linux.ibm.com>
+S: Supported
+F: hw/watchdog/wdt_diag288.c
+F: include/hw/watchdog/wdt_diag288.h
+L: qemu-s390x@nongnu.org
+
+S390 storage key device
+M: Halil Pasic <pasic@linux.ibm.com>
+M: Christian Borntraeger <borntraeger@linux.ibm.com>
+S: Supported
+F: hw/s390x/storage-keys.h
+F: hw/390x/s390-skeys*.c
+L: qemu-s390x@nongnu.org
+
+S390 storage attribute device
+M: Halil Pasic <pasic@linux.ibm.com>
+M: Christian Borntraeger <borntraeger@linux.ibm.com>
+S: Supported
+F: hw/s390x/storage-attributes.h
+F: hw/s390/s390-stattrib*.c
+L: qemu-s390x@nongnu.org
+
+S390 floating interrupt controller
+M: Halil Pasic <pasic@linux.ibm.com>
+M: Christian Borntraeger <borntraeger@linux.ibm.com>
+M: David Hildenbrand <david@redhat.com>
+S: Supported
+F: hw/intc/s390_flic*.c
+F: include/hw/s390x/s390_flic.h
+L: qemu-s390x@nongnu.org
+
Subsystems
----------
Overall Audio backends
--
2.41.0

View File

@ -1,43 +0,0 @@
From f1480fe9a4054113ddacd218961e29f31c33d329 Mon Sep 17 00:00:00 2001
From: Peter Xu <peterx@redhat.com>
Date: Wed, 6 Sep 2023 16:29:23 -0400
Subject: [PATCH 2/3] RHEL: Enable "x-not-migrate-acpi-index" for all pre-RHEL8
guests
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Peter Xu <peterx@redhat.com>
RH-MergeRequest: 343: acpi: fix acpi_index migration
RH-Jira: RHEL-20189
RH-Acked-by: Leonardo Brás <leobras@redhat.com>
RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
RH-Acked-by: Prasad Pandit <None>
RH-Commit: [2/2] 0a26a71236e68dd7feb5d2063254090e3852d6ba
The acpi index migration is simply broken before for all pre-RHEL8
branches. Don't migrate it for all of them.
Signed-off-by: Peter Xu <peterx@redhat.com>
---
hw/core/machine.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 2724f6848a..6650a3d7b7 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -44,6 +44,10 @@ GlobalProperty hw_compat_rhel_8_6[] = {
* we need do disable it downstream on the latest hw_compat_rhel_8.
*/
{ "vhost-vsock-device", "seqpacket", "off" },
+ /*
+ * RHEL-2186: all rhel8 machines should not migrate acpi index.
+ */
+ { "PIIX4_PM", "x-not-migrate-acpi-index", "on"},
};
const size_t hw_compat_rhel_8_6_len = G_N_ELEMENTS(hw_compat_rhel_8_6);
--
2.41.0

View File

@ -1,165 +0,0 @@
From 3deffc03c2e9b0053eec5aeb5b5d633dfe29f499 Mon Sep 17 00:00:00 2001
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Date: Wed, 6 Apr 2022 14:58:12 -0400
Subject: [PATCH 1/3] acpi: fix acpi_index migration
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Peter Xu <peterx@redhat.com>
RH-MergeRequest: 343: acpi: fix acpi_index migration
RH-Jira: RHEL-20189
RH-Acked-by: Leonardo Brás <leobras@redhat.com>
RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
RH-Acked-by: Prasad Pandit <None>
RH-Commit: [1/2] c5b9cdf5791cd856207b7df7e2ef5df360ec8de4
vmstate_acpi_pcihp_use_acpi_index() was expecting AcpiPciHpState
as state but it actually received PIIX4PMState, because
VMSTATE_PCI_HOTPLUG is a macro and not another struct.
So it ended up accessing random pointer, which resulted
in 'false' return value and acpi_index field wasn't ever
sent.
However in 7.0 that pointer de-references to value > 0, and
destination QEMU starts to expect the field which isn't
sent in migratioon stream from older QEMU (6.2 and older).
As result migration fails with:
qemu-system-x86_64: Missing section footer for 0000:00:01.3/piix4_pm
qemu-system-x86_64: load of migration failed: Invalid argument
In addition with QEMU-6.2, destination due to not expected
state, also never expects the acpi_index field in migration
stream.
Q35 is not affected as it always sends/expects the field as
long as acpi based PCI hotplug is enabled.
Fix issue by introducing compat knob to never send/expect
acpi_index in migration stream for 6.2 and older PC machine
types and always send it for 7.0 and newer PC machine types.
Diagnosed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Fixes: b32bd76 ("pci: introduce acpi-index property for PCI device")
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/932
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit a83c2844903c45aa7d32cdd17305f23ce2c56ab9)
Signed-off-by: Peter Xu <peterx@redhat.com>
---
hw/acpi/acpi-pci-hotplug-stub.c | 4 ----
hw/acpi/pcihp.c | 6 ------
hw/acpi/piix4.c | 15 ++++++++++++++-
hw/core/machine.c | 5 +++++
include/hw/acpi/pcihp.h | 2 --
5 files changed, 19 insertions(+), 13 deletions(-)
diff --git a/hw/acpi/acpi-pci-hotplug-stub.c b/hw/acpi/acpi-pci-hotplug-stub.c
index 734e4c5986..a43f6dafc9 100644
--- a/hw/acpi/acpi-pci-hotplug-stub.c
+++ b/hw/acpi/acpi-pci-hotplug-stub.c
@@ -41,7 +41,3 @@ void acpi_pcihp_reset(AcpiPciHpState *s, bool acpihp_root_off)
return;
}
-bool vmstate_acpi_pcihp_use_acpi_index(void *opaque, int version_id)
-{
- return false;
-}
diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
index be0e846b34..ec861661c3 100644
--- a/hw/acpi/pcihp.c
+++ b/hw/acpi/pcihp.c
@@ -559,12 +559,6 @@ void acpi_pcihp_init(Object *owner, AcpiPciHpState *s, PCIBus *root_bus,
OBJ_PROP_FLAG_READ);
}
-bool vmstate_acpi_pcihp_use_acpi_index(void *opaque, int version_id)
-{
- AcpiPciHpState *s = opaque;
- return s->acpi_index;
-}
-
const VMStateDescription vmstate_acpi_pcihp_pci_status = {
.name = "acpi_pcihp_pci_status",
.version_id = 1,
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 8d6011c0a3..033e75ce5b 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -82,6 +82,7 @@ struct PIIX4PMState {
AcpiPciHpState acpi_pci_hotplug;
bool use_acpi_hotplug_bridge;
bool use_acpi_root_pci_hotplug;
+ bool not_migrate_acpi_index;
uint8_t disable_s3;
uint8_t disable_s4;
@@ -269,6 +270,16 @@ static bool piix4_vmstate_need_smbus(void *opaque, int version_id)
return pm_smbus_vmstate_needed();
}
+/*
+ * This is a fudge to turn off the acpi_index field,
+ * whose test was always broken on piix4 with 6.2 and older machine types.
+ */
+static bool vmstate_test_migrate_acpi_index(void *opaque, int version_id)
+{
+ PIIX4PMState *s = PIIX4_PM(opaque);
+ return s->use_acpi_hotplug_bridge && !s->not_migrate_acpi_index;
+}
+
/* qemu-kvm 1.2 uses version 3 but advertised as 2
* To support incoming qemu-kvm 1.2 migration, change version_id
* and minimum_version_id to 2 below (which breaks migration from
@@ -299,7 +310,7 @@ static const VMStateDescription vmstate_acpi = {
struct AcpiPciHpPciStatus),
VMSTATE_PCI_HOTPLUG(acpi_pci_hotplug, PIIX4PMState,
vmstate_test_use_acpi_hotplug_bridge,
- vmstate_acpi_pcihp_use_acpi_index),
+ vmstate_test_migrate_acpi_index),
VMSTATE_END_OF_LIST()
},
.subsections = (const VMStateDescription*[]) {
@@ -654,6 +665,8 @@ static Property piix4_pm_properties[] = {
DEFINE_PROP_BOOL("memory-hotplug-support", PIIX4PMState,
acpi_memory_hotplug.is_enabled, true),
DEFINE_PROP_BOOL("smm-compat", PIIX4PMState, smm_compat, false),
+ DEFINE_PROP_BOOL("x-not-migrate-acpi-index", PIIX4PMState,
+ not_migrate_acpi_index, false),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 76fcabec7a..2724f6848a 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -331,6 +331,11 @@ GlobalProperty hw_compat_rhel_7_1[] = {
};
const size_t hw_compat_rhel_7_1_len = G_N_ELEMENTS(hw_compat_rhel_7_1);
+GlobalProperty hw_compat_6_2[] = {
+ { "PIIX4_PM", "x-not-migrate-acpi-index", "on"},
+};
+const size_t hw_compat_6_2_len = G_N_ELEMENTS(hw_compat_6_2);
+
GlobalProperty hw_compat_6_1[] = {
{ "vhost-user-vsock-device", "seqpacket", "off" },
{ "nvme-ns", "shared", "off" },
diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h
index af1a169fc3..7e268c2c9c 100644
--- a/include/hw/acpi/pcihp.h
+++ b/include/hw/acpi/pcihp.h
@@ -73,8 +73,6 @@ void acpi_pcihp_reset(AcpiPciHpState *s, bool acpihp_root_off);
extern const VMStateDescription vmstate_acpi_pcihp_pci_status;
-bool vmstate_acpi_pcihp_use_acpi_index(void *opaque, int version_id);
-
#define VMSTATE_PCI_HOTPLUG(pcihp, state, test_pcihp, test_acpi_index) \
VMSTATE_UINT32_TEST(pcihp.hotplug_select, state, \
test_pcihp), \
--
2.41.0

View File

@ -1,260 +0,0 @@
From c4ba1f1755031a0ac2f600ed8c17e7dcb6b2b857 Mon Sep 17 00:00:00 2001
From: Jon Maloy <jmaloy@redhat.com>
Date: Wed, 5 Jun 2024 19:56:51 -0400
Subject: [PATCH 5/5] block: Parse filenames only when explicitly requested
RH-Author: Jon Maloy <jmaloy@redhat.com>
RH-MergeRequest: 5: EMBARGOED CVE-2024-4467 for rhel-8.10.z (PRDSC)
RH-Jira: RHEL-35616
RH-CVE: CVE-2024-4467
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
RH-Commit: [5/5] a3e197add64fc6950c4ac576e34d833dfae7ee34
Conflicts: - brdv_open_child_common(): bdrv_graph_wrlock/unlock()
don't exist in this code version. We ignore them.
bdrv_open_inherit(): no_coroutine_fn/GRAPH_UNLOCKED
doesn't exist. We ignore it.
- Changes to bdrv_open_file_child() didn't apply cleanly,
but fixing it is straight-forward.
- GLOBAL_STATE_CODE() not present in this code. Ignoring it.
- bdrv_open_file_child(): Need to continue setting of
parent->file.
commit f44c2941d4419e60f16dea3e9adca164e75aa78d
Author: Kevin Wolf <kwolf@redhat.com>
Date: Thu Apr 25 14:56:02 2024 +0200
block: Parse filenames only when explicitly requested
When handling image filenames from legacy options such as -drive or from
tools, these filenames are parsed for protocol prefixes, including for
the json:{} pseudo-protocol.
This behaviour is intended for filenames that come directly from the
command line and for backing files, which may come from the image file
itself. Higher level management tools generally take care to verify that
untrusted images don't contain a bad (or any) backing file reference;
'qemu-img info' is a suitable tool for this.
However, for other files that can be referenced in images, such as
qcow2 data files or VMDK extents, the string from the image file is
usually not verified by management tools - and 'qemu-img info' wouldn't
be suitable because in contrast to backing files, it already opens these
other referenced files. So here the string should be interpreted as a
literal local filename. More complex configurations need to be specified
explicitly on the command line or in QMP.
This patch changes bdrv_open_inherit() so that it only parses filenames
if a new parameter parse_filename is true. It is set for the top level
in bdrv_open(), for the file child and for the backing file child. All
other callers pass false and disable filename parsing this way.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
Upstream: N/A, embargoed
Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
block.c | 81 +++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 56 insertions(+), 25 deletions(-)
diff --git a/block.c b/block.c
index 889f878565..ddebf50efa 100644
--- a/block.c
+++ b/block.c
@@ -82,6 +82,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
BlockDriverState *parent,
const BdrvChildClass *child_class,
BdrvChildRole child_role,
+ bool parse_filename,
Error **errp);
static bool bdrv_recurse_has_child(BlockDriverState *bs,
@@ -1926,7 +1927,8 @@ static void parse_json_protocol(QDict *options, const char **pfilename,
* block driver has been specified explicitly.
*/
static int bdrv_fill_options(QDict **options, const char *filename,
- int *flags, Error **errp)
+ int *flags, bool allow_parse_filename,
+ Error **errp)
{
const char *drvname;
bool protocol = *flags & BDRV_O_PROTOCOL;
@@ -1966,7 +1968,7 @@ static int bdrv_fill_options(QDict **options, const char *filename,
if (protocol && filename) {
if (!qdict_haskey(*options, "filename")) {
qdict_put_str(*options, "filename", filename);
- parse_filename = true;
+ parse_filename = allow_parse_filename;
} else {
error_setg(errp, "Can't specify 'file' and 'filename' options at "
"the same time");
@@ -3439,7 +3441,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
}
backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
- &child_of_bds, bdrv_backing_role(bs), errp);
+ &child_of_bds, bdrv_backing_role(bs), true,
+ errp);
if (!backing_hd) {
bs->open_flags |= BDRV_O_NO_BACKING;
error_prepend(errp, "Could not open backing file: ");
@@ -3472,7 +3475,8 @@ free_exit:
static BlockDriverState *
bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
BlockDriverState *parent, const BdrvChildClass *child_class,
- BdrvChildRole child_role, bool allow_none, Error **errp)
+ BdrvChildRole child_role, bool allow_none,
+ bool parse_filename, Error **errp)
{
BlockDriverState *bs = NULL;
QDict *image_options;
@@ -3503,7 +3507,8 @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
}
bs = bdrv_open_inherit(filename, reference, image_options, 0,
- parent, child_class, child_role, errp);
+ parent, child_class, child_role, parse_filename,
+ errp);
if (!bs) {
goto done;
}
@@ -3513,6 +3518,29 @@ done:
return bs;
}
+static BdrvChild *bdrv_open_child_common(const char *filename,
+ QDict *options, const char *bdref_key,
+ BlockDriverState *parent,
+ const BdrvChildClass *child_class,
+ BdrvChildRole child_role,
+ bool allow_none, bool parse_filename,
+ Error **errp)
+{
+ BlockDriverState *bs;
+ BdrvChild *child;
+
+ bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
+ child_role, allow_none, parse_filename, errp);
+ if (bs == NULL) {
+ return NULL;
+ }
+
+ child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
+ errp);
+
+ return child;
+}
+
/*
* Opens a disk image whose options are given as BlockdevRef in another block
* device's options.
@@ -3534,20 +3562,17 @@ BdrvChild *bdrv_open_child(const char *filename,
BdrvChildRole child_role,
bool allow_none, Error **errp)
{
- BlockDriverState *bs;
-
- bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
- child_role, allow_none, errp);
- if (bs == NULL) {
- return NULL;
- }
-
- return bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
- errp);
+ return bdrv_open_child_common(filename, options, bdref_key, parent,
+ child_class, child_role, allow_none, false,
+ errp);
}
/*
- * Wrapper on bdrv_open_child() for most popular case: open primary child of bs.
+ * This does mostly the same as bdrv_open_child(), but for opening the primary
+ * child of a node. A notable difference from bdrv_open_child() is that it
+ * enables filename parsing for protocol names (including json:).
+ *
+ * @parent can move to a different AioContext in this function.
*/
int bdrv_open_file_child(const char *filename,
QDict *options, const char *bdref_key,
@@ -3558,8 +3583,9 @@ int bdrv_open_file_child(const char *filename,
role = parent->drv->is_filter ?
(BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE;
- parent->file = bdrv_open_child(filename, options, bdref_key, parent,
- &child_of_bds, role, false, errp);
+ parent->file = bdrv_open_child_common(filename, options, bdref_key, parent,
+ &child_of_bds, role, false, true,
+ errp);
return parent->file ? 0 : -EINVAL;
}
@@ -3599,7 +3625,8 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
}
- bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, errp);
+ bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, false,
+ errp);
obj = NULL;
qobject_unref(obj);
visit_free(v);
@@ -3690,6 +3717,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
BlockDriverState *parent,
const BdrvChildClass *child_class,
BdrvChildRole child_role,
+ bool parse_filename,
Error **errp)
{
int ret;
@@ -3733,9 +3761,11 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
}
/* json: syntax counts as explicit options, as if in the QDict */
- parse_json_protocol(options, &filename, &local_err);
- if (local_err) {
- goto fail;
+ if (parse_filename) {
+ parse_json_protocol(options, &filename, &local_err);
+ if (local_err) {
+ goto fail;
+ }
}
bs->explicit_options = qdict_clone_shallow(options);
@@ -3760,7 +3790,8 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
parent->open_flags, parent->options);
}
- ret = bdrv_fill_options(&options, filename, &flags, &local_err);
+ ret = bdrv_fill_options(&options, filename, &flags, parse_filename,
+ &local_err);
if (ret < 0) {
goto fail;
}
@@ -3829,7 +3860,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
file_bs = bdrv_open_child_bs(filename, options, "file", bs,
&child_of_bds, BDRV_CHILD_IMAGE,
- true, &local_err);
+ true, true, &local_err);
if (local_err) {
goto fail;
}
@@ -3974,7 +4005,7 @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
QDict *options, int flags, Error **errp)
{
return bdrv_open_inherit(filename, reference, options, flags, NULL,
- NULL, 0, errp);
+ NULL, 0, true, errp);
}
/* Return true if the NULL-terminated @list contains @str */
--
2.39.3

View File

@ -1,566 +0,0 @@
From 996680dd6d5afd51918e600126dbfed4dfe89e05 Mon Sep 17 00:00:00 2001
From: Jon Maloy <jmaloy@redhat.com>
Date: Sun, 9 Jun 2024 23:08:39 -0400
Subject: [PATCH 4/5] block: introduce bdrv_open_file_child() helper
RH-Author: Jon Maloy <jmaloy@redhat.com>
RH-MergeRequest: 5: EMBARGOED CVE-2024-4467 for rhel-8.10.z (PRDSC)
RH-Jira: RHEL-35616
RH-CVE: CVE-2024-4467
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
RH-Commit: [4/5] 9f582a9aff740eb9ec6f64bfec94854038d8545f
Conflicts: - copy-before-write.c::cbw_copy() is an older version than
upstream, but introduction of the new function is
straight-forward.
- include/block/block-global-state.h doesn't exist in this
code version. Adding the prototype to
include/block/block.h instead.
- struct BlockDriver has no field 'filtered_child_is_backing'
We remove the corresponding assert() in the new function.
commit 83930780325b144a5908c45b3957b9b6457b3831
Author: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Date: Tue Jul 26 23:11:21 2022 +0300
block: introduce bdrv_open_file_child() helper
Almost all drivers call bdrv_open_child() similarly. Let's create a
helper for this.
The only not updated drivers that call bdrv_open_child() to set
bs->file are raw-format and snapshot-access:
raw-format sometimes want to have filtered child but
don't set drv->is_filter to true.
snapshot-access wants only DATA | PRIMARY
Possibly we should implement drv->is_filter_func() handler, to consider
raw-format as filter when it works as filter.. But it's another story.
Note also, that we decrease assignments to bs->file in code: it helps
us restrict modifying this field in further commit.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
Message-Id: <20220726201134.924743-3-vsementsov@yandex-team.ru>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
block.c | 18 ++++++++++++++++++
block/blkdebug.c | 9 +++------
block/blklogwrites.c | 7 ++-----
block/blkreplay.c | 7 ++-----
block/blkverify.c | 9 +++------
block/bochs.c | 7 +++----
block/cloop.c | 7 +++----
block/copy-before-write.c | 9 ++++-----
block/copy-on-read.c | 9 ++++-----
block/crypto.c | 11 ++++++-----
block/dmg.c | 7 +++----
block/filter-compress.c | 8 +++-----
block/parallels.c | 7 +++----
block/preallocate.c | 9 ++++-----
block/qcow.c | 6 ++----
block/qcow2.c | 8 ++++----
block/qed.c | 8 ++++----
block/replication.c | 8 +++-----
block/throttle.c | 8 +++-----
block/vdi.c | 7 +++----
block/vhdx.c | 7 +++----
block/vmdk.c | 7 +++----
block/vpc.c | 7 +++----
include/block/block.h | 3 +++
24 files changed, 92 insertions(+), 101 deletions(-)
diff --git a/block.c b/block.c
index 0ac5b163d2..889f878565 100644
--- a/block.c
+++ b/block.c
@@ -3546,6 +3546,24 @@ BdrvChild *bdrv_open_child(const char *filename,
errp);
}
+/*
+ * Wrapper on bdrv_open_child() for most popular case: open primary child of bs.
+ */
+int bdrv_open_file_child(const char *filename,
+ QDict *options, const char *bdref_key,
+ BlockDriverState *parent, Error **errp)
+{
+ BdrvChildRole role;
+
+ role = parent->drv->is_filter ?
+ (BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE;
+
+ parent->file = bdrv_open_child(filename, options, bdref_key, parent,
+ &child_of_bds, role, false, errp);
+
+ return parent->file ? 0 : -EINVAL;
+}
+
/*
* TODO Future callers may need to specify parent/child_class in order for
* option inheritance to work. Existing callers use it for the root node.
diff --git a/block/blkdebug.c b/block/blkdebug.c
index bbf2948703..5fcfc8ac6f 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -503,12 +503,9 @@ static int blkdebug_open(BlockDriverState *bs, QDict *options, int flags,
}
/* Open the image file */
- bs->file = bdrv_open_child(qemu_opt_get(opts, "x-image"), options, "image",
- bs, &child_of_bds,
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
- false, errp);
- if (!bs->file) {
- ret = -EINVAL;
+ ret = bdrv_open_file_child(qemu_opt_get(opts, "x-image"), options, "image",
+ bs, errp);
+ if (ret < 0) {
goto out;
}
diff --git a/block/blklogwrites.c b/block/blklogwrites.c
index f7a251e91f..f66a617eb3 100644
--- a/block/blklogwrites.c
+++ b/block/blklogwrites.c
@@ -155,11 +155,8 @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags,
}
/* Open the file */
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, false,
- errp);
- if (!bs->file) {
- ret = -EINVAL;
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
+ if (ret < 0) {
goto fail;
}
diff --git a/block/blkreplay.c b/block/blkreplay.c
index dcbe780ddb..76a0b8d12a 100644
--- a/block/blkreplay.c
+++ b/block/blkreplay.c
@@ -26,11 +26,8 @@ static int blkreplay_open(BlockDriverState *bs, QDict *options, int flags,
int ret;
/* Open the image file */
- bs->file = bdrv_open_child(NULL, options, "image", bs, &child_of_bds,
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
- false, errp);
- if (!bs->file) {
- ret = -EINVAL;
+ ret = bdrv_open_file_child(NULL, options, "image", bs, errp);
+ if (ret < 0) {
goto fail;
}
diff --git a/block/blkverify.c b/block/blkverify.c
index d1facf5ba9..920e891684 100644
--- a/block/blkverify.c
+++ b/block/blkverify.c
@@ -121,12 +121,9 @@ static int blkverify_open(BlockDriverState *bs, QDict *options, int flags,
}
/* Open the raw file */
- bs->file = bdrv_open_child(qemu_opt_get(opts, "x-raw"), options, "raw",
- bs, &child_of_bds,
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
- false, errp);
- if (!bs->file) {
- ret = -EINVAL;
+ ret = bdrv_open_file_child(qemu_opt_get(opts, "x-raw"), options, "raw",
+ bs, errp);
+ if (ret < 0) {
goto fail;
}
diff --git a/block/bochs.c b/block/bochs.c
index 4d68658087..b2dc06bbfd 100644
--- a/block/bochs.c
+++ b/block/bochs.c
@@ -110,10 +110,9 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
return ret;
}
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
- BDRV_CHILD_IMAGE, false, errp);
- if (!bs->file) {
- return -EINVAL;
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
+ if (ret < 0) {
+ return ret;
}
ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
diff --git a/block/cloop.c b/block/cloop.c
index b8c6d0eccd..bee87da173 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -71,10 +71,9 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
return ret;
}
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
- BDRV_CHILD_IMAGE, false, errp);
- if (!bs->file) {
- return -EINVAL;
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
+ if (ret < 0) {
+ return ret;
}
/* read header */
diff --git a/block/copy-before-write.c b/block/copy-before-write.c
index c30a5ff8de..8aa2cb6a85 100644
--- a/block/copy-before-write.c
+++ b/block/copy-before-write.c
@@ -150,12 +150,11 @@ static int cbw_open(BlockDriverState *bs, QDict *options, int flags,
{
BDRVCopyBeforeWriteState *s = bs->opaque;
BdrvDirtyBitmap *copy_bitmap;
+ int ret;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
- false, errp);
- if (!bs->file) {
- return -EINVAL;
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
+ if (ret < 0) {
+ return ret;
}
s->target = bdrv_open_child(NULL, options, "target", bs, &child_of_bds,
diff --git a/block/copy-on-read.c b/block/copy-on-read.c
index 1fc7fb3333..815ac1d835 100644
--- a/block/copy-on-read.c
+++ b/block/copy-on-read.c
@@ -41,12 +41,11 @@ static int cor_open(BlockDriverState *bs, QDict *options, int flags,
BDRVStateCOR *state = bs->opaque;
/* Find a bottom node name, if any */
const char *bottom_node = qdict_get_try_str(options, "bottom");
+ int ret;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
- false, errp);
- if (!bs->file) {
- return -EINVAL;
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
+ if (ret < 0) {
+ return ret;
}
bs->supported_read_flags = BDRV_REQ_PREFETCH;
diff --git a/block/crypto.c b/block/crypto.c
index c8ba4681e2..abfce39230 100644
--- a/block/crypto.c
+++ b/block/crypto.c
@@ -260,15 +260,14 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
{
BlockCrypto *crypto = bs->opaque;
QemuOpts *opts = NULL;
- int ret = -EINVAL;
+ int ret;
QCryptoBlockOpenOptions *open_opts = NULL;
unsigned int cflags = 0;
QDict *cryptoopts = NULL;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
- BDRV_CHILD_IMAGE, false, errp);
- if (!bs->file) {
- return -EINVAL;
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
+ if (ret < 0) {
+ return ret;
}
bs->supported_write_flags = BDRV_REQ_FUA &
@@ -276,6 +275,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
opts = qemu_opts_create(opts_spec, NULL, 0, &error_abort);
if (!qemu_opts_absorb_qdict(opts, options, errp)) {
+ ret = -EINVAL;
goto cleanup;
}
@@ -284,6 +284,7 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
open_opts = block_crypto_open_opts_init(cryptoopts, errp);
if (!open_opts) {
+ ret = -EINVAL;
goto cleanup;
}
diff --git a/block/dmg.c b/block/dmg.c
index 447901fbb8..38c363dd39 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -439,10 +439,9 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
return ret;
}
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
- BDRV_CHILD_IMAGE, false, errp);
- if (!bs->file) {
- return -EINVAL;
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
+ if (ret < 0) {
+ return ret;
}
block_module_load_one("dmg-bz2");
diff --git a/block/filter-compress.c b/block/filter-compress.c
index d5be538619..305716c86c 100644
--- a/block/filter-compress.c
+++ b/block/filter-compress.c
@@ -30,11 +30,9 @@
static int compress_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
- false, errp);
- if (!bs->file) {
- return -EINVAL;
+ int ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
+ if (ret < 0) {
+ return ret;
}
if (!bs->file->bs->drv || !block_driver_can_compress(bs->file->bs->drv)) {
diff --git a/block/parallels.c b/block/parallels.c
index 6ebad2a2bb..ed4debd899 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -735,10 +735,9 @@ static int parallels_open(BlockDriverState *bs, QDict *options, int flags,
Error *local_err = NULL;
char *buf;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
- BDRV_CHILD_IMAGE, false, errp);
- if (!bs->file) {
- return -EINVAL;
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
+ if (ret < 0) {
+ return ret;
}
ret = bdrv_pread(bs->file, 0, &ph, sizeof(ph));
diff --git a/block/preallocate.c b/block/preallocate.c
index 1d4233f730..332408bdc9 100644
--- a/block/preallocate.c
+++ b/block/preallocate.c
@@ -134,6 +134,7 @@ static int preallocate_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
BDRVPreallocateState *s = bs->opaque;
+ int ret;
/*
* s->data_end and friends should be initialized on permission update.
@@ -141,11 +142,9 @@ static int preallocate_open(BlockDriverState *bs, QDict *options, int flags,
*/
s->file_end = s->zero_start = s->data_end = -EINVAL;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
- false, errp);
- if (!bs->file) {
- return -EINVAL;
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
+ if (ret < 0) {
+ return ret;
}
if (!preallocate_absorb_opts(&s->opts, options, bs->file->bs, errp)) {
diff --git a/block/qcow.c b/block/qcow.c
index c39940f33e..544a17261f 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -120,10 +120,8 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
qdict_extract_subqdict(options, &encryptopts, "encrypt.");
encryptfmt = qdict_get_try_str(encryptopts, "format");
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
- BDRV_CHILD_IMAGE, false, errp);
- if (!bs->file) {
- ret = -EINVAL;
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
+ if (ret < 0) {
goto fail;
}
diff --git a/block/qcow2.c b/block/qcow2.c
index 6ee1919612..29ea157e6b 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1907,11 +1907,11 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags,
.errp = errp,
.ret = -EINPROGRESS
};
+ int ret;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
- BDRV_CHILD_IMAGE, false, errp);
- if (!bs->file) {
- return -EINVAL;
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
+ if (ret < 0) {
+ return ret;
}
/* Initialise locks */
diff --git a/block/qed.c b/block/qed.c
index 558d3646c4..e3b06a3d00 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -558,11 +558,11 @@ static int bdrv_qed_open(BlockDriverState *bs, QDict *options, int flags,
.errp = errp,
.ret = -EINPROGRESS
};
+ int ret;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
- BDRV_CHILD_IMAGE, false, errp);
- if (!bs->file) {
- return -EINVAL;
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
+ if (ret < 0) {
+ return ret;
}
bdrv_qed_init_state(bs);
diff --git a/block/replication.c b/block/replication.c
index 55c8f894aa..2f17397764 100644
--- a/block/replication.c
+++ b/block/replication.c
@@ -88,11 +88,9 @@ static int replication_open(BlockDriverState *bs, QDict *options,
const char *mode;
const char *top_id;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
- false, errp);
- if (!bs->file) {
- return -EINVAL;
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
+ if (ret < 0) {
+ return ret;
}
ret = -EINVAL;
diff --git a/block/throttle.c b/block/throttle.c
index 6e8d52fa24..4fb5798c27 100644
--- a/block/throttle.c
+++ b/block/throttle.c
@@ -78,11 +78,9 @@ static int throttle_open(BlockDriverState *bs, QDict *options,
char *group;
int ret;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
- BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY,
- false, errp);
- if (!bs->file) {
- return -EINVAL;
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
+ if (ret < 0) {
+ return ret;
}
bs->supported_write_flags = bs->file->bs->supported_write_flags |
BDRV_REQ_WRITE_UNCHANGED;
diff --git a/block/vdi.c b/block/vdi.c
index bdc58d726e..c50c0ed61f 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -376,10 +376,9 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
int ret;
QemuUUID uuid_link, uuid_parent;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
- BDRV_CHILD_IMAGE, false, errp);
- if (!bs->file) {
- return -EINVAL;
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
+ if (ret < 0) {
+ return ret;
}
logout("\n");
diff --git a/block/vhdx.c b/block/vhdx.c
index 356ec4c455..e7d6d7509a 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -996,10 +996,9 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
uint64_t signature;
Error *local_err = NULL;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
- BDRV_CHILD_IMAGE, false, errp);
- if (!bs->file) {
- return -EINVAL;
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
+ if (ret < 0) {
+ return ret;
}
s->bat = NULL;
diff --git a/block/vmdk.c b/block/vmdk.c
index 0dfab6e941..7d7e56b36c 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -1262,10 +1262,9 @@ static int vmdk_open(BlockDriverState *bs, QDict *options, int flags,
BDRVVmdkState *s = bs->opaque;
uint32_t magic;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
- BDRV_CHILD_IMAGE, false, errp);
- if (!bs->file) {
- return -EINVAL;
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
+ if (ret < 0) {
+ return ret;
}
buf = vmdk_read_desc(bs->file, 0, errp);
diff --git a/block/vpc.c b/block/vpc.c
index 297a26262a..430cab1cbb 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -232,10 +232,9 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
int ret;
int64_t bs_size;
- bs->file = bdrv_open_child(NULL, options, "file", bs, &child_of_bds,
- BDRV_CHILD_IMAGE, false, errp);
- if (!bs->file) {
- return -EINVAL;
+ ret = bdrv_open_file_child(NULL, options, "file", bs, errp);
+ if (ret < 0) {
+ return ret;
}
opts = qemu_opts_create(&vpc_runtime_opts, NULL, 0, &error_abort);
diff --git a/include/block/block.h b/include/block/block.h
index e5dd22b034..f885f113ef 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -376,6 +376,9 @@ BdrvChild *bdrv_open_child(const char *filename,
const BdrvChildClass *child_class,
BdrvChildRole child_role,
bool allow_none, Error **errp);
+int bdrv_open_file_child(const char *filename,
+ QDict *options, const char *bdref_key,
+ BlockDriverState *parent, Error **errp);
BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp);
int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
Error **errp);
--
2.39.3

View File

@ -1,69 +0,0 @@
From 837e09b1a8a38b53488f59aad090fbe6bb94e257 Mon Sep 17 00:00:00 2001
From: Thomas Huth <thuth@redhat.com>
Date: Fri, 17 Nov 2023 11:32:37 +0100
Subject: [PATCH 2/3] dump: Add arch cleanup function
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 323: Fix problem that secure execution guest might remain in "paused" state after failed dump
RH-Jira: RHEL-16696
RH-Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com>
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
RH-Commit: [2/3] b70f406dec88ffd4877f3d5d580fc8f821bdb252
JIRA: https://issues.redhat.com/browse/RHEL-16696
commit e72629e5149aba6f44122ea6d2a803ef136a0c6b
Author: Janosch Frank <frankja@linux.ibm.com>
Date: Thu Nov 9 12:04:42 2023 +0000
dump: Add arch cleanup function
Some architectures (s390x) need to cleanup after a failed dump to be
able to continue to run the vm. Add a cleanup function pointer and
call it if it's set.
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20231109120443.185979-3-frankja@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
dump/dump.c | 4 ++++
include/sysemu/dump-arch.h | 1 +
2 files changed, 5 insertions(+)
diff --git a/dump/dump.c b/dump/dump.c
index 5dee060b73..93edb89547 100644
--- a/dump/dump.c
+++ b/dump/dump.c
@@ -100,6 +100,10 @@ uint64_t cpu_to_dump64(DumpState *s, uint64_t val)
static int dump_cleanup(DumpState *s)
{
+ if (s->dump_info.arch_cleanup_fn) {
+ s->dump_info.arch_cleanup_fn(s);
+ }
+
guest_phys_blocks_free(&s->guest_phys_blocks);
memory_mapping_list_free(&s->list);
close(s->fd);
diff --git a/include/sysemu/dump-arch.h b/include/sysemu/dump-arch.h
index 59bbc9be38..743916e46c 100644
--- a/include/sysemu/dump-arch.h
+++ b/include/sysemu/dump-arch.h
@@ -24,6 +24,7 @@ typedef struct ArchDumpInfo {
void (*arch_sections_add_fn)(DumpState *s);
uint64_t (*arch_sections_write_hdr_fn)(DumpState *s, uint8_t *buff);
int (*arch_sections_write_fn)(DumpState *s, uint8_t *buff);
+ void (*arch_cleanup_fn)(DumpState *s);
} ArchDumpInfo;
struct GuestPhysBlockList; /* memory_mapping.h */
--
2.39.3

View File

@ -1,105 +0,0 @@
From 939c75ab92ac608893cad0e46f55527950518a57 Mon Sep 17 00:00:00 2001
From: Jon Maloy <jmaloy@redhat.com>
Date: Tue, 5 Mar 2024 11:36:15 -0500
Subject: [PATCH 1/3] glib-compat: Introduce g_memdup2() wrapper
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Jon Maloy <jmaloy@redhat.com>
RH-MergeRequest: 353: ui/clipboard: mark type as not available when there is no data
RH-Jira: RHEL-19628
RH-Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com>
RH-Acked-by: Gerd Hoffmann <None>
RH-Commit: [1/2] f401c63303ef558bfcbb36e4c8fcc8bf2b1c3eb4 (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2)
JIRA: https://issues.redhat.com/browse/RHEL-19628
CVE: CVE-2023-6683
Upstream: Merged
commit 2c674fada72079583a3f2cc1790b16a0259c4fa0
Author: Philippe Mathieu-Daudé <philmd@linaro.org>
Date: Fri Sep 3 19:44:44 2021 +0200
glib-compat: Introduce g_memdup2() wrapper
When experimenting raising GLIB_VERSION_MIN_REQUIRED to 2.68
(Fedora 34 provides GLib 2.68.1) we get:
hw/virtio/virtio-crypto.c:245:24: error: 'g_memdup' is deprecated: Use 'g_memdup2' instead [-Werror,-Wdeprecated-declarations]
...
g_memdup() has been updated by g_memdup2() to fix eventual security
issues (size argument is 32-bit and could be truncated / wrapping).
GLib recommends to copy their static inline version of g_memdup2():
https://discourse.gnome.org/t/port-your-module-from-g-memdup-to-g-memdup2-now/5538
Our glib-compat.h provides a comment explaining how to deal with
these deprecated declarations (see commit e71e8cc0355
"glib: enforce the minimum required version and warn about old APIs").
Following this comment suggestion, implement the g_memdup2_qemu()
wrapper to g_memdup2(), and use the safer equivalent inlined when
we are using pre-2.68 GLib.
Reported-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20210903174510.751630-3-philmd@redhat.com>
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
include/glib-compat.h | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/include/glib-compat.h b/include/glib-compat.h
index 9e95c888f5..8d01a8c01f 100644
--- a/include/glib-compat.h
+++ b/include/glib-compat.h
@@ -68,6 +68,43 @@
* without generating warnings.
*/
+/*
+ * g_memdup2_qemu:
+ * @mem: (nullable): the memory to copy.
+ * @byte_size: the number of bytes to copy.
+ *
+ * Allocates @byte_size bytes of memory, and copies @byte_size bytes into it
+ * from @mem. If @mem is %NULL it returns %NULL.
+ *
+ * This replaces g_memdup(), which was prone to integer overflows when
+ * converting the argument from a #gsize to a #guint.
+ *
+ * This static inline version is a backport of the new public API from
+ * GLib 2.68, kept internal to GLib for backport to older stable releases.
+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/2319.
+ *
+ * Returns: (nullable): a pointer to the newly-allocated copy of the memory,
+ * or %NULL if @mem is %NULL.
+ */
+static inline gpointer g_memdup2_qemu(gconstpointer mem, gsize byte_size)
+{
+#if GLIB_CHECK_VERSION(2, 68, 0)
+ return g_memdup2(mem, byte_size);
+#else
+ gpointer new_mem;
+
+ if (mem && byte_size != 0) {
+ new_mem = g_malloc(byte_size);
+ memcpy(new_mem, mem, byte_size);
+ } else {
+ new_mem = NULL;
+ }
+
+ return new_mem;
+#endif
+}
+#define g_memdup2(m, s) g_memdup2_qemu(m, s)
+
#if defined(G_OS_UNIX)
/*
* Note: The fallback implementation is not MT-safe, and it returns a copy of
--
2.41.0

View File

@ -1,119 +0,0 @@
From 4f6f881de10e31cac4636d5fde4b7ed4c8affadb Mon Sep 17 00:00:00 2001
From: Eric Auger <eric.auger@redhat.com>
Date: Thu, 4 Jan 2024 12:02:31 +0100
Subject: [PATCH 3/3] hw/arm/virt: Do not load efi-virtio.rom for all
virtio-net-pci variants
RH-Author: Eric Auger <eric.auger@redhat.com>
RH-MergeRequest: 344: hw/arm/virt: Do not load efi-virtio.rom for any virtio-net-pci variants
RH-Jira: RHEL-14870
RH-Acked-by: Gerd Hoffmann <None>
RH-Acked-by: Sebastian Ott <None>
RH-Commit: [1/1] ffeaa78ad0a1cff5b49009dfb32d25e5cadc0e05
Upstream: RHEL-only
Brew: http://brewweb.engineering.redhat.com/brew/taskinfo?taskID=5785640
Currently arm_rhel_compat just sets the romfile to "" for
virtio-net-pci and not for transitional and non transitional
variants. However, on aarch64 RHEL, efi-virtio.rom is not
shipped so transitional and non-transitional variants cannot
be used and the following error is obeserved:
"Could not open option rom 'efi-virtio.rom': No such file or directory"
In practice, we do not need any rom file for those virtio-net-pci
variants either because edk2 already brings the full functionality.
So let's change the applied compat to cover all the variants. While
at it also change the way arm_rhel_compat is applied. Instead of
applying it from the latest _virt_options(), which is error prone
when upgrading the machine type, let's apply it before calling
*virt_options in the non abstract machine class. That way the setting
will apply to any machine type without any need to add it in any
future machine types.
We don't really care keeping non void romfiles for transitional and
non transitional devices on previous machine types because this
was not working anyway.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
hw/arm/virt.c | 42 ++++++++++++++++++++++++++++--------------
1 file changed, 28 insertions(+), 14 deletions(-)
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index dbf0a6d62f..46c72a9611 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -108,11 +108,39 @@
DEFINE_VIRT_MACHINE_LATEST(major, minor, false)
#endif /* disabled for RHEL */
+/*
+ * This variable is for changes to properties that are RHEL specific,
+ * different to the current upstream and to be applied to the latest
+ * machine type. They may be overriden by older machine compats.
+ *
+ * virtio-net-pci variant romfiles are not needed because edk2 does
+ * fully support the pxe boot. Besides virtio romfiles are not shipped
+ * on rhel/aarch64.
+ */
+GlobalProperty arm_rhel_compat[] = {
+ {"virtio-net-pci", "romfile", "" },
+ {"virtio-net-pci-transitional", "romfile", "" },
+ {"virtio-net-pci-non-transitional", "romfile", "" },
+};
+const size_t arm_rhel_compat_len = G_N_ELEMENTS(arm_rhel_compat);
+
+/*
+ * This cannot be called from the rhel_virt_class_init() because
+ * TYPE_RHEL_MACHINE is abstract and mc->compat_props g_ptr_array_new()
+ * only is called on virt-rhelm.n.s non abstract class init.
+ */
+static void arm_rhel_compat_set(MachineClass *mc)
+{
+ compat_props_add(mc->compat_props, arm_rhel_compat,
+ arm_rhel_compat_len);
+}
+
#define DEFINE_RHEL_MACHINE_LATEST(m, n, s, latest) \
static void rhel##m##n##s##_virt_class_init(ObjectClass *oc, \
void *data) \
{ \
MachineClass *mc = MACHINE_CLASS(oc); \
+ arm_rhel_compat_set(mc); \
rhel##m##n##s##_virt_options(mc); \
mc->desc = "RHEL " # m "." # n "." # s " ARM Virtual Machine"; \
if (latest) { \
@@ -136,19 +164,6 @@
#define DEFINE_RHEL_MACHINE(major, minor, subminor) \
DEFINE_RHEL_MACHINE_LATEST(major, minor, subminor, false)
-/* This variable is for changes to properties that are RHEL specific,
- * different to the current upstream and to be applied to the latest
- * machine type.
- */
-GlobalProperty arm_rhel_compat[] = {
- {
- .driver = "virtio-net-pci",
- .property = "romfile",
- .value = "",
- },
-};
-const size_t arm_rhel_compat_len = G_N_ELEMENTS(arm_rhel_compat);
-
/* Number of external interrupt lines to configure the GIC with */
#define NUM_IRQS 256
@@ -3240,7 +3255,6 @@ type_init(rhel_machine_init);
static void rhel860_virt_options(MachineClass *mc)
{
- compat_props_add(mc->compat_props, arm_rhel_compat, arm_rhel_compat_len);
}
DEFINE_RHEL_MACHINE_AS_LATEST(8, 6, 0)
--
2.41.0

View File

@ -1,61 +0,0 @@
From f4623ea611a74c684b0097b98a803cbe7ffb0825 Mon Sep 17 00:00:00 2001
From: Jon Maloy <jmaloy@redhat.com>
Date: Thu, 18 Jul 2024 09:26:55 -0400
Subject: [PATCH 5/6] hw/char/virtio-serial-bus: Protect from DMA re-entrancy
bugs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Jon Maloy <jmaloy@redhat.com>
RH-MergeRequest: 380: QEMU: virtio: DMA reentrancy issue leads to double free vulnerability
RH-Jira: RHEL-32276
RH-Acked-by: Gerd Hoffmann <None>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Commit: [5/6] fc8a445ebf6e763cd1482cd1f7ee23e5b5bbb388 (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2)
JIRA: https://issues.redhat.com/browse/RHEL-32276
CVE: CVE-2024-3446
Upstream: Merged
commit b4295bff25f7b50de1d9cc94a9c6effd40056bca
Author: Philippe Mathieu-Daudé <philmd@linaro.org>
Date: Thu Apr 4 20:56:35 2024 +0200
hw/char/virtio-serial-bus: Protect from DMA re-entrancy bugs
Replace qemu_bh_new_guarded() by virtio_bh_new_guarded()
so the bus and device use the same guard. Otherwise the
DMA-reentrancy protection can be bypassed.
Fixes: CVE-2024-3446
Cc: qemu-stable@nongnu.org
Suggested-by: Alexander Bulekov <alxndr@bu.edu>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20240409105537.18308-4-philmd@linaro.org>
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
hw/char/virtio-serial-bus.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c
index f18124b155..791b7ac59e 100644
--- a/hw/char/virtio-serial-bus.c
+++ b/hw/char/virtio-serial-bus.c
@@ -985,8 +985,7 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp)
return;
}
- port->bh = qemu_bh_new_guarded(flush_queued_data_bh, port,
- &dev->mem_reentrancy_guard);
+ port->bh = virtio_bh_new_guarded(dev, flush_queued_data_bh, port);
port->elem = NULL;
}
--
2.39.3

View File

@ -1,160 +0,0 @@
From d37035373a266644b241aab1f041ab09c9185540 Mon Sep 17 00:00:00 2001
From: Jon Maloy <jmaloy@redhat.com>
Date: Thu, 18 Jul 2024 09:29:54 -0400
Subject: [PATCH 4/6] hw/display/virtio-gpu: Protect from DMA re-entrancy bugs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Jon Maloy <jmaloy@redhat.com>
RH-MergeRequest: 380: QEMU: virtio: DMA reentrancy issue leads to double free vulnerability
RH-Jira: RHEL-32276
RH-Acked-by: Gerd Hoffmann <None>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Commit: [4/6] e3cd21742228528a1a74ea62d55b5941d3efb261 (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2)
JIRA: https://issues.redhat.com/browse/RHEL-32276
CVE: CVE-2024-3446
Upstream: Merged
commit ba28e0ff4d95b56dc334aac2730ab3651ffc3132
Author: Philippe Mathieu-Daudé <philmd@linaro.org>
Date: Thu Apr 4 20:56:27 2024 +0200
hw/display/virtio-gpu: Protect from DMA re-entrancy bugs
Replace qemu_bh_new_guarded() by virtio_bh_new_guarded()
so the bus and device use the same guard. Otherwise the
DMA-reentrancy protection can be bypassed:
$ cat << EOF | qemu-system-i386 -display none -nodefaults \
-machine q35,accel=qtest \
-m 512M \
-device virtio-gpu \
-qtest stdio
outl 0xcf8 0x80000820
outl 0xcfc 0xe0004000
outl 0xcf8 0x80000804
outw 0xcfc 0x06
write 0xe0004030 0x4 0x024000e0
write 0xe0004028 0x1 0xff
write 0xe0004020 0x4 0x00009300
write 0xe000401c 0x1 0x01
write 0x101 0x1 0x04
write 0x103 0x1 0x1c
write 0x9301c8 0x1 0x18
write 0x105 0x1 0x1c
write 0x107 0x1 0x1c
write 0x109 0x1 0x1c
write 0x10b 0x1 0x00
write 0x10d 0x1 0x00
write 0x10f 0x1 0x00
write 0x111 0x1 0x00
write 0x113 0x1 0x00
write 0x115 0x1 0x00
write 0x117 0x1 0x00
write 0x119 0x1 0x00
write 0x11b 0x1 0x00
write 0x11d 0x1 0x00
write 0x11f 0x1 0x00
write 0x121 0x1 0x00
write 0x123 0x1 0x00
write 0x125 0x1 0x00
write 0x127 0x1 0x00
write 0x129 0x1 0x00
write 0x12b 0x1 0x00
write 0x12d 0x1 0x00
write 0x12f 0x1 0x00
write 0x131 0x1 0x00
write 0x133 0x1 0x00
write 0x135 0x1 0x00
write 0x137 0x1 0x00
write 0x139 0x1 0x00
write 0xe0007003 0x1 0x00
EOF
...
=================================================================
==276099==ERROR: AddressSanitizer: heap-use-after-free on address 0x60d000011178
at pc 0x562cc3b736c7 bp 0x7ffed49dee60 sp 0x7ffed49dee58
READ of size 8 at 0x60d000011178 thread T0
#0 0x562cc3b736c6 in virtio_gpu_ctrl_response hw/display/virtio-gpu.c:180:42
#1 0x562cc3b7c40b in virtio_gpu_ctrl_response_nodata hw/display/virtio-gpu.c:192:5
#2 0x562cc3b7c40b in virtio_gpu_simple_process_cmd hw/display/virtio-gpu.c:1015:13
#3 0x562cc3b82873 in virtio_gpu_process_cmdq hw/display/virtio-gpu.c:1050:9
#4 0x562cc4a85514 in aio_bh_call util/async.c:169:5
#5 0x562cc4a85c52 in aio_bh_poll util/async.c:216:13
#6 0x562cc4a1a79b in aio_dispatch util/aio-posix.c:423:5
#7 0x562cc4a8a2da in aio_ctx_dispatch util/async.c:358:5
#8 0x7f36840547a8 in g_main_context_dispatch (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x547a8)
#9 0x562cc4a8b753 in glib_pollfds_poll util/main-loop.c:290:9
#10 0x562cc4a8b753 in os_host_main_loop_wait util/main-loop.c:313:5
#11 0x562cc4a8b753 in main_loop_wait util/main-loop.c:592:11
#12 0x562cc3938186 in qemu_main_loop system/runstate.c:782:9
#13 0x562cc43b7af5 in qemu_default_main system/main.c:37:14
#14 0x7f3683a6c189 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#15 0x7f3683a6c244 in __libc_start_main csu/../csu/libc-start.c:381:3
#16 0x562cc2a58ac0 in _start (qemu-system-i386+0x231bac0)
0x60d000011178 is located 56 bytes inside of 136-byte region [0x60d000011140,0x60d0000111c8)
freed by thread T0 here:
#0 0x562cc2adb662 in __interceptor_free (qemu-system-i386+0x239e662)
#1 0x562cc3b86b21 in virtio_gpu_reset hw/display/virtio-gpu.c:1524:9
#2 0x562cc416e20e in virtio_reset hw/virtio/virtio.c:2145:9
#3 0x562cc37c5644 in virtio_pci_reset hw/virtio/virtio-pci.c:2249:5
#4 0x562cc4233758 in memory_region_write_accessor system/memory.c:497:5
#5 0x562cc4232eea in access_with_adjusted_size system/memory.c:573:18
previously allocated by thread T0 here:
#0 0x562cc2adb90e in malloc (qemu-system-i386+0x239e90e)
#1 0x7f368405a678 in g_malloc (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x5a678)
#2 0x562cc4163ffc in virtqueue_split_pop hw/virtio/virtio.c:1612:12
#3 0x562cc4163ffc in virtqueue_pop hw/virtio/virtio.c:1783:16
#4 0x562cc3b91a95 in virtio_gpu_handle_ctrl hw/display/virtio-gpu.c:1112:15
#5 0x562cc4a85514 in aio_bh_call util/async.c:169:5
#6 0x562cc4a85c52 in aio_bh_poll util/async.c:216:13
#7 0x562cc4a1a79b in aio_dispatch util/aio-posix.c:423:5
SUMMARY: AddressSanitizer: heap-use-after-free hw/display/virtio-gpu.c:180:42 in virtio_gpu_ctrl_response
With this change, the same reproducer triggers:
qemu-system-i386: warning: Blocked re-entrant IO on MemoryRegion: virtio-pci-common-virtio-gpu at addr: 0x6
Fixes: CVE-2024-3446
Cc: qemu-stable@nongnu.org
Reported-by: Alexander Bulekov <alxndr@bu.edu>
Reported-by: Yongkang Jia <kangel@zju.edu.cn>
Reported-by: Xiao Lei <nop.leixiao@gmail.com>
Reported-by: Yiming Tao <taoym@zju.edu.cn>
Buglink: https://bugs.launchpad.net/qemu/+bug/1888606
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20240409105537.18308-3-philmd@linaro.org>
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
hw/display/virtio-gpu.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index c28ce1ea72..64fdc18478 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1334,10 +1334,8 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
g->ctrl_vq = virtio_get_queue(vdev, 0);
g->cursor_vq = virtio_get_queue(vdev, 1);
- g->ctrl_bh = qemu_bh_new_guarded(virtio_gpu_ctrl_bh, g,
- &qdev->mem_reentrancy_guard);
- g->cursor_bh = qemu_bh_new_guarded(virtio_gpu_cursor_bh, g,
- &qdev->mem_reentrancy_guard);
+ g->ctrl_bh = virtio_bh_new_guarded(qdev, virtio_gpu_ctrl_bh, g);
+ g->cursor_bh = virtio_bh_new_guarded(qdev, virtio_gpu_cursor_bh, g);
g->reset_bh = qemu_bh_new(virtio_gpu_reset_bh, g);
qemu_cond_init(&g->reset_cond);
QTAILQ_INIT(&g->reslist);
--
2.39.3

View File

@ -1,128 +0,0 @@
From 2308abf0c5da2fe35a0721318c31d22e077663c2 Mon Sep 17 00:00:00 2001
From: Jon Maloy <jmaloy@redhat.com>
Date: Fri, 24 Nov 2023 12:17:11 -0500
Subject: [PATCH 1/2] hw/ide: reset: cancel async DMA operation before
resetting state
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Jon Maloy <jmaloy@redhat.com>
RH-MergeRequest: 335: hw/ide: reset: cancel async DMA operation before resetting state
RH-Jira: RHEL-15437
RH-Acked-by: Hanna Czenczek <hreitz@redhat.com>
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Commit: [1/2] b0f5f7f888559a210f1c6b3c545e337dbbc9cf22 (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2)
JIRA: https://issues.redhat.com/browse/RHEL-15437
CVE: CVE-2023-5088
Upstream: Merged
commit 7d7512019fc40c577e2bdd61f114f31a9eb84a8e
Author: Fiona Ebner <f.ebner@proxmox.com>
Date: Wed Sep 6 15:09:21 2023 +0200
hw/ide: reset: cancel async DMA operation before resetting state
If there is a pending DMA operation during ide_bus_reset(), the fact
that the IDEState is already reset before the operation is canceled
can be problematic. In particular, ide_dma_cb() might be called and
then use the reset IDEState which contains the signature after the
reset. When used to construct the IO operation this leads to
ide_get_sector() returning 0 and nsector being 1. This is particularly
bad, because a write command will thus destroy the first sector which
often contains a partition table or similar.
Traces showing the unsolicited write happening with IDEState
0x5595af6949d0 being used after reset:
> ahci_port_write ahci(0x5595af6923f0)[0]: port write [reg:PxSCTL] @ 0x2c: 0x00000300
> ahci_reset_port ahci(0x5595af6923f0)[0]: reset port
> ide_reset IDEstate 0x5595af6949d0
> ide_reset IDEstate 0x5595af694da8
> ide_bus_reset_aio aio_cancel
> dma_aio_cancel dbs=0x7f64600089a0
> dma_blk_cb dbs=0x7f64600089a0 ret=0
> dma_complete dbs=0x7f64600089a0 ret=0 cb=0x5595acd40b30
> ahci_populate_sglist ahci(0x5595af6923f0)[0]
> ahci_dma_prepare_buf ahci(0x5595af6923f0)[0]: prepare buf limit=512 prepared=512
> ide_dma_cb IDEState 0x5595af6949d0; sector_num=0 n=1 cmd=DMA WRITE
> dma_blk_io dbs=0x7f6420802010 bs=0x5595ae2c6c30 offset=0 to_dev=1
> dma_blk_cb dbs=0x7f6420802010 ret=0
> (gdb) p *qiov
> $11 = {iov = 0x7f647c76d840, niov = 1, {{nalloc = 1, local_iov = {iov_base = 0x0,
> iov_len = 512}}, {__pad = "\001\000\000\000\000\000\000\000\000\000\000",
> size = 512}}}
> (gdb) bt
> #0 blk_aio_pwritev (blk=0x5595ae2c6c30, offset=0, qiov=0x7f6420802070, flags=0,
> cb=0x5595ace6f0b0 <dma_blk_cb>, opaque=0x7f6420802010)
> at ../block/block-backend.c:1682
> #1 0x00005595ace6f185 in dma_blk_cb (opaque=0x7f6420802010, ret=<optimized out>)
> at ../softmmu/dma-helpers.c:179
> #2 0x00005595ace6f778 in dma_blk_io (ctx=0x5595ae0609f0,
> sg=sg@entry=0x5595af694d00, offset=offset@entry=0, align=align@entry=512,
> io_func=io_func@entry=0x5595ace6ee30 <dma_blk_write_io_func>,
> io_func_opaque=io_func_opaque@entry=0x5595ae2c6c30,
> cb=0x5595acd40b30 <ide_dma_cb>, opaque=0x5595af6949d0,
> dir=DMA_DIRECTION_TO_DEVICE) at ../softmmu/dma-helpers.c:244
> #3 0x00005595ace6f90a in dma_blk_write (blk=0x5595ae2c6c30,
> sg=sg@entry=0x5595af694d00, offset=offset@entry=0, align=align@entry=512,
> cb=cb@entry=0x5595acd40b30 <ide_dma_cb>, opaque=opaque@entry=0x5595af6949d0)
> at ../softmmu/dma-helpers.c:280
> #4 0x00005595acd40e18 in ide_dma_cb (opaque=0x5595af6949d0, ret=<optimized out>)
> at ../hw/ide/core.c:953
> #5 0x00005595ace6f319 in dma_complete (ret=0, dbs=0x7f64600089a0)
> at ../softmmu/dma-helpers.c:107
> #6 dma_blk_cb (opaque=0x7f64600089a0, ret=0) at ../softmmu/dma-helpers.c:127
> #7 0x00005595ad12227d in blk_aio_complete (acb=0x7f6460005b10)
> at ../block/block-backend.c:1527
> #8 blk_aio_complete (acb=0x7f6460005b10) at ../block/block-backend.c:1524
> #9 blk_aio_write_entry (opaque=0x7f6460005b10) at ../block/block-backend.c:1594
> #10 0x00005595ad258cfb in coroutine_trampoline (i0=<optimized out>,
> i1=<optimized out>) at ../util/coroutine-ucontext.c:177
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Tested-by: simon.rowe@nutanix.com
Message-ID: <20230906130922.142845-1-f.ebner@proxmox.com>
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
hw/ide/core.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 05a32d0a99..fd50c123e8 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2456,19 +2456,19 @@ static void ide_dummy_transfer_stop(IDEState *s)
void ide_bus_reset(IDEBus *bus)
{
- bus->unit = 0;
- bus->cmd = 0;
- ide_reset(&bus->ifs[0]);
- ide_reset(&bus->ifs[1]);
- ide_clear_hob(bus);
-
- /* pending async DMA */
+ /* pending async DMA - needs the IDEState before it is reset */
if (bus->dma->aiocb) {
trace_ide_bus_reset_aio();
blk_aio_cancel(bus->dma->aiocb);
bus->dma->aiocb = NULL;
}
+ bus->unit = 0;
+ bus->cmd = 0;
+ ide_reset(&bus->ifs[0]);
+ ide_reset(&bus->ifs[1]);
+ ide_clear_hob(bus);
+
/* reset dma provider too */
if (bus->dma->ops->reset) {
bus->dma->ops->reset(bus->dma);
--
2.41.0

View File

@ -1,283 +0,0 @@
From 59f02a421ecdba6e856597367020926fc0cb5177 Mon Sep 17 00:00:00 2001
From: Thomas Huth <thuth@redhat.com>
Date: Mon, 15 Jan 2024 18:52:30 +0100
Subject: [PATCH 4/5] hw/s390x: Move KVM specific PV from hw/ to
target/s390x/kvm/
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 348: s390x: Provide some more useful information if decryption of a PV image fails
RH-Jira: RHEL-18214
RH-Acked-by: Jon Maloy <jmaloy@redhat.com>
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
RH-Commit: [4/5] f6095bfdb89268007a0741665284955db4752d46
JIRA: https://issues.redhat.com/browse/RHEL-18214
commit f5f9c6ea11bc807664fdeb9354915c2c9cdcbd89
Author: Philippe Mathieu-Daudé <philmd@linaro.org>
Date: Sat Jun 24 22:06:44 2023 +0200
hw/s390x: Move KVM specific PV from hw/ to target/s390x/kvm/
Protected Virtualization (PV) is not a real hardware device:
it is a feature of the firmware on s390x that is exposed to
userspace via the KVM interface.
Move the pv.c/pv.h files to target/s390x/kvm/ to make this clearer.
Suggested-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20230624200644.23931-1-philmd@linaro.org>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Conflicts:
hw/s390x/ipl.c
hw/s390x/s390-virtio-ccw.c
target/s390x/diag.c
(simple contextual conflict due to differce with #include statements)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
MAINTAINERS | 2 --
hw/s390x/ipl.c | 2 +-
hw/s390x/meson.build | 1 -
hw/s390x/s390-pci-kvm.c | 2 +-
hw/s390x/s390-virtio-ccw.c | 2 +-
hw/s390x/tod-kvm.c | 2 +-
target/s390x/arch_dump.c | 2 +-
target/s390x/cpu-sysemu.c | 2 +-
target/s390x/cpu_features.c | 2 +-
target/s390x/cpu_models.c | 2 +-
target/s390x/diag.c | 2 +-
target/s390x/helper.c | 2 +-
target/s390x/ioinst.c | 2 +-
target/s390x/kvm/kvm.c | 2 +-
target/s390x/kvm/meson.build | 1 +
{hw/s390x => target/s390x/kvm}/pv.c | 2 +-
{include/hw/s390x => target/s390x/kvm}/pv.h | 0
17 files changed, 14 insertions(+), 16 deletions(-)
rename {hw/s390x => target/s390x/kvm}/pv.c (99%)
rename {include/hw/s390x => target/s390x/kvm}/pv.h (100%)
diff --git a/MAINTAINERS b/MAINTAINERS
index b893206fc3..d74ca51154 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -397,8 +397,6 @@ S: Supported
F: target/s390x/kvm/
F: target/s390x/machine.c
F: target/s390x/sigp.c
-F: hw/s390x/pv.c
-F: include/hw/s390x/pv.h
F: gdb-xml/s390*.xml
T: git https://github.com/borntraeger/qemu.git s390-next
L: qemu-s390x@nongnu.org
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index 9051d8652d..c25e247426 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -27,7 +27,7 @@
#include "hw/s390x/vfio-ccw.h"
#include "hw/s390x/css.h"
#include "hw/s390x/ebcdic.h"
-#include "hw/s390x/pv.h"
+#include "target/s390x/kvm/pv.h"
#include "ipl.h"
#include "qemu/error-report.h"
#include "qemu/config-file.h"
diff --git a/hw/s390x/meson.build b/hw/s390x/meson.build
index 6e6e47fcda..bb3b42f613 100644
--- a/hw/s390x/meson.build
+++ b/hw/s390x/meson.build
@@ -22,7 +22,6 @@ s390x_ss.add(when: 'CONFIG_KVM', if_true: files(
'tod-kvm.c',
's390-skeys-kvm.c',
's390-stattrib-kvm.c',
- 'pv.c',
's390-pci-kvm.c',
))
s390x_ss.add(when: 'CONFIG_TCG', if_true: files(
diff --git a/hw/s390x/s390-pci-kvm.c b/hw/s390x/s390-pci-kvm.c
index 9134fe185f..ff41e4106d 100644
--- a/hw/s390x/s390-pci-kvm.c
+++ b/hw/s390x/s390-pci-kvm.c
@@ -14,7 +14,7 @@
#include <linux/kvm.h>
#include "kvm/kvm_s390x.h"
-#include "hw/s390x/pv.h"
+#include "target/s390x/kvm/pv.h"
#include "hw/s390x/s390-pci-bus.h"
#include "hw/s390x/s390-pci-kvm.h"
#include "hw/s390x/s390-pci-inst.h"
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 17146469ee..7bfa5b4e8f 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -40,7 +40,7 @@
#include "hw/qdev-properties.h"
#include "hw/s390x/tod.h"
#include "sysemu/sysemu.h"
-#include "hw/s390x/pv.h"
+#include "target/s390x/kvm/pv.h"
#include "migration/blocker.h"
#include "qapi/visitor.h"
diff --git a/hw/s390x/tod-kvm.c b/hw/s390x/tod-kvm.c
index c804c979b5..9776cda50a 100644
--- a/hw/s390x/tod-kvm.c
+++ b/hw/s390x/tod-kvm.c
@@ -13,7 +13,7 @@
#include "qemu/module.h"
#include "sysemu/runstate.h"
#include "hw/s390x/tod.h"
-#include "hw/s390x/pv.h"
+#include "target/s390x/kvm/pv.h"
#include "kvm/kvm_s390x.h"
static void kvm_s390_get_tod_raw(S390TOD *tod, Error **errp)
diff --git a/target/s390x/arch_dump.c b/target/s390x/arch_dump.c
index 3b1f178dc3..2554238c16 100644
--- a/target/s390x/arch_dump.c
+++ b/target/s390x/arch_dump.c
@@ -17,8 +17,8 @@
#include "s390x-internal.h"
#include "elf.h"
#include "sysemu/dump.h"
-#include "hw/s390x/pv.h"
#include "kvm/kvm_s390x.h"
+#include "target/s390x/kvm/pv.h"
struct S390xUserRegsStruct {
uint64_t psw[2];
diff --git a/target/s390x/cpu-sysemu.c b/target/s390x/cpu-sysemu.c
index 5471e01ee8..547287a949 100644
--- a/target/s390x/cpu-sysemu.c
+++ b/target/s390x/cpu-sysemu.c
@@ -32,7 +32,7 @@
#include "qapi/qapi-visit-run-state.h"
#include "sysemu/hw_accel.h"
-#include "hw/s390x/pv.h"
+#include "target/s390x/kvm/pv.h"
#include "hw/boards.h"
#include "sysemu/sysemu.h"
#include "sysemu/tcg.h"
diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c
index 2e4e11d264..ebb155ce1c 100644
--- a/target/s390x/cpu_features.c
+++ b/target/s390x/cpu_features.c
@@ -15,7 +15,7 @@
#include "qemu/module.h"
#include "cpu_features.h"
#ifndef CONFIG_USER_ONLY
-#include "hw/s390x/pv.h"
+#include "target/s390x/kvm/pv.h"
#endif
#define DEF_FEAT(_FEAT, _NAME, _TYPE, _BIT, _DESC) \
diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c
index e7c586c76e..100c5e7b3a 100644
--- a/target/s390x/cpu_models.c
+++ b/target/s390x/cpu_models.c
@@ -22,7 +22,7 @@
#include "qemu/qemu-print.h"
#ifndef CONFIG_USER_ONLY
#include "sysemu/sysemu.h"
-#include "hw/s390x/pv.h"
+#include "target/s390x/kvm/pv.h"
#endif
#define CPUDEF_INIT(_type, _gen, _ec_ga, _mha_pow, _hmfai, _name, _desc) \
diff --git a/target/s390x/diag.c b/target/s390x/diag.c
index 76b01dcd68..7c8714cc27 100644
--- a/target/s390x/diag.c
+++ b/target/s390x/diag.c
@@ -19,9 +19,9 @@
#include "sysemu/cpus.h"
#include "hw/s390x/ipl.h"
#include "hw/s390x/s390-virtio-ccw.h"
-#include "hw/s390x/pv.h"
#include "sysemu/kvm.h"
#include "kvm/kvm_s390x.h"
+#include "target/s390x/kvm/pv.h"
int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3)
{
diff --git a/target/s390x/helper.c b/target/s390x/helper.c
index 6e35473c7f..860977126a 100644
--- a/target/s390x/helper.c
+++ b/target/s390x/helper.c
@@ -24,7 +24,7 @@
#include "exec/gdbstub.h"
#include "qemu/timer.h"
#include "hw/s390x/ioinst.h"
-#include "hw/s390x/pv.h"
+#include "target/s390x/kvm/pv.h"
#include "sysemu/hw_accel.h"
#include "sysemu/runstate.h"
#include "sysemu/tcg.h"
diff --git a/target/s390x/ioinst.c b/target/s390x/ioinst.c
index bdae5090bc..409f3e3e63 100644
--- a/target/s390x/ioinst.c
+++ b/target/s390x/ioinst.c
@@ -16,7 +16,7 @@
#include "hw/s390x/ioinst.h"
#include "trace.h"
#include "hw/s390x/s390-pci-bus.h"
-#include "hw/s390x/pv.h"
+#include "target/s390x/kvm/pv.h"
/* All I/O instructions but chsc use the s format */
static uint64_t get_address_from_regs(CPUS390XState *env, uint32_t ipb,
diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c
index a963866ef4..6d1a6324b9 100644
--- a/target/s390x/kvm/kvm.c
+++ b/target/s390x/kvm/kvm.c
@@ -51,7 +51,7 @@
#include "exec/memattrs.h"
#include "hw/s390x/s390-virtio-ccw.h"
#include "hw/s390x/s390-virtio-hcall.h"
-#include "hw/s390x/pv.h"
+#include "target/s390x/kvm/pv.h"
#ifndef DEBUG_KVM
#define DEBUG_KVM 0
diff --git a/target/s390x/kvm/meson.build b/target/s390x/kvm/meson.build
index aef52b6686..739d5b9f54 100644
--- a/target/s390x/kvm/meson.build
+++ b/target/s390x/kvm/meson.build
@@ -1,5 +1,6 @@
s390x_ss.add(when: 'CONFIG_KVM', if_true: files(
+ 'pv.c',
'kvm.c'
), if_false: files(
'stubs.c'
diff --git a/hw/s390x/pv.c b/target/s390x/kvm/pv.c
similarity index 99%
rename from hw/s390x/pv.c
rename to target/s390x/kvm/pv.c
index 8a1c71436b..e14db4f41a 100644
--- a/hw/s390x/pv.c
+++ b/target/s390x/kvm/pv.c
@@ -19,9 +19,9 @@
#include "qom/object_interfaces.h"
#include "exec/confidential-guest-support.h"
#include "hw/s390x/ipl.h"
-#include "hw/s390x/pv.h"
#include "hw/s390x/sclp.h"
#include "target/s390x/kvm/kvm_s390x.h"
+#include "target/s390x/kvm/pv.h"
static bool info_valid;
static struct kvm_s390_pv_info_vm info_vm;
diff --git a/include/hw/s390x/pv.h b/target/s390x/kvm/pv.h
similarity index 100%
rename from include/hw/s390x/pv.h
rename to target/s390x/kvm/pv.h
--
2.41.0

View File

@ -1,100 +0,0 @@
From 053faafcf523b0ea4d841c0af8e7e26a2cddd5e8 Mon Sep 17 00:00:00 2001
From: Thomas Huth <thuth@redhat.com>
Date: Mon, 15 Jan 2024 14:00:04 +0100
Subject: [PATCH 3/5] hw/s390x/pv: Restrict Protected Virtualization to sysemu
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 348: s390x: Provide some more useful information if decryption of a PV image fails
RH-Jira: RHEL-18214
RH-Acked-by: Jon Maloy <jmaloy@redhat.com>
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
RH-Commit: [3/5] 17b11f9fd2b53c7d33c09a62f28cfca19b18e798
JIRA: https://issues.redhat.com/browse/RHEL-18214
commit 3ea7e312671686e616efa1b8caa5f5ce2d06543a
Author: Philippe Mathieu-Daudé <philmd@linaro.org>
Date: Sat Dec 17 16:24:52 2022 +0100
hw/s390x/pv: Restrict Protected Virtualization to sysemu
Protected Virtualization is irrelevant in user emulation.
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20221217152454.96388-4-philmd@linaro.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
target/s390x/cpu_features.c | 4 ++++
target/s390x/cpu_models.c | 4 +++-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c
index 5528acd082..2e4e11d264 100644
--- a/target/s390x/cpu_features.c
+++ b/target/s390x/cpu_features.c
@@ -14,7 +14,9 @@
#include "qemu/osdep.h"
#include "qemu/module.h"
#include "cpu_features.h"
+#ifndef CONFIG_USER_ONLY
#include "hw/s390x/pv.h"
+#endif
#define DEF_FEAT(_FEAT, _NAME, _TYPE, _BIT, _DESC) \
[S390_FEAT_##_FEAT] = { \
@@ -107,6 +109,7 @@ void s390_fill_feat_block(const S390FeatBitmap features, S390FeatType type,
feat = find_next_bit(features, S390_FEAT_MAX, feat + 1);
}
+#ifndef CONFIG_USER_ONLY
if (!s390_is_pv()) {
return;
}
@@ -147,6 +150,7 @@ void s390_fill_feat_block(const S390FeatBitmap features, S390FeatType type,
default:
return;
}
+#endif
}
void s390_add_from_feat_block(S390FeatBitmap features, S390FeatType type,
diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c
index 454485e706..e7c586c76e 100644
--- a/target/s390x/cpu_models.c
+++ b/target/s390x/cpu_models.c
@@ -22,8 +22,8 @@
#include "qemu/qemu-print.h"
#ifndef CONFIG_USER_ONLY
#include "sysemu/sysemu.h"
-#endif
#include "hw/s390x/pv.h"
+#endif
#define CPUDEF_INIT(_type, _gen, _ec_ga, _mha_pow, _hmfai, _name, _desc) \
{ \
@@ -236,6 +236,7 @@ bool s390_has_feat(S390Feat feat)
return 0;
}
+#ifndef CONFIG_USER_ONLY
if (s390_is_pv()) {
switch (feat) {
case S390_FEAT_DIAG_318:
@@ -259,6 +260,7 @@ bool s390_has_feat(S390Feat feat)
break;
}
}
+#endif
return test_bit(feat, cpu->model->features);
}
--
2.41.0

View File

@ -1,86 +0,0 @@
From 1b62d61c495bf4cd3a819ab8d1ef024d153e0ece Mon Sep 17 00:00:00 2001
From: Jon Maloy <jmaloy@redhat.com>
Date: Thu, 18 Jul 2024 09:40:29 -0400
Subject: [PATCH 3/6] hw/virtio: Introduce virtio_bh_new_guarded() helper
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Jon Maloy <jmaloy@redhat.com>
RH-MergeRequest: 380: QEMU: virtio: DMA reentrancy issue leads to double free vulnerability
RH-Jira: RHEL-32276
RH-Acked-by: Gerd Hoffmann <None>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Commit: [3/6] 1cbde7ddb8393b72e2e8d457b5e2d739116567a9 (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2)
JIRA: https://issues.redhat.com/browse/RHEL-32276
CVE: CVE-2024-3446
Upstream: Merged
commit ec0504b989ca61e03636384d3602b7bf07ffe4da
Author: Philippe Mathieu-Daudé <philmd@linaro.org>
Date: Thu Apr 4 20:56:11 2024 +0200
hw/virtio: Introduce virtio_bh_new_guarded() helper
Introduce virtio_bh_new_guarded(), similar to qemu_bh_new_guarded()
but using the transport memory guard, instead of the device one
(there can only be one virtio device per virtio bus).
Inspired-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20240409105537.18308-2-philmd@linaro.org>
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
hw/virtio/virtio.c | 10 ++++++++++
include/hw/virtio/virtio.h | 7 +++++++
2 files changed, 17 insertions(+)
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index ea7c079fb0..5ae9c44841 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -3874,3 +3874,13 @@ static void virtio_register_types(void)
}
type_init(virtio_register_types)
+
+QEMUBH *virtio_bh_new_guarded_full(DeviceState *dev,
+ QEMUBHFunc *cb, void *opaque,
+ const char *name)
+{
+ DeviceState *transport = qdev_get_parent_bus(dev)->parent;
+
+ return qemu_bh_new_full(cb, opaque, name,
+ &transport->mem_reentrancy_guard);
+}
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 8bab9cfb75..731c631a81 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -22,6 +22,7 @@
#include "standard-headers/linux/virtio_config.h"
#include "standard-headers/linux/virtio_ring.h"
#include "qom/object.h"
+#include "block/aio.h"
/* A guest should never accept this. It implies negotiation is broken. */
#define VIRTIO_F_BAD_FEATURE 30
@@ -397,4 +398,10 @@ static inline bool virtio_device_disabled(VirtIODevice *vdev)
bool virtio_legacy_allowed(VirtIODevice *vdev);
bool virtio_legacy_check_disabled(VirtIODevice *vdev);
+QEMUBH *virtio_bh_new_guarded_full(DeviceState *dev,
+ QEMUBHFunc *cb, void *opaque,
+ const char *name);
+#define virtio_bh_new_guarded(dev, cb, opaque) \
+ virtio_bh_new_guarded_full((dev), (cb), (opaque), (stringify(cb)))
+
#endif
--
2.39.3

View File

@ -1,62 +0,0 @@
From 2ecbd673a0e2191821ce88128587f709936ad765 Mon Sep 17 00:00:00 2001
From: Jon Maloy <jmaloy@redhat.com>
Date: Thu, 18 Jul 2024 09:21:27 -0400
Subject: [PATCH 6/6] hw/virtio/virtio-crypto: Protect from DMA re-entrancy
bugs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Jon Maloy <jmaloy@redhat.com>
RH-MergeRequest: 380: QEMU: virtio: DMA reentrancy issue leads to double free vulnerability
RH-Jira: RHEL-32276
RH-Acked-by: Gerd Hoffmann <None>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Commit: [6/6] 975ac4640fd8e7cbf3820757787ee7b1270173be (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2)
JIRA: https://issues.redhat.com/browse/RHEL-32276
CVE: CVE-2024-3446
Upstream: Merged
commit f4729ec39ad97a42ceaa7b5697f84f440ea6e5dc
Author: Philippe Mathieu-Daudé <philmd@linaro.org>
Date: Thu Apr 4 20:56:41 2024 +0200
hw/virtio/virtio-crypto: Protect from DMA re-entrancy bugs
Replace qemu_bh_new_guarded() by virtio_bh_new_guarded()
so the bus and device use the same guard. Otherwise the
DMA-reentrancy protection can be bypassed.
Fixes: CVE-2024-3446
Cc: qemu-stable@nongnu.org
Suggested-by: Alexander Bulekov <alxndr@bu.edu>
Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20240409105537.18308-5-philmd@linaro.org>
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
hw/virtio/virtio-crypto.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
index 1be7bb543c..1741d4aba1 100644
--- a/hw/virtio/virtio-crypto.c
+++ b/hw/virtio/virtio-crypto.c
@@ -817,8 +817,8 @@ static void virtio_crypto_device_realize(DeviceState *dev, Error **errp)
vcrypto->vqs[i].dataq =
virtio_add_queue(vdev, 1024, virtio_crypto_handle_dataq_bh);
vcrypto->vqs[i].dataq_bh =
- qemu_bh_new_guarded(virtio_crypto_dataq_bh, &vcrypto->vqs[i],
- &dev->mem_reentrancy_guard);
+ virtio_bh_new_guarded(dev, virtio_crypto_dataq_bh,
+ &vcrypto->vqs[i]);
vcrypto->vqs[i].vcrypto = vcrypto;
}
--
2.39.3

View File

@ -1,68 +0,0 @@
From 3cb587f460ec432f329fb83df034bbb7e79e17aa Mon Sep 17 00:00:00 2001
From: Jon Maloy <jmaloy@redhat.com>
Date: Wed, 5 Jun 2024 19:56:51 -0400
Subject: [PATCH 2/5] iotests/244: Don't store data-file with protocol in image
RH-Author: Jon Maloy <jmaloy@redhat.com>
RH-MergeRequest: 5: EMBARGOED CVE-2024-4467 for rhel-8.10.z (PRDSC)
RH-Jira: RHEL-35616
RH-CVE: CVE-2024-4467
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
RH-Commit: [2/5] a422cfdba938e1bd857008ccbbddc695011ae0ff
commit 92e00dab8be1570b13172353d77d2af44cb4e22b
Author: Kevin Wolf <kwolf@redhat.com>
Date: Thu Apr 25 14:49:40 2024 +0200
iotests/244: Don't store data-file with protocol in image
We want to disable filename parsing for data files because it's too easy
to abuse in malicious image files. Make the test ready for the change by
passing the data file explicitly in command line options.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
Upstream: N/A, embargoed
Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
tests/qemu-iotests/244 | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244
index 3e61fa25bb..bb9cc6512f 100755
--- a/tests/qemu-iotests/244
+++ b/tests/qemu-iotests/244
@@ -215,9 +215,22 @@ $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$TEST_IMG"
$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG"
# blkdebug doesn't support copy offloading, so this tests the error path
-$QEMU_IMG amend -f $IMGFMT -o "data_file=blkdebug::$TEST_IMG.data" "$TEST_IMG"
-$QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$TEST_IMG"
-$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG"
+test_img_with_blkdebug="json:{
+ 'driver': 'qcow2',
+ 'file': {
+ 'driver': 'file',
+ 'filename': '$TEST_IMG'
+ },
+ 'data-file': {
+ 'driver': 'blkdebug',
+ 'image': {
+ 'driver': 'file',
+ 'filename': '$TEST_IMG.data'
+ }
+ }
+}"
+$QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$test_img_with_blkdebug"
+$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$test_img_with_blkdebug"
echo
echo "=== Flushing should flush the data file ==="
--
2.39.3

View File

@ -1,71 +0,0 @@
From 59a84673079f9763e9507733e308442397aba703 Mon Sep 17 00:00:00 2001
From: Jon Maloy <jmaloy@redhat.com>
Date: Wed, 5 Jun 2024 19:56:51 -0400
Subject: [PATCH 3/5] iotests/270: Don't store data-file with json: prefix in
image
RH-Author: Jon Maloy <jmaloy@redhat.com>
RH-MergeRequest: 5: EMBARGOED CVE-2024-4467 for rhel-8.10.z (PRDSC)
RH-Jira: RHEL-35616
RH-CVE: CVE-2024-4467
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
RH-Commit: [3/5] ac08690fd3ea3af6e24b2f6a8beedcfe469917a8
commit 705bcc2819ce8e0f8b9d660a93bc48de26413aec
Author: Kevin Wolf <kwolf@redhat.com>
Date: Thu Apr 25 14:49:40 2024 +0200
iotests/270: Don't store data-file with json: prefix in image
We want to disable filename parsing for data files because it's too easy
to abuse in malicious image files. Make the test ready for the change by
passing the data file explicitly in command line options.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
Upstream: N/A, embargoed
Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
tests/qemu-iotests/270 | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/tests/qemu-iotests/270 b/tests/qemu-iotests/270
index 74352342db..c37b674aa2 100755
--- a/tests/qemu-iotests/270
+++ b/tests/qemu-iotests/270
@@ -60,8 +60,16 @@ _make_test_img -o cluster_size=2M,data_file="$TEST_IMG.orig" \
# "write" 2G of data without using any space.
# (qemu-img create does not like it, though, because null-co does not
# support image creation.)
-$QEMU_IMG amend -o data_file="json:{'driver':'null-co',,'size':'4294967296'}" \
- "$TEST_IMG"
+test_img_with_null_data="json:{
+ 'driver': '$IMGFMT',
+ 'file': {
+ 'filename': '$TEST_IMG'
+ },
+ 'data-file': {
+ 'driver': 'null-co',
+ 'size':'4294967296'
+ }
+}"
# This gives us a range of:
# 2^31 - 512 + 768 - 1 = 2^31 + 255 > 2^31
@@ -74,7 +82,7 @@ $QEMU_IMG amend -o data_file="json:{'driver':'null-co',,'size':'4294967296'}" \
# on L2 boundaries, we need large L2 tables; hence the cluster size of
# 2 MB. (Anything from 256 kB should work, though, because then one L2
# table covers 8 GB.)
-$QEMU_IO -c "write 768 $((2 ** 31 - 512))" "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write 768 $((2 ** 31 - 512))" "$test_img_with_null_data" | _filter_qemu_io
_check_test_img
--
2.39.3

View File

@ -1,82 +0,0 @@
From 9b5e69ce5f4ba9541e55d801af16ece4969379e9 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Fri, 9 Feb 2024 18:31:03 +0100
Subject: [PATCH 4/4] iotests: Make 144 deterministic again
RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
RH-MergeRequest: 352: monitor: only run coroutine commands in qemu_aio_context
RH-Jira: RHEL-7353
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
RH-Acked-by: Hanna Czenczek <hreitz@redhat.com>
RH-Commit: [4/4] 4974a32174abefb509b7c46671a364b4b991449e
Since commit effd60c8 changed how QMP commands are processed, the order
of the block-commit return value and job events in iotests 144 wasn't
fixed and more and caused the test to fail intermittently.
Change the test to cache events first and then print them in a
predefined order.
Waiting three times for JOB_STATUS_CHANGE is a bit uglier than just
waiting for the JOB_STATUS_CHANGE that has "status": "ready", but the
tooling we have doesn't seem to allow the latter easily.
Fixes: effd60c878176bcaf97fa7ce2b12d04bb8ead6f7
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2126
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 20240209173103.239994-1-kwolf@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit cc29c12ec629ba68a4a6cb7d165c94cc8502815a)
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
tests/qemu-iotests/144 | 12 +++++++++++-
tests/qemu-iotests/144.out | 2 +-
2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/tests/qemu-iotests/144 b/tests/qemu-iotests/144
index 60e9ddd75f..8c50d6487e 100755
--- a/tests/qemu-iotests/144
+++ b/tests/qemu-iotests/144
@@ -83,12 +83,22 @@ echo
echo === Performing block-commit on active layer ===
echo
+capture_events="BLOCK_JOB_READY JOB_STATUS_CHANGE"
+
# Block commit on active layer, push the new overlay into base
_send_qemu_cmd $h "{ 'execute': 'block-commit',
'arguments': {
'device': 'virtio0'
}
- }" "READY"
+ }" "return"
+
+_wait_event $h "JOB_STATUS_CHANGE"
+_wait_event $h "JOB_STATUS_CHANGE"
+_wait_event $h "JOB_STATUS_CHANGE"
+
+_wait_event $h "BLOCK_JOB_READY"
+
+capture_events=
_send_qemu_cmd $h "{ 'execute': 'block-job-complete',
'arguments': {
diff --git a/tests/qemu-iotests/144.out b/tests/qemu-iotests/144.out
index b3b4812015..2245ddfa10 100644
--- a/tests/qemu-iotests/144.out
+++ b/tests/qemu-iotests/144.out
@@ -25,9 +25,9 @@ Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off co
'device': 'virtio0'
}
}
+{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "virtio0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "virtio0"}}
-{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "virtio0"}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "virtio0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
{ 'execute': 'block-job-complete',
--
2.39.3

View File

@ -1,49 +0,0 @@
From f164083416a9d09712b8cb8c654dd3b8988e6c5c Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi <stefanha@redhat.com>
Date: Thu, 18 Jan 2024 09:48:21 -0500
Subject: [PATCH 1/4] iotests: add filter_qmp_generated_node_ids()
RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
RH-MergeRequest: 352: monitor: only run coroutine commands in qemu_aio_context
RH-Jira: RHEL-7353
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
RH-Acked-by: Hanna Czenczek <hreitz@redhat.com>
RH-Commit: [1/4] cc276c8ef9e140203afc19fcd8b5b8e20577054d
Add a filter function for QMP responses that contain QEMU's
automatically generated node ids. The ids change between runs and must
be masked in the reference output.
The next commit will use this new function.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-ID: <20240118144823.1497953-2-stefanha@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit da62b507a20510d819bcfbe8f5e573409b954006)
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
tests/qemu-iotests/iotests.py | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index 2ef493755c..fd41f93421 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -521,6 +521,13 @@ def _filter(_key, value):
def filter_generated_node_ids(msg):
return re.sub("#block[0-9]+", "NODE_NAME", msg)
+def filter_qmp_generated_node_ids(qmsg):
+ def _filter(_key, value):
+ if is_str(value):
+ return filter_generated_node_ids(value)
+ return value
+ return filter_qmp(qmsg, _filter)
+
def filter_img_info(output, filename):
lines = []
for line in output.split('\n'):
--
2.39.3

View File

@ -1,601 +0,0 @@
From 968c8ff7ea7d43bf29d8e5f6e9e17f84168c22c4 Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi <stefanha@redhat.com>
Date: Thu, 18 Jan 2024 09:48:22 -0500
Subject: [PATCH 2/4] iotests: port 141 to Python for reliable QMP testing
RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
RH-MergeRequest: 352: monitor: only run coroutine commands in qemu_aio_context
RH-Jira: RHEL-7353
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
RH-Acked-by: Hanna Czenczek <hreitz@redhat.com>
RH-Commit: [2/4] ff0899262544b1b61b4c7de2eb798b664fe5202e
The common.qemu bash functions allow tests to interact with the QMP
monitor of a QEMU process. I spent two days trying to update 141 when
the order of the test output changed, but found it would still fail
occassionally because printf() and QMP events race with synchronous QMP
communication.
I gave up and ported 141 to the existing Python API for QMP tests. The
Python API is less affected by the order in which QEMU prints output
because it does not print all QMP traffic by default.
The next commit changes the order in which QMP messages are received.
Make 141 reliable first.
Cc: Hanna Czenczek <hreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-ID: <20240118144823.1497953-3-stefanha@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 9ee2dd4c22a3639c5462b3fc20df60c005c3de64)
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Conflicts:
tests/qemu-iotests/141
tests/qemu-iotests/141.out
This commit replaces these files anyway, so apply our changes instead
of dragging in more dependencies to resolve context conflicts.
---
tests/qemu-iotests/141 | 307 ++++++++++++++++---------------------
tests/qemu-iotests/141.out | 204 ++++++------------------
2 files changed, 178 insertions(+), 333 deletions(-)
diff --git a/tests/qemu-iotests/141 b/tests/qemu-iotests/141
index 115cc1691e..a7d3985a02 100755
--- a/tests/qemu-iotests/141
+++ b/tests/qemu-iotests/141
@@ -1,9 +1,12 @@
-#!/usr/bin/env bash
+#!/usr/bin/env python3
# group: rw auto quick
#
# Test case for ejecting BDSs with block jobs still running on them
#
-# Copyright (C) 2016 Red Hat, Inc.
+# Originally written in bash by Hanna Czenczek, ported to Python by Stefan
+# Hajnoczi.
+#
+# Copyright Red Hat
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -19,177 +22,129 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-# creator
-owner=mreitz@redhat.com
-
-seq="$(basename $0)"
-echo "QA output created by $seq"
-
-status=1 # failure is the default!
-
-_cleanup()
-{
- _cleanup_qemu
- _cleanup_test_img
- for img in "$TEST_DIR"/{b,m,o}.$IMGFMT; do
- _rm_test_img "$img"
- done
-}
-trap "_cleanup; exit \$status" 0 1 2 3 15
-
-# get standard environment, filters and checks
-. ./common.rc
-. ./common.filter
-. ./common.qemu
-
-# Needs backing file and backing format support
-_supported_fmt qcow2 qed
-_supported_proto file
-_supported_os Linux
-
-
-test_blockjob()
-{
- _send_qemu_cmd $QEMU_HANDLE \
- "{'execute': 'blockdev-add',
- 'arguments': {
- 'node-name': 'drv0',
- 'driver': '$IMGFMT',
- 'file': {
- 'driver': 'file',
- 'filename': '$TEST_IMG'
- }}}" \
- 'return'
-
- # If "$2" is an event, we may or may not see it before the
- # {"return": {}}. Therefore, filter the {"return": {}} out both
- # here and in the next command. (Naturally, if we do not see it
- # here, we will see it before the next command can be executed,
- # so it will appear in the next _send_qemu_cmd's output.)
- _send_qemu_cmd $QEMU_HANDLE \
- "$1" \
- "$2" \
- | _filter_img_create | _filter_qmp_empty_return
-
- # We want this to return an error because the block job is still running
- _send_qemu_cmd $QEMU_HANDLE \
- "{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}" \
- 'error' | _filter_generated_node_ids | _filter_qmp_empty_return
-
- _send_qemu_cmd $QEMU_HANDLE \
- "{'execute': 'block-job-cancel',
- 'arguments': {'device': 'job0'}}" \
- "$3"
-
- _send_qemu_cmd $QEMU_HANDLE \
- "{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}" \
- 'return'
-}
-
-
-TEST_IMG="$TEST_DIR/b.$IMGFMT" _make_test_img 1M
-TEST_IMG="$TEST_DIR/m.$IMGFMT" _make_test_img -b "$TEST_DIR/b.$IMGFMT" -F $IMGFMT 1M
-_make_test_img -b "$TEST_DIR/m.$IMGFMT" 1M -F $IMGFMT
-
-_launch_qemu -nodefaults
-
-_send_qemu_cmd $QEMU_HANDLE \
- "{'execute': 'qmp_capabilities'}" \
- 'return'
-
-echo
-echo '=== Testing drive-backup ==='
-echo
-
-# drive-backup will not send BLOCK_JOB_READY by itself, and cancelling the job
-# will consequently result in BLOCK_JOB_CANCELLED being emitted.
-
-test_blockjob \
- "{'execute': 'drive-backup',
- 'arguments': {'job-id': 'job0',
- 'device': 'drv0',
- 'target': '$TEST_DIR/o.$IMGFMT',
- 'format': '$IMGFMT',
- 'sync': 'none'}}" \
- 'return' \
- '"status": "null"'
-
-echo
-echo '=== Testing drive-mirror ==='
-echo
-
-# drive-mirror will send BLOCK_JOB_READY basically immediately, and cancelling
-# the job will consequently result in BLOCK_JOB_COMPLETED being emitted.
-
-test_blockjob \
- "{'execute': 'drive-mirror',
- 'arguments': {'job-id': 'job0',
- 'device': 'drv0',
- 'target': '$TEST_DIR/o.$IMGFMT',
- 'format': '$IMGFMT',
- 'sync': 'none'}}" \
- 'BLOCK_JOB_READY' \
- '"status": "null"'
-
-echo
-echo '=== Testing active block-commit ==='
-echo
-
-# An active block-commit will send BLOCK_JOB_READY basically immediately, and
-# cancelling the job will consequently result in BLOCK_JOB_COMPLETED being
-# emitted.
-
-test_blockjob \
- "{'execute': 'block-commit',
- 'arguments': {'job-id': 'job0', 'device': 'drv0'}}" \
- 'BLOCK_JOB_READY' \
- '"status": "null"'
-
-echo
-echo '=== Testing non-active block-commit ==='
-echo
-
-# Give block-commit something to work on, otherwise it would be done
-# immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would work just
-# fine without the block job still running.
-
-$QEMU_IO -c 'write 0 1M' "$TEST_DIR/m.$IMGFMT" | _filter_qemu_io
-
-test_blockjob \
- "{'execute': 'block-commit',
- 'arguments': {'job-id': 'job0',
- 'device': 'drv0',
- 'top': '$TEST_DIR/m.$IMGFMT',
- 'speed': 1}}" \
- 'return' \
- '"status": "null"'
-
-echo
-echo '=== Testing block-stream ==='
-echo
-
-# Give block-stream something to work on, otherwise it would be done
-# immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would work just
-# fine without the block job still running.
-
-$QEMU_IO -c 'write 0 1M' "$TEST_DIR/b.$IMGFMT" | _filter_qemu_io
-
-# With some data to stream (and @speed set to 1), block-stream will not complete
-# until we send the block-job-cancel command.
-
-test_blockjob \
- "{'execute': 'block-stream',
- 'arguments': {'job-id': 'job0',
- 'device': 'drv0',
- 'speed': 1}}" \
- 'return' \
- '"status": "null"'
-
-_cleanup_qemu
-
-# success, all done
-echo "*** done"
-rm -f $seq.full
-status=0
+import iotests
+
+# Common filters to mask values that vary in the test output
+QMP_FILTERS = [iotests.filter_qmp_testfiles, \
+ iotests.filter_qmp_imgfmt]
+
+
+class TestCase:
+ def __init__(self, name, vm, image_path, cancel_event):
+ self.name = name
+ self.vm = vm
+ self.image_path = image_path
+ self.cancel_event = cancel_event
+
+ def __enter__(self):
+ iotests.log(f'=== Testing {self.name} ===')
+ self.vm.qmp_log('blockdev-add', \
+ node_name='drv0', \
+ driver=iotests.imgfmt, \
+ file={'driver': 'file', 'filename': self.image_path}, \
+ filters=QMP_FILTERS)
+
+ def __exit__(self, *exc_details):
+ # This is expected to fail because the job still exists
+ self.vm.qmp_log('blockdev-del', node_name='drv0', \
+ filters=[iotests.filter_qmp_generated_node_ids])
+
+ self.vm.qmp_log('block-job-cancel', device='job0')
+ event = self.vm.event_wait(self.cancel_event)
+ iotests.log(event, filters=[iotests.filter_qmp_event])
+
+ # This time it succeeds
+ self.vm.qmp_log('blockdev-del', node_name='drv0')
+
+ # Separate test cases in output
+ iotests.log('')
+
+
+def main() -> None:
+ with iotests.FilePath('bottom', 'middle', 'top', 'target') as \
+ (bottom_path, middle_path, top_path, target_path), \
+ iotests.VM() as vm:
+
+ iotests.log('Creating bottom <- middle <- top backing file chain...')
+ IMAGE_SIZE='1M'
+ iotests.qemu_img_create('-f', iotests.imgfmt, bottom_path, IMAGE_SIZE)
+ iotests.qemu_img_create('-f', iotests.imgfmt, \
+ '-F', iotests.imgfmt, \
+ '-b', bottom_path, \
+ middle_path, \
+ IMAGE_SIZE)
+ iotests.qemu_img_create('-f', iotests.imgfmt, \
+ '-F', iotests.imgfmt, \
+ '-b', middle_path, \
+ top_path, \
+ IMAGE_SIZE)
+
+ iotests.log('Starting VM...')
+ vm.add_args('-nodefaults')
+ vm.launch()
+
+ # drive-backup will not send BLOCK_JOB_READY by itself, and cancelling
+ # the job will consequently result in BLOCK_JOB_CANCELLED being
+ # emitted.
+ with TestCase('drive-backup', vm, top_path, 'BLOCK_JOB_CANCELLED'):
+ vm.qmp_log('drive-backup', \
+ job_id='job0', \
+ device='drv0', \
+ target=target_path, \
+ format=iotests.imgfmt, \
+ sync='none', \
+ filters=QMP_FILTERS)
+
+ # drive-mirror will send BLOCK_JOB_READY basically immediately, and
+ # cancelling the job will consequently result in BLOCK_JOB_COMPLETED
+ # being emitted.
+ with TestCase('drive-mirror', vm, top_path, 'BLOCK_JOB_COMPLETED'):
+ vm.qmp_log('drive-mirror', \
+ job_id='job0', \
+ device='drv0', \
+ target=target_path, \
+ format=iotests.imgfmt, \
+ sync='none', \
+ filters=QMP_FILTERS)
+ event = vm.event_wait('BLOCK_JOB_READY')
+ assert event is not None # silence mypy
+ iotests.log(event, filters=[iotests.filter_qmp_event])
+
+ # An active block-commit will send BLOCK_JOB_READY basically
+ # immediately, and cancelling the job will consequently result in
+ # BLOCK_JOB_COMPLETED being emitted.
+ with TestCase('active block-commit', vm, top_path, \
+ 'BLOCK_JOB_COMPLETED'):
+ vm.qmp_log('block-commit', \
+ job_id='job0', \
+ device='drv0')
+ event = vm.event_wait('BLOCK_JOB_READY')
+ assert event is not None # silence mypy
+ iotests.log(event, filters=[iotests.filter_qmp_event])
+
+ # Give block-commit something to work on, otherwise it would be done
+ # immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would
+ # work just fine without the block job still running.
+ iotests.qemu_io(middle_path, '-c', f'write 0 {IMAGE_SIZE}')
+ with TestCase('non-active block-commit', vm, top_path, \
+ 'BLOCK_JOB_CANCELLED'):
+ vm.qmp_log('block-commit', \
+ job_id='job0', \
+ device='drv0', \
+ top=middle_path, \
+ speed=1, \
+ filters=[iotests.filter_qmp_testfiles])
+
+ # Give block-stream something to work on, otherwise it would be done
+ # immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would
+ # work just fine without the block job still running.
+ iotests.qemu_io(bottom_path, '-c', f'write 0 {IMAGE_SIZE}')
+ with TestCase('block-stream', vm, top_path, 'BLOCK_JOB_CANCELLED'):
+ vm.qmp_log('block-stream', \
+ job_id='job0', \
+ device='drv0', \
+ speed=1)
+
+if __name__ == '__main__':
+ iotests.script_main(main, supported_fmts=['qcow2', 'qed'],
+ supported_protocols=['file'])
diff --git a/tests/qemu-iotests/141.out b/tests/qemu-iotests/141.out
index c4c15fb275..91b7ba50af 100644
--- a/tests/qemu-iotests/141.out
+++ b/tests/qemu-iotests/141.out
@@ -1,179 +1,69 @@
-QA output created by 141
-Formatting 'TEST_DIR/b.IMGFMT', fmt=IMGFMT size=1048576
-Formatting 'TEST_DIR/m.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/b.IMGFMT backing_fmt=IMGFMT
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/m.IMGFMT backing_fmt=IMGFMT
-{'execute': 'qmp_capabilities'}
-{"return": {}}
-
+Creating bottom <- middle <- top backing file chain...
+Starting VM...
=== Testing drive-backup ===
-
-{'execute': 'blockdev-add',
- 'arguments': {
- 'node-name': 'drv0',
- 'driver': 'IMGFMT',
- 'file': {
- 'driver': 'file',
- 'filename': 'TEST_DIR/t.IMGFMT'
- }}}
-{"return": {}}
-{'execute': 'drive-backup',
-'arguments': {'job-id': 'job0',
-'device': 'drv0',
-'target': 'TEST_DIR/o.IMGFMT',
-'format': 'IMGFMT',
-'sync': 'none'}}
-Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "paused", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
-{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}}
+{"return": {}}
+{"execute": "drive-backup", "arguments": {"device": "drv0", "format": "IMGFMT", "job-id": "job0", "sync": "none", "target": "TEST_DIR/PID-target"}}
+{"return": {}}
+{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: node is used as backing hd of 'NODE_NAME'"}}
-{'execute': 'block-job-cancel',
- 'arguments': {'device': 'job0'}}
+{"execute": "block-job-cancel", "arguments": {"device": "job0"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 0, "speed": 0, "type": "backup"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
-{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}
+{"data": {"device": "job0", "len": 1048576, "offset": 0, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
{"return": {}}
=== Testing drive-mirror ===
-
-{'execute': 'blockdev-add',
- 'arguments': {
- 'node-name': 'drv0',
- 'driver': 'IMGFMT',
- 'file': {
- 'driver': 'file',
- 'filename': 'TEST_DIR/t.IMGFMT'
- }}}
-{"return": {}}
-{'execute': 'drive-mirror',
-'arguments': {'job-id': 'job0',
-'device': 'drv0',
-'target': 'TEST_DIR/o.IMGFMT',
-'format': 'IMGFMT',
-'sync': 'none'}}
-Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
-{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}}
+{"return": {}}
+{"execute": "drive-mirror", "arguments": {"device": "drv0", "format": "IMGFMT", "job-id": "job0", "sync": "none", "target": "TEST_DIR/PID-target"}}
+{"return": {}}
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: mirror"}}
-{'execute': 'block-job-cancel',
- 'arguments': {'device': 'job0'}}
+{"execute": "block-job-cancel", "arguments": {"device": "job0"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
-{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
{"return": {}}
=== Testing active block-commit ===
-
-{'execute': 'blockdev-add',
- 'arguments': {
- 'node-name': 'drv0',
- 'driver': 'IMGFMT',
- 'file': {
- 'driver': 'file',
- 'filename': 'TEST_DIR/t.IMGFMT'
- }}}
-{"return": {}}
-{'execute': 'block-commit',
-'arguments': {'job-id': 'job0', 'device': 'drv0'}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
-{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}}
+{"return": {}}
+{"execute": "block-commit", "arguments": {"device": "drv0", "job-id": "job0"}}
+{"return": {}}
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}}
-{'execute': 'block-job-cancel',
- 'arguments': {'device': 'job0'}}
+{"execute": "block-job-cancel", "arguments": {"device": "job0"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "waiting", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "pending", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
-{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}
+{"data": {"device": "job0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
{"return": {}}
=== Testing non-active block-commit ===
-
-wrote 1048576/1048576 bytes at offset 0
-1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-{'execute': 'blockdev-add',
- 'arguments': {
- 'node-name': 'drv0',
- 'driver': 'IMGFMT',
- 'file': {
- 'driver': 'file',
- 'filename': 'TEST_DIR/t.IMGFMT'
- }}}
-{"return": {}}
-{'execute': 'block-commit',
-'arguments': {'job-id': 'job0',
-'device': 'drv0',
-'top': 'TEST_DIR/m.IMGFMT',
-'speed': 1}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
-{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}
-{"error": {"class": "GenericError", "desc": "Node drv0 is in use"}}
-{'execute': 'block-job-cancel',
- 'arguments': {'device': 'job0'}}
-{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "commit"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
-{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}}
+{"return": {}}
+{"execute": "block-commit", "arguments": {"device": "drv0", "job-id": "job0", "speed": 1, "top": "TEST_DIR/PID-middle"}}
+{"return": {}}
+{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
+{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}}
+{"execute": "block-job-cancel", "arguments": {"device": "job0"}}
+{"return": {}}
+{"data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "commit"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
{"return": {}}
=== Testing block-stream ===
-
-wrote 1048576/1048576 bytes at offset 0
-1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-{'execute': 'blockdev-add',
- 'arguments': {
- 'node-name': 'drv0',
- 'driver': 'IMGFMT',
- 'file': {
- 'driver': 'file',
- 'filename': 'TEST_DIR/t.IMGFMT'
- }}}
-{"return": {}}
-{'execute': 'block-stream',
-'arguments': {'job-id': 'job0',
-'device': 'drv0',
-'speed': 1}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "job0"}}
-{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}
+{"execute": "blockdev-add", "arguments": {"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_DIR/PID-top"}, "node-name": "drv0"}}
+{"return": {}}
+{"execute": "block-stream", "arguments": {"device": "drv0", "job-id": "job0", "speed": 1}}
+{"return": {}}
+{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: stream"}}
-{'execute': 'block-job-cancel',
- 'arguments': {'device': 'job0'}}
+{"execute": "block-job-cancel", "arguments": {"device": "job0"}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "aborting", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "stream"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "concluded", "id": "job0"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "null", "id": "job0"}}
-{'execute': 'blockdev-del',
- 'arguments': {'node-name': 'drv0'}}
+{"data": {"device": "job0", "len": 1048576, "offset": 524288, "speed": 1, "type": "stream"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}}
+{"execute": "blockdev-del", "arguments": {"node-name": "drv0"}}
{"return": {}}
-*** done
+
--
2.39.3

View File

@ -1,277 +0,0 @@
From a0b12780f3cb97abad0a2c54d185c298d3f589e7 Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Fri, 17 May 2024 21:50:15 -0500
Subject: [PATCH 2/3] iotests: test NBD+TLS+iothread
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Eric Blake <eblake@redhat.com>
RH-MergeRequest: 398: nbd/server: CVE-2024-7409: Avoid use-after-free when closing server
RH-Jira: RHEL-52611
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
RH-Commit: [2/3] f522ff5156086a83a7327c379dd3ccd8b583a421 (ebblake/qemu-kvm)
Prevent regressions when using NBD with TLS in the presence of
iothreads, adding coverage the fix to qio channels made in the
previous patch.
The shell function pick_unused_port() was copied from
nbdkit.git/tests/functions.sh.in, where it had all authors from Red
Hat, agreeing to the resulting relicensing from 2-clause BSD to GPLv2.
CC: qemu-stable@nongnu.org
CC: "Richard W.M. Jones" <rjones@redhat.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-ID: <20240531180639.1392905-6-eblake@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit a73c99378022ebb785481e84cfe1e81097546268)
Jira: https://issues.redhat.com/browse/RHEL-52611
Conflicts:
tests/qemu-iotests/tests/nbd-tls-iothread{,.out} - drop unknown
"tls-hostname" parameter
Signed-off-by: Eric Blake <eblake@redhat.com>
---
tests/qemu-iotests/tests/nbd-tls-iothread | 167 ++++++++++++++++++
tests/qemu-iotests/tests/nbd-tls-iothread.out | 53 ++++++
2 files changed, 220 insertions(+)
create mode 100755 tests/qemu-iotests/tests/nbd-tls-iothread
create mode 100644 tests/qemu-iotests/tests/nbd-tls-iothread.out
diff --git a/tests/qemu-iotests/tests/nbd-tls-iothread b/tests/qemu-iotests/tests/nbd-tls-iothread
new file mode 100755
index 0000000000..9e747e2639
--- /dev/null
+++ b/tests/qemu-iotests/tests/nbd-tls-iothread
@@ -0,0 +1,167 @@
+#!/usr/bin/env bash
+# group: rw quick
+#
+# Test of NBD+TLS+iothread
+#
+# Copyright (C) 2024 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=eblake@redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_qemu
+ _cleanup_test_img
+ rm -f "$dst_image"
+ tls_x509_cleanup
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+cd ..
+. ./common.rc
+. ./common.filter
+. ./common.qemu
+. ./common.tls
+. ./common.nbd
+
+_supported_fmt qcow2 # Hardcoded to qcow2 command line and QMP below
+_supported_proto file
+
+# pick_unused_port
+#
+# Picks and returns an "unused" port, setting the global variable
+# $port.
+#
+# This is inherently racy, but we need it because qemu does not currently
+# permit NBD+TLS over a Unix domain socket
+pick_unused_port ()
+{
+ if ! (ss --version) >/dev/null 2>&1; then
+ _notrun "ss utility required, skipped this test"
+ fi
+
+ # Start at a random port to make it less likely that two parallel
+ # tests will conflict.
+ port=$(( 50000 + (RANDOM%15000) ))
+ while ss -ltn | grep -sqE ":$port\b"; do
+ ((port++))
+ if [ $port -eq 65000 ]; then port=50000; fi
+ done
+ echo picked unused port
+}
+
+tls_x509_init
+
+size=1G
+DST_IMG="$TEST_DIR/dst.qcow2"
+
+echo
+echo "== preparing TLS creds and spare port =="
+
+pick_unused_port
+tls_x509_create_root_ca "ca1"
+tls_x509_create_server "ca1" "server1"
+tls_x509_create_client "ca1" "client1"
+tls_obj_base=tls-creds-x509,id=tls0,verify-peer=true,dir="${tls_dir}"
+
+echo
+echo "== preparing image =="
+
+_make_test_img $size
+$QEMU_IMG create -f qcow2 "$DST_IMG" $size | _filter_img_create
+
+echo
+echo === Starting Src QEMU ===
+echo
+
+_launch_qemu -machine q35 \
+ -object iothread,id=iothread0 \
+ -object "${tls_obj_base}"/client1,endpoint=client \
+ -device '{"driver":"pcie-root-port", "id":"root0", "multifunction":true,
+ "bus":"pcie.0"}' \
+ -device '{"driver":"virtio-scsi-pci", "id":"virtio_scsi_pci0",
+ "bus":"root0", "iothread":"iothread0"}' \
+ -device '{"driver":"scsi-hd", "id":"image1", "drive":"drive_image1",
+ "bus":"virtio_scsi_pci0.0"}' \
+ -blockdev '{"driver":"file", "cache":{"direct":true, "no-flush":false},
+ "filename":"'"$TEST_IMG"'", "node-name":"drive_sys1"}' \
+ -blockdev '{"driver":"qcow2", "node-name":"drive_image1",
+ "file":"drive_sys1"}'
+h1=$QEMU_HANDLE
+_send_qemu_cmd $h1 '{"execute": "qmp_capabilities"}' 'return'
+
+echo
+echo === Starting Dst VM2 ===
+echo
+
+_launch_qemu -machine q35 \
+ -object iothread,id=iothread0 \
+ -object "${tls_obj_base}"/server1,endpoint=server \
+ -device '{"driver":"pcie-root-port", "id":"root0", "multifunction":true,
+ "bus":"pcie.0"}' \
+ -device '{"driver":"virtio-scsi-pci", "id":"virtio_scsi_pci0",
+ "bus":"root0", "iothread":"iothread0"}' \
+ -device '{"driver":"scsi-hd", "id":"image1", "drive":"drive_image1",
+ "bus":"virtio_scsi_pci0.0"}' \
+ -blockdev '{"driver":"file", "cache":{"direct":true, "no-flush":false},
+ "filename":"'"$DST_IMG"'", "node-name":"drive_sys1"}' \
+ -blockdev '{"driver":"qcow2", "node-name":"drive_image1",
+ "file":"drive_sys1"}' \
+ -incoming defer
+h2=$QEMU_HANDLE
+_send_qemu_cmd $h2 '{"execute": "qmp_capabilities"}' 'return'
+
+echo
+echo === Dst VM: Enable NBD server for incoming storage migration ===
+echo
+
+_send_qemu_cmd $h2 '{"execute": "nbd-server-start", "arguments":
+ {"addr": {"type": "inet", "data": {"host": "127.0.0.1", "port": "'$port'"}},
+ "tls-creds": "tls0"}}' '{"return": {}}' | sed "s/\"$port\"/PORT/g"
+_send_qemu_cmd $h2 '{"execute": "block-export-add", "arguments":
+ {"node-name": "drive_image1", "type": "nbd", "writable": true,
+ "id": "drive_image1"}}' '{"return": {}}'
+
+echo
+echo === Src VM: Mirror to dst NBD for outgoing storage migration ===
+echo
+
+_send_qemu_cmd $h1 '{"execute": "blockdev-add", "arguments":
+ {"node-name": "mirror", "driver": "nbd",
+ "server": {"type": "inet", "host": "127.0.0.1", "port": "'$port'"},
+ "export": "drive_image1", "tls-creds": "tls0"}}' '{"return": {}}' | sed "s/\"$port\"/PORT/g"
+_send_qemu_cmd $h1 '{"execute": "blockdev-mirror", "arguments":
+ {"sync": "full", "device": "drive_image1", "target": "mirror",
+ "job-id": "drive_image1_53"}}' '{"return": {}}'
+_timed_wait_for $h1 '"ready"'
+
+echo
+echo === Cleaning up ===
+echo
+
+_send_qemu_cmd $h1 '{"execute":"quit"}' ''
+_send_qemu_cmd $h2 '{"execute":"quit"}' ''
+
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/tests/nbd-tls-iothread.out b/tests/qemu-iotests/tests/nbd-tls-iothread.out
new file mode 100644
index 0000000000..a3899fd2d7
--- /dev/null
+++ b/tests/qemu-iotests/tests/nbd-tls-iothread.out
@@ -0,0 +1,53 @@
+QA output created by nbd-tls-iothread
+
+== preparing TLS creds and spare port ==
+picked unused port
+Generating a self signed certificate...
+Generating a signed certificate...
+Generating a signed certificate...
+
+== preparing image ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+Formatting 'TEST_DIR/dst.IMGFMT', fmt=IMGFMT size=1073741824
+
+=== Starting Src QEMU ===
+
+{"execute": "qmp_capabilities"}
+{"return": {}}
+
+=== Starting Dst VM2 ===
+
+{"execute": "qmp_capabilities"}
+{"return": {}}
+
+=== Dst VM: Enable NBD server for incoming storage migration ===
+
+{"execute": "nbd-server-start", "arguments":
+ {"addr": {"type": "inet", "data": {"host": "127.0.0.1", "port": PORT}},
+ "tls-creds": "tls0"}}
+{"return": {}}
+{"execute": "block-export-add", "arguments":
+ {"node-name": "drive_image1", "type": "nbd", "writable": true,
+ "id": "drive_image1"}}
+{"return": {}}
+
+=== Src VM: Mirror to dst NBD for outgoing storage migration ===
+
+{"execute": "blockdev-add", "arguments":
+ {"node-name": "mirror", "driver": "nbd",
+ "server": {"type": "inet", "host": "127.0.0.1", "port": PORT},
+ "export": "drive_image1", "tls-creds": "tls0"}}
+{"return": {}}
+{"execute": "blockdev-mirror", "arguments":
+ {"sync": "full", "device": "drive_image1", "target": "mirror",
+ "job-id": "drive_image1_53"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "created", "id": "drive_image1_53"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "running", "id": "drive_image1_53"}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "JOB_STATUS_CHANGE", "data": {"status": "ready", "id": "drive_image1_53"}}
+
+=== Cleaning up ===
+
+{"execute":"quit"}
+{"execute":"quit"}
+*** done
--
2.39.3

View File

@ -1,101 +0,0 @@
From 676438ff8c42323c3e5d9e7eeeb1b3367999136c Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Thu, 22 Aug 2024 09:35:29 -0500
Subject: [PATCH 3/3] nbd/server: CVE-2024-7409: Avoid use-after-free when
closing server
RH-Author: Eric Blake <eblake@redhat.com>
RH-MergeRequest: 398: nbd/server: CVE-2024-7409: Avoid use-after-free when closing server
RH-Jira: RHEL-52611
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
RH-Commit: [3/3] 1ee35a40ded067a085bf6fcafa690b40976d7f2d (ebblake/qemu-kvm)
Commit 3e7ef738 plugged the use-after-free of the global nbd_server
object, but overlooked a use-after-free of nbd_server->listener.
Although this race is harder to hit, notice that our shutdown path
first drops the reference count of nbd_server->listener, then triggers
actions that can result in a pending client reaching the
nbd_blockdev_client_closed() callback, which in turn calls
qio_net_listener_set_client_func on a potentially stale object.
If we know we don't want any more clients to connect, and have already
told the listener socket to shut down, then we should not be trying to
update the listener socket's associated function.
Reproducer:
> #!/usr/bin/python3
>
> import os
> from threading import Thread
>
> def start_stop():
> while 1:
> os.system('virsh qemu-monitor-command VM \'{"execute": "nbd-server-start",
+"arguments":{"addr":{"type":"unix","data":{"path":"/tmp/nbd-sock"}}}}\'')
> os.system('virsh qemu-monitor-command VM \'{"execute": "nbd-server-stop"}\'')
>
> def nbd_list():
> while 1:
> os.system('/path/to/build/qemu-nbd -L -k /tmp/nbd-sock')
>
> def test():
> sst = Thread(target=start_stop)
> sst.start()
> nlt = Thread(target=nbd_list)
> nlt.start()
>
> sst.join()
> nlt.join()
>
> test()
Fixes: CVE-2024-7409
Fixes: 3e7ef738c8 ("nbd/server: CVE-2024-7409: Close stray clients at server-stop")
CC: qemu-stable@nongnu.org
Reported-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-ID: <20240822143617.800419-2-eblake@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 3874f5f73c441c52f1c699c848d463b0eda01e4c)
Jira: https://issues.redhat.com/browse/RHEL-52611
Signed-off-by: Eric Blake <eblake@redhat.com>
---
blockdev-nbd.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index 87839c180b..b5d55e2518 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -87,10 +87,13 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc,
static void nbd_update_server_watch(NBDServerData *s)
{
- if (!s->max_connections || s->connections < s->max_connections) {
- qio_net_listener_set_client_func(s->listener, nbd_accept, NULL, NULL);
- } else {
- qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL);
+ if (s->listener) {
+ if (!s->max_connections || s->connections < s->max_connections) {
+ qio_net_listener_set_client_func(s->listener, nbd_accept, NULL,
+ NULL);
+ } else {
+ qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL);
+ }
}
}
@@ -108,6 +111,7 @@ static void nbd_server_free(NBDServerData *server)
*/
qio_net_listener_disconnect(server->listener);
object_unref(OBJECT(server->listener));
+ server->listener = NULL;
QLIST_FOREACH_SAFE(conn, &server->conns, next, tmp) {
qio_channel_shutdown(QIO_CHANNEL(conn->cioc), QIO_CHANNEL_SHUTDOWN_BOTH,
NULL);
--
2.39.3

View File

@ -1,187 +0,0 @@
From adfddc25c82576458442f61efb913e44d83bcbd0 Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Tue, 6 Aug 2024 13:53:00 -0500
Subject: [PATCH 2/5] nbd/server: CVE-2024-7409: Cap default max-connections to
100
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Eric Blake <eblake@redhat.com>
RH-MergeRequest: 388: nbd/server: fix CVE-2024-7409 (qemu crash on nbd-server-stop) [rhel-8.10.z]
RH-Jira: RHEL-52611
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Richard W.M. Jones <rjones@redhat.com>
RH-Commit: [2/4] 1f5d88d5644c46cbb957778254a993930b9d86dc (ebblake/qemu-kvm)
Allowing an unlimited number of clients to any web service is a recipe
for a rudimentary denial of service attack: the client merely needs to
open lots of sockets without closing them, until qemu no longer has
any more fds available to allocate.
For qemu-nbd, we default to allowing only 1 connection unless more are
explicitly asked for (-e or --shared); this was historically picked as
a nice default (without an explicit -t, a non-persistent qemu-nbd goes
away after a client disconnects, without needing any additional
follow-up commands), and we are not going to change that interface now
(besides, someday we want to point people towards qemu-storage-daemon
instead of qemu-nbd).
But for qemu proper, and the newer qemu-storage-daemon, the QMP
nbd-server-start command has historically had a default of unlimited
number of connections, in part because unlike qemu-nbd it is
inherently persistent until nbd-server-stop. Allowing multiple client
sockets is particularly useful for clients that can take advantage of
MULTI_CONN (creating parallel sockets to increase throughput),
although known clients that do so (such as libnbd's nbdcopy) typically
use only 8 or 16 connections (the benefits of scaling diminish once
more sockets are competing for kernel attention). Picking a number
large enough for typical use cases, but not unlimited, makes it
slightly harder for a malicious client to perform a denial of service
merely by opening lots of connections withot progressing through the
handshake.
This change does not eliminate CVE-2024-7409 on its own, but reduces
the chance for fd exhaustion or unlimited memory usage as an attack
surface. On the other hand, by itself, it makes it more obvious that
with a finite limit, we have the problem of an unauthenticated client
holding 100 fds opened as a way to block out a legitimate client from
being able to connect; thus, later patches will further add timeouts
to reject clients that are not making progress.
This is an INTENTIONAL change in behavior, and will break any client
of nbd-server-start that was not passing an explicit max-connections
parameter, yet expects more than 100 simultaneous connections. We are
not aware of any such client (as stated above, most clients aware of
MULTI_CONN get by just fine on 8 or 16 connections, and probably cope
with later connections failing by relying on the earlier connections;
libvirt has not yet been passing max-connections, but generally
creates NBD servers with the intent for a single client for the sake
of live storage migration; meanwhile, the KubeSAN project anticipates
a large cluster sharing multiple clients [up to 8 per node, and up to
100 nodes in a cluster], but it currently uses qemu-nbd with an
explicit --shared=0 rather than qemu-storage-daemon with
nbd-server-start).
We considered using a deprecation period (declare that omitting
max-parameters is deprecated, and make it mandatory in 3 releases -
then we don't need to pick an arbitrary default); that has zero risk
of breaking any apps that accidentally depended on more than 100
connections, and where such breakage might not be noticed under unit
testing but only under the larger loads of production usage. But it
does not close the denial-of-service hole until far into the future,
and requires all apps to change to add the parameter even if 100 was
good enough. It also has a drawback that any app (like libvirt) that
is accidentally relying on an unlimited default should seriously
consider their own CVE now, at which point they are going to change to
pass explicit max-connections sooner than waiting for 3 qemu releases.
Finally, if our changed default breaks an app, that app can always
pass in an explicit max-parameters with a larger value.
It is also intentional that the HMP interface to nbd-server-start is
not changed to expose max-connections (any client needing to fine-tune
things should be using QMP).
Suggested-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-ID: <20240807174943.771624-12-eblake@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
[ericb: Expand commit message to summarize Dan's argument for why we
break corner-case back-compat behavior without a deprecation period]
Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit c8a76dbd90c2f48df89b75bef74917f90a59b623)
Conflicts:
qapi/block-export.json - context (no multi-conn, older format)
Jira: https://issues.redhat.com/browse/RHEL-52611
Signed-off-by: Eric Blake <eblake@redhat.com>
---
block/monitor/block-hmp-cmds.c | 3 ++-
blockdev-nbd.c | 8 ++++++++
include/block/nbd.h | 7 +++++++
qapi/block-export.json | 4 ++--
4 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c
index 2ac4aedfff..32a666b5dc 100644
--- a/block/monitor/block-hmp-cmds.c
+++ b/block/monitor/block-hmp-cmds.c
@@ -411,7 +411,8 @@ void hmp_nbd_server_start(Monitor *mon, const QDict *qdict)
goto exit;
}
- nbd_server_start(addr, NULL, NULL, 0, &local_err);
+ nbd_server_start(addr, NULL, NULL, NBD_DEFAULT_MAX_CONNECTIONS,
+ &local_err);
qapi_free_SocketAddress(addr);
if (local_err != NULL) {
goto exit;
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index b9e8dc78f3..4bd90bac16 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -171,6 +171,10 @@ void nbd_server_start(SocketAddress *addr, const char *tls_creds,
void nbd_server_start_options(NbdServerOptions *arg, Error **errp)
{
+ if (!arg->has_max_connections) {
+ arg->max_connections = NBD_DEFAULT_MAX_CONNECTIONS;
+ }
+
nbd_server_start(arg->addr, arg->tls_creds, arg->tls_authz,
arg->max_connections, errp);
}
@@ -183,6 +187,10 @@ void qmp_nbd_server_start(SocketAddressLegacy *addr,
{
SocketAddress *addr_flat = socket_address_flatten(addr);
+ if (!has_max_connections) {
+ max_connections = NBD_DEFAULT_MAX_CONNECTIONS;
+ }
+
nbd_server_start(addr_flat, tls_creds, tls_authz, max_connections, errp);
qapi_free_SocketAddress(addr_flat);
}
diff --git a/include/block/nbd.h b/include/block/nbd.h
index b71a297249..a31c34a8a6 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -33,6 +33,13 @@ extern const BlockExportDriver blk_exp_nbd;
*/
#define NBD_DEFAULT_HANDSHAKE_MAX_SECS 10
+/*
+ * NBD_DEFAULT_MAX_CONNECTIONS: Number of client sockets to allow at
+ * once; must be large enough to allow a MULTI_CONN-aware client like
+ * nbdcopy to create its typical number of 8-16 sockets.
+ */
+#define NBD_DEFAULT_MAX_CONNECTIONS 100
+
/* Handshake phase structs - this struct is passed on the wire */
struct NBDOption {
diff --git a/qapi/block-export.json b/qapi/block-export.json
index c1b92ce1c1..181d7238fe 100644
--- a/qapi/block-export.json
+++ b/qapi/block-export.json
@@ -21,7 +21,7 @@
# recreated on the fly while the NBD server is active.
# If missing, it will default to denying access (since 4.0).
# @max-connections: The maximum number of connections to allow at the same
-# time, 0 for unlimited. (since 5.2; default: 0)
+# time, 0 for unlimited. (since 5.2; default: 100)
#
# Since: 4.2
##
@@ -50,7 +50,7 @@
# recreated on the fly while the NBD server is active.
# If missing, it will default to denying access (since 4.0).
# @max-connections: The maximum number of connections to allow at the same
-# time, 0 for unlimited. (since 5.2; default: 0)
+# time, 0 for unlimited. (since 5.2; default: 100)
#
# Returns: error if the server is already running.
#
--
2.39.3

View File

@ -1,180 +0,0 @@
From 4ab086cdf9a5842c49f3fe59baff1747d863b97a Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Wed, 7 Aug 2024 12:23:13 -0500
Subject: [PATCH 4/5] nbd/server: CVE-2024-7409: Close stray clients at
server-stop
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Eric Blake <eblake@redhat.com>
RH-MergeRequest: 388: nbd/server: fix CVE-2024-7409 (qemu crash on nbd-server-stop) [rhel-8.10.z]
RH-Jira: RHEL-52611
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Richard W.M. Jones <rjones@redhat.com>
RH-Commit: [4/4] 92a20764dbee3cf94181cab412d90cbf92b4a417 (ebblake/qemu-kvm)
A malicious client can attempt to connect to an NBD server, and then
intentionally delay progress in the handshake, including if it does
not know the TLS secrets. Although the previous two patches reduce
this behavior by capping the default max-connections parameter and
killing slow clients, they did not eliminate the possibility of a
client waiting to close the socket until after the QMP nbd-server-stop
command is executed, at which point qemu would SEGV when trying to
dereference the NULL nbd_server global which is no longer present.
This amounts to a denial of service attack. Worse, if another NBD
server is started before the malicious client disconnects, I cannot
rule out additional adverse effects when the old client interferes
with the connection count of the new server (although the most likely
is a crash due to an assertion failure when checking
nbd_server->connections > 0).
For environments without this patch, the CVE can be mitigated by
ensuring (such as via a firewall) that only trusted clients can
connect to an NBD server. Note that using frameworks like libvirt
that ensure that TLS is used and that nbd-server-stop is not executed
while any trusted clients are still connected will only help if there
is also no possibility for an untrusted client to open a connection
but then stall on the NBD handshake.
Given the previous patches, it would be possible to guarantee that no
clients remain connected by having nbd-server-stop sleep for longer
than the default handshake deadline before finally freeing the global
nbd_server object, but that could make QMP non-responsive for a long
time. So intead, this patch fixes the problem by tracking all client
sockets opened while the server is running, and forcefully closing any
such sockets remaining without a completed handshake at the time of
nbd-server-stop, then waiting until the coroutines servicing those
sockets notice the state change. nbd-server-stop now has a second
AIO_WAIT_WHILE_UNLOCKED (the first is indirectly through the
blk_exp_close_all_type() that disconnects all clients that completed
handshakes), but forced socket shutdown is enough to progress the
coroutines and quickly tear down all clients before the server is
freed, thus finally fixing the CVE.
This patch relies heavily on the fact that nbd/server.c guarantees
that it only calls nbd_blockdev_client_closed() from the main loop
(see the assertion in nbd_client_put() and the hoops used in
nbd_client_put_nonzero() to achieve that); if we did not have that
guarantee, we would also need a mutex protecting our accesses of the
list of connections to survive re-entrancy from independent iothreads.
Although I did not actually try to test old builds, it looks like this
problem has existed since at least commit 862172f45c (v2.12.0, 2017) -
even back when that patch started using a QIONetListener to handle
listening on multiple sockets, nbd_server_free() was already unaware
that the nbd_blockdev_client_closed callback can be reached later by a
client thread that has not completed handshakes (and therefore the
client's socket never got added to the list closed in
nbd_export_close_all), despite that patch intentionally tearing down
the QIONetListener to prevent new clients.
Reported-by: Alexander Ivanov <alexander.ivanov@virtuozzo.com>
Fixes: CVE-2024-7409
CC: qemu-stable@nongnu.org
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-ID: <20240807174943.771624-14-eblake@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit 3e7ef738c8462c45043a1d39f702a0990406a3b3)
Conflicts:
- blockdev-nbd.c:
- qemu_in_main_thread() not backported, but only used in assertions so
safe to drop
- AIO_WAIT_WHILE_UNLOCKED() not backported, use AIO_WAIT_WHILE() like
blk_exp_close_all_type()
Jira: https://issues.redhat.com/browse/RHEL-52611
Signed-off-by: Eric Blake <eblake@redhat.com>
---
blockdev-nbd.c | 35 ++++++++++++++++++++++++++++++++++-
1 file changed, 34 insertions(+), 1 deletion(-)
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index 4bd90bac16..87839c180b 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -21,12 +21,18 @@
#include "io/channel-socket.h"
#include "io/net-listener.h"
+typedef struct NBDConn {
+ QIOChannelSocket *cioc;
+ QLIST_ENTRY(NBDConn) next;
+} NBDConn;
+
typedef struct NBDServerData {
QIONetListener *listener;
QCryptoTLSCreds *tlscreds;
char *tlsauthz;
uint32_t max_connections;
uint32_t connections;
+ QLIST_HEAD(, NBDConn) conns;
} NBDServerData;
static NBDServerData *nbd_server;
@@ -46,6 +52,14 @@ bool nbd_server_is_running(void)
static void nbd_blockdev_client_closed(NBDClient *client, bool ignored)
{
+ NBDConn *conn = nbd_client_owner(client);
+
+ assert(nbd_server);
+
+ object_unref(OBJECT(conn->cioc));
+ QLIST_REMOVE(conn, next);
+ g_free(conn);
+
nbd_client_put(client);
assert(nbd_server->connections > 0);
nbd_server->connections--;
@@ -55,14 +69,20 @@ static void nbd_blockdev_client_closed(NBDClient *client, bool ignored)
static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc,
gpointer opaque)
{
+ NBDConn *conn = g_new0(NBDConn, 1);
+
+ assert(nbd_server);
nbd_server->connections++;
+ object_ref(OBJECT(cioc));
+ conn->cioc = cioc;
+ QLIST_INSERT_HEAD(&nbd_server->conns, conn, next);
nbd_update_server_watch(nbd_server);
qio_channel_set_name(QIO_CHANNEL(cioc), "nbd-server");
/* TODO - expose handshake timeout as QMP option */
nbd_client_new(cioc, NBD_DEFAULT_HANDSHAKE_MAX_SECS,
nbd_server->tlscreds, nbd_server->tlsauthz,
- nbd_blockdev_client_closed, NULL);
+ nbd_blockdev_client_closed, conn);
}
static void nbd_update_server_watch(NBDServerData *s)
@@ -76,12 +96,25 @@ static void nbd_update_server_watch(NBDServerData *s)
static void nbd_server_free(NBDServerData *server)
{
+ NBDConn *conn, *tmp;
+
if (!server) {
return;
}
+ /*
+ * Forcefully close the listener socket, and any clients that have
+ * not yet disconnected on their own.
+ */
qio_net_listener_disconnect(server->listener);
object_unref(OBJECT(server->listener));
+ QLIST_FOREACH_SAFE(conn, &server->conns, next, tmp) {
+ qio_channel_shutdown(QIO_CHANNEL(conn->cioc), QIO_CHANNEL_SHUTDOWN_BOTH,
+ NULL);
+ }
+
+ AIO_WAIT_WHILE(NULL, server->connections > 0);
+
if (server->tlscreds) {
object_unref(OBJECT(server->tlscreds));
}
--
2.39.3

View File

@ -1,135 +0,0 @@
From faac5261d5a9af155950c4e7779c5a4721562824 Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Thu, 8 Aug 2024 16:05:08 -0500
Subject: [PATCH 3/5] nbd/server: CVE-2024-7409: Drop non-negotiating clients
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Eric Blake <eblake@redhat.com>
RH-MergeRequest: 388: nbd/server: fix CVE-2024-7409 (qemu crash on nbd-server-stop) [rhel-8.10.z]
RH-Jira: RHEL-52611
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Richard W.M. Jones <rjones@redhat.com>
RH-Commit: [3/4] 8c39829f8efbded9af018a4b915af266a55a793a (ebblake/qemu-kvm)
A client that opens a socket but does not negotiate is merely hogging
qemu's resources (an open fd and a small amount of memory); and a
malicious client that can access the port where NBD is listening can
attempt a denial of service attack by intentionally opening and
abandoning lots of unfinished connections. The previous patch put a
default bound on the number of such ongoing connections, but once that
limit is hit, no more clients can connect (including legitimate ones).
The solution is to insist that clients complete handshake within a
reasonable time limit, defaulting to 10 seconds. A client that has
not successfully completed NBD_OPT_GO by then (including the case of
where the client didn't know TLS credentials to even reach the point
of NBD_OPT_GO) is wasting our time and does not deserve to stay
connected. Later patches will allow fine-tuning the limit away from
the default value (including disabling it for doing integration
testing of the handshake process itself).
Note that this patch in isolation actually makes it more likely to see
qemu SEGV after nbd-server-stop, as any client socket still connected
when the server shuts down will now be closed after 10 seconds rather
than at the client's whims. That will be addressed in the next patch.
For a demo of this patch in action:
$ qemu-nbd -f raw -r -t -e 10 file &
$ nbdsh --opt-mode -c '
H = list()
for i in range(20):
print(i)
H.insert(i, nbd.NBD())
H[i].set_opt_mode(True)
H[i].connect_uri("nbd://localhost")
'
$ kill $!
where later connections get to start progressing once earlier ones are
forcefully dropped for taking too long, rather than hanging.
Suggested-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-ID: <20240807174943.771624-13-eblake@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
[eblake: rebase to changes earlier in series, reduce scope of timer]
Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit b9b72cb3ce15b693148bd09cef7e50110566d8a0)
Conflicts:
nbd/server.c - context with different aiocontext locking
nbd/trace-events - context with no client-connection.c
Jira: https://issues.redhat.com/browse/RHEL-52611
Signed-off-by: Eric Blake <eblake@redhat.com>
---
nbd/server.c | 28 +++++++++++++++++++++++++++-
nbd/trace-events | 1 +
2 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/nbd/server.c b/nbd/server.c
index cc1b6838bf..1265068f70 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -2701,22 +2701,48 @@ static void nbd_client_receive_next_request(NBDClient *client)
}
}
+static void nbd_handshake_timer_cb(void *opaque)
+{
+ QIOChannel *ioc = opaque;
+
+ trace_nbd_handshake_timer_cb();
+ qio_channel_shutdown(ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL);
+}
+
static coroutine_fn void nbd_co_client_start(void *opaque)
{
NBDClient *client = opaque;
Error *local_err = NULL;
+ QEMUTimer *handshake_timer = NULL;
qemu_co_mutex_init(&client->send_lock);
- /* TODO - utilize client->handshake_max_secs */
+ /*
+ * Create a timer to bound the time spent in negotiation. If the
+ * timer expires, it is likely nbd_negotiate will fail because the
+ * socket was shutdown.
+ */
+ if (client->handshake_max_secs > 0) {
+ handshake_timer = aio_timer_new(qemu_get_aio_context(),
+ QEMU_CLOCK_REALTIME,
+ SCALE_NS,
+ nbd_handshake_timer_cb,
+ client->sioc);
+ timer_mod(handshake_timer,
+ qemu_clock_get_ns(QEMU_CLOCK_REALTIME) +
+ client->handshake_max_secs * NANOSECONDS_PER_SECOND);
+ }
+
if (nbd_negotiate(client, &local_err)) {
if (local_err) {
error_report_err(local_err);
}
+ timer_free(handshake_timer);
client_close(client, false);
return;
}
+ timer_free(handshake_timer);
nbd_client_receive_next_request(client);
}
diff --git a/nbd/trace-events b/nbd/trace-events
index c4919a2dd5..553546f1f2 100644
--- a/nbd/trace-events
+++ b/nbd/trace-events
@@ -73,3 +73,4 @@ nbd_co_receive_request_decode_type(uint64_t handle, uint16_t type, const char *n
nbd_co_receive_request_payload_received(uint64_t handle, uint32_t len) "Payload received: handle = %" PRIu64 ", len = %" PRIu32
nbd_co_receive_align_compliance(const char *op, uint64_t from, uint32_t len, uint32_t align) "client sent non-compliant unaligned %s request: from=0x%" PRIx64 ", len=0x%" PRIx32 ", align=0x%" PRIx32
nbd_trip(void) "Reading request"
+nbd_handshake_timer_cb(void) "client took too long to negotiate"
--
2.39.3

View File

@ -1,161 +0,0 @@
From 00af174d1388ed2d2df7961ee78be6af3757a01c Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Wed, 30 Aug 2023 18:48:02 -0400
Subject: [PATCH 1/3] nbd/server: Favor qemu_aio_context over iohandler context
RH-Author: Eric Blake <eblake@redhat.com>
RH-MergeRequest: 398: nbd/server: CVE-2024-7409: Avoid use-after-free when closing server
RH-Jira: RHEL-52611
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
RH-Commit: [1/3] 6ec0ef287fbc976175da83a0c14d9878e83affa2 (ebblake/qemu-kvm)
DOWNSTREAM ONLY - but based on an idea originally included as a
side-effect in the larger upstream patch 06e0f098 "io: follow
coroutine AioContext in qio_channel_yield()", as well as handling the
state of the qio TLS channel before it is associated with a block
device as an alternative to 199e84de "qio: Inherit
follow_coroutine_ctx across TLS".
The NBD server code wants to use qio_channel_shutdown() followed by
AIO_WAIT_WHILE() during nbd_server_free(), but cannot attach the ioc
to an AioContext until the client has completed the handshake to the
point that the server knows what block device to associate with the
connection. The qio code is set up to handle connections with no
AioContext in the iohandler context, but this context is specifically
designed to NOT make progress during AIO_WAIT_WHILE(). In order to
prevent things from deadlocking, the qio channels handling NBD
handshake MUST be in the qemu_aio_context, so that an early shutdown
triggered by nbd-server-stop can make progress.
Note that upstream handled the main qio channel by the use of
qio_channel_set_follow_coroutine_ctx() in only one place in
nbd/server.c; upstream handled the TLS channel by a more generic
second patch that taught qio TLS channel to inherit the
follow_coroutine_ctx status from its parent. But since this patch is
already downstream only, the minimal diff is achieved by manually
setting the status of the TLS channel in NBD code, rather than
backporting the qio inheritance code. For testing that the second
call to qio_channel_set_favor_qemu_aio_ctx() matters, I used this test
setup (borrowing a pre-built PSK file for username alice from the
libnbd project, and using IPv4 since this qemu is too old to support
TLS over Unix sockets):
$ # in terminal 1:
$ qemu-system-x86_64 --nographic --nodefaults --qmp stdio \
--object tls-creds-psk,id=tls0,dir=/PATHTO/libnbd/tests,endpoint=server
{"execute": "qmp_capabilities"}
{"execute":"nbd-server-start","arguments":{"addr":{"type":"inet",
"data":{"host":"127.0.0.1","port":"10809"}},"tls-creds":"tls0"}}
$ # in terminal 2:
$ nbdsh -c 'h.set_uri_allow_local_file(True)' --opt-mode -u \
'nbds://alice@127.0.0.1/?tls-psk-file=/PATHTO/libnbd/tests/keys.psk' \
-c 'import time; time.sleep(15)'
$ # in terminal 1, before 10 seconds elapse
{"execute":"nbd-server-stop"}
{"execute":"quit"}
and observed that, when omitting the one-line TLS setting, qemu would
hit the same deadlock with a TLS client as what I was observing for a
non-TLS client without this entire patch.
Jira: https://issues.redhat.com/browse/RHEL-52611
Suggested-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
---
include/io/channel.h | 16 ++++++++++++++++
io/channel.c | 14 +++++++++++++-
nbd/server.c | 2 ++
3 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/include/io/channel.h b/include/io/channel.h
index 716235d496..f1ce19ea81 100644
--- a/include/io/channel.h
+++ b/include/io/channel.h
@@ -84,6 +84,7 @@ struct QIOChannel {
AioContext *ctx;
Coroutine *read_coroutine;
Coroutine *write_coroutine;
+ bool favor_qemu_aio_ctx;
#ifdef _WIN32
HANDLE event; /* For use with GSource on Win32 */
#endif
@@ -498,6 +499,21 @@ int qio_channel_set_blocking(QIOChannel *ioc,
bool enabled,
Error **errp);
+/**
+ * qio_channel_set_favor_qemu_aio_ctx:
+ * @ioc: the channel object
+ * @enabled: whether to fall back to qemu_aio_context
+ *
+ * If @enabled is true, calls to qio_channel_yield() with no AioContext
+ * set use the qemu_aio_context instead of the global iohandler context.
+ *
+ * If @enabled is false, calls to qio_channel_yield() use the global iohandler
+ * AioContext. This is may be used by coroutines that run in the main loop and
+ * do not wish to respond to I/O during nested event loops. This is the
+ * default for compatibility with code that is not aware of AioContexts.
+ */
+void qio_channel_set_favor_qemu_aio_ctx(QIOChannel *ioc, bool enabled);
+
/**
* qio_channel_close:
* @ioc: the channel object
diff --git a/io/channel.c b/io/channel.c
index a8c7f11649..74704d0464 100644
--- a/io/channel.c
+++ b/io/channel.c
@@ -364,6 +364,12 @@ int qio_channel_set_blocking(QIOChannel *ioc,
}
+void qio_channel_set_favor_qemu_aio_ctx(QIOChannel *ioc, bool enabled)
+{
+ ioc->favor_qemu_aio_ctx = enabled;
+}
+
+
int qio_channel_close(QIOChannel *ioc,
Error **errp)
{
@@ -545,7 +551,13 @@ static void qio_channel_set_aio_fd_handlers(QIOChannel *ioc)
wr_handler = qio_channel_restart_write;
}
- ctx = ioc->ctx ? ioc->ctx : iohandler_get_aio_context();
+ if (ioc->ctx) {
+ ctx = ioc->ctx;
+ } else if (ioc->favor_qemu_aio_ctx) {
+ ctx = qemu_get_aio_context();
+ } else {
+ ctx = iohandler_get_aio_context();
+ }
qio_channel_set_aio_fd_handler(ioc, ctx, rd_handler, wr_handler, ioc);
}
diff --git a/nbd/server.c b/nbd/server.c
index 1265068f70..41a2003300 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -758,6 +758,7 @@ static QIOChannel *nbd_negotiate_handle_starttls(NBDClient *client,
return NULL;
}
+ qio_channel_set_favor_qemu_aio_ctx(QIO_CHANNEL(tioc), true);
qio_channel_set_name(QIO_CHANNEL(tioc), "nbd-server-tls");
trace_nbd_negotiate_handle_starttls_handshake();
data.loop = g_main_loop_new(g_main_context_default(), FALSE);
@@ -1333,6 +1334,7 @@ static coroutine_fn int nbd_negotiate(NBDClient *client, Error **errp)
*/
qio_channel_set_blocking(client->ioc, false, NULL);
+ qio_channel_set_favor_qemu_aio_ctx(client->ioc, true);
trace_nbd_negotiate_begin();
memcpy(buf, "NBDMAGIC", 8);
--
2.39.3

View File

@ -1,174 +0,0 @@
From 0d204cb81aec2b13254a0bd53938f53bfea81cb5 Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Wed, 7 Aug 2024 08:50:01 -0500
Subject: [PATCH 1/5] nbd/server: Plumb in new args to nbd_client_add()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Eric Blake <eblake@redhat.com>
RH-MergeRequest: 388: nbd/server: fix CVE-2024-7409 (qemu crash on nbd-server-stop) [rhel-8.10.z]
RH-Jira: RHEL-52611
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Acked-by: Richard W.M. Jones <rjones@redhat.com>
RH-Commit: [1/4] 292be8dd2df2a840b2200e31a27e9d17fdab91ad (ebblake/qemu-kvm)
Upcoming patches to fix a CVE need to track an opaque pointer passed
in by the owner of a client object, as well as request for a time
limit on how fast negotiation must complete. Prepare for that by
changing the signature of nbd_client_new() and adding an accessor to
get at the opaque pointer, although for now the two servers
(qemu-nbd.c and blockdev-nbd.c) do not change behavior even though
they pass in a new default timeout value.
Suggested-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-ID: <20240807174943.771624-11-eblake@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
[eblake: s/LIMIT/MAX_SECS/ as suggested by Dan]
Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit fb1c2aaa981e0a2fa6362c9985f1296b74f055ac)
Jira: https://issues.redhat.com/browse/RHEL-52611
Signed-off-by: Eric Blake <eblake@redhat.com>
---
blockdev-nbd.c | 6 ++++--
include/block/nbd.h | 11 ++++++++++-
nbd/server.c | 20 +++++++++++++++++---
qemu-nbd.c | 4 +++-
4 files changed, 34 insertions(+), 7 deletions(-)
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
index bdfa7ed3a5..b9e8dc78f3 100644
--- a/blockdev-nbd.c
+++ b/blockdev-nbd.c
@@ -59,8 +59,10 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc,
nbd_update_server_watch(nbd_server);
qio_channel_set_name(QIO_CHANNEL(cioc), "nbd-server");
- nbd_client_new(cioc, nbd_server->tlscreds, nbd_server->tlsauthz,
- nbd_blockdev_client_closed);
+ /* TODO - expose handshake timeout as QMP option */
+ nbd_client_new(cioc, NBD_DEFAULT_HANDSHAKE_MAX_SECS,
+ nbd_server->tlscreds, nbd_server->tlsauthz,
+ nbd_blockdev_client_closed, NULL);
}
static void nbd_update_server_watch(NBDServerData *s)
diff --git a/include/block/nbd.h b/include/block/nbd.h
index 78d101b774..b71a297249 100644
--- a/include/block/nbd.h
+++ b/include/block/nbd.h
@@ -27,6 +27,12 @@
extern const BlockExportDriver blk_exp_nbd;
+/*
+ * NBD_DEFAULT_HANDSHAKE_MAX_SECS: Number of seconds in which client must
+ * succeed at NBD_OPT_GO before being forcefully dropped as too slow.
+ */
+#define NBD_DEFAULT_HANDSHAKE_MAX_SECS 10
+
/* Handshake phase structs - this struct is passed on the wire */
struct NBDOption {
@@ -338,9 +344,12 @@ AioContext *nbd_export_aio_context(NBDExport *exp);
NBDExport *nbd_export_find(const char *name);
void nbd_client_new(QIOChannelSocket *sioc,
+ uint32_t handshake_max_secs,
QCryptoTLSCreds *tlscreds,
const char *tlsauthz,
- void (*close_fn)(NBDClient *, bool));
+ void (*close_fn)(NBDClient *, bool),
+ void *owner);
+void *nbd_client_owner(NBDClient *client);
void nbd_client_get(NBDClient *client);
void nbd_client_put(NBDClient *client);
diff --git a/nbd/server.c b/nbd/server.c
index 6db124cf53..cc1b6838bf 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -120,10 +120,12 @@ typedef struct NBDExportMetaContexts {
struct NBDClient {
int refcount;
void (*close_fn)(NBDClient *client, bool negotiated);
+ void *owner;
NBDExport *exp;
QCryptoTLSCreds *tlscreds;
char *tlsauthz;
+ uint32_t handshake_max_secs;
QIOChannelSocket *sioc; /* The underlying data channel */
QIOChannel *ioc; /* The current I/O channel which may differ (eg TLS) */
@@ -2706,6 +2708,7 @@ static coroutine_fn void nbd_co_client_start(void *opaque)
qemu_co_mutex_init(&client->send_lock);
+ /* TODO - utilize client->handshake_max_secs */
if (nbd_negotiate(client, &local_err)) {
if (local_err) {
error_report_err(local_err);
@@ -2718,14 +2721,17 @@ static coroutine_fn void nbd_co_client_start(void *opaque)
}
/*
- * Create a new client listener using the given channel @sioc.
+ * Create a new client listener using the given channel @sioc and @owner.
* Begin servicing it in a coroutine. When the connection closes, call
- * @close_fn with an indication of whether the client completed negotiation.
+ * @close_fn with an indication of whether the client completed negotiation
+ * within @handshake_max_secs seconds (0 for unbounded).
*/
void nbd_client_new(QIOChannelSocket *sioc,
+ uint32_t handshake_max_secs,
QCryptoTLSCreds *tlscreds,
const char *tlsauthz,
- void (*close_fn)(NBDClient *, bool))
+ void (*close_fn)(NBDClient *, bool),
+ void *owner)
{
NBDClient *client;
Coroutine *co;
@@ -2737,13 +2743,21 @@ void nbd_client_new(QIOChannelSocket *sioc,
object_ref(OBJECT(client->tlscreds));
}
client->tlsauthz = g_strdup(tlsauthz);
+ client->handshake_max_secs = handshake_max_secs;
client->sioc = sioc;
qio_channel_set_delay(QIO_CHANNEL(sioc), false);
object_ref(OBJECT(client->sioc));
client->ioc = QIO_CHANNEL(sioc);
object_ref(OBJECT(client->ioc));
client->close_fn = close_fn;
+ client->owner = owner;
co = qemu_coroutine_create(nbd_co_client_start, client);
qemu_coroutine_enter(co);
}
+
+void *
+nbd_client_owner(NBDClient *client)
+{
+ return client->owner;
+}
diff --git a/qemu-nbd.c b/qemu-nbd.c
index c6c20df68a..f48abf379e 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -363,7 +363,9 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc,
nb_fds++;
nbd_update_server_watch();
- nbd_client_new(cioc, tlscreds, tlsauthz, nbd_client_closed);
+ /* TODO - expose handshake timeout as command line option */
+ nbd_client_new(cioc, NBD_DEFAULT_HANDSHAKE_MAX_SECS,
+ tlscreds, tlsauthz, nbd_client_closed, NULL);
}
static void nbd_update_server_watch(void)
--
2.39.3

View File

@ -1,611 +0,0 @@
From 2ae925a6d55a77627be8d1146f2b9ed139dbdb77 Mon Sep 17 00:00:00 2001
From: Jon Maloy <jmaloy@redhat.com>
Date: Thu, 23 Nov 2023 11:30:46 -0500
Subject: [PATCH 1/4] net: Provide MemReentrancyGuard * to qemu_new_nic()
RH-Author: Jon Maloy <jmaloy@redhat.com>
RH-MergeRequest: 331: net: Provide MemReentrancyGuard * to qemu_new_nic()
RH-Jira: RHEL-7309
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Jason Wang <jasowang@redhat.com>
RH-Commit: [1/2] bc963fb349b90288f547de97a5cbe9a74f856419 (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2)
Jira: https://issues.redhat.com/browse/RHEL-7309
CVE: CVE-2023-3019
Upstream: Merged
Conflicts: hw/net/hw/net/xen_nic.c seems to have undergone significant changes upstream,
so the change had to be manually adapted to the old code.
commit 7d0fefdf81f5973334c344f6b8e1896c309dff66
Author: Akihiko Odaki <akihiko.odaki@daynix.com>
Date: Thu Jun 1 12:18:58 2023 +0900
net: Provide MemReentrancyGuard * to qemu_new_nic()
Recently MemReentrancyGuard was added to DeviceState to record that the
device is engaging in I/O. The network device backend needs to update it
when delivering a packet to a device.
In preparation for such a change, add MemReentrancyGuard * as a
parameter of qemu_new_nic().
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Reviewed-by: Alexander Bulekov <alxndr@bu.edu>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
hw/net/allwinner-sun8i-emac.c | 3 ++-
hw/net/allwinner_emac.c | 3 ++-
hw/net/cadence_gem.c | 3 ++-
hw/net/dp8393x.c | 3 ++-
hw/net/e1000.c | 3 ++-
hw/net/e1000e.c | 2 +-
hw/net/eepro100.c | 4 +++-
hw/net/etraxfs_eth.c | 3 ++-
hw/net/fsl_etsec/etsec.c | 3 ++-
hw/net/ftgmac100.c | 3 ++-
hw/net/i82596.c | 2 +-
hw/net/imx_fec.c | 2 +-
hw/net/lan9118.c | 3 ++-
hw/net/mcf_fec.c | 3 ++-
hw/net/mipsnet.c | 3 ++-
hw/net/msf2-emac.c | 3 ++-
hw/net/ne2000-isa.c | 3 ++-
hw/net/ne2000-pci.c | 3 ++-
hw/net/npcm7xx_emc.c | 3 ++-
hw/net/opencores_eth.c | 3 ++-
hw/net/pcnet.c | 3 ++-
hw/net/rocker/rocker_fp.c | 4 ++--
hw/net/rtl8139.c | 3 ++-
hw/net/smc91c111.c | 3 ++-
hw/net/spapr_llan.c | 3 ++-
hw/net/stellaris_enet.c | 3 ++-
hw/net/sungem.c | 2 +-
hw/net/sunhme.c | 3 ++-
hw/net/tulip.c | 3 ++-
hw/net/virtio-net.c | 6 ++++--
hw/net/vmxnet3.c | 2 +-
hw/net/xen_nic.c | 3 ++-
hw/net/xgmac.c | 3 ++-
hw/net/xilinx_axienet.c | 3 ++-
hw/net/xilinx_ethlite.c | 3 ++-
hw/usb/dev-network.c | 3 ++-
include/net/net.h | 1 +
net/net.c | 1 +
38 files changed, 72 insertions(+), 38 deletions(-)
diff --git a/hw/net/allwinner-sun8i-emac.c b/hw/net/allwinner-sun8i-emac.c
index ff611f18fb..9d0885ee15 100644
--- a/hw/net/allwinner-sun8i-emac.c
+++ b/hw/net/allwinner-sun8i-emac.c
@@ -810,7 +810,8 @@ static void allwinner_sun8i_emac_realize(DeviceState *dev, Error **errp)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_allwinner_sun8i_emac_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->id, s);
+ object_get_typename(OBJECT(dev)), dev->id,
+ &dev->mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
}
diff --git a/hw/net/allwinner_emac.c b/hw/net/allwinner_emac.c
index ddddf35c45..b3d73143bf 100644
--- a/hw/net/allwinner_emac.c
+++ b/hw/net/allwinner_emac.c
@@ -453,7 +453,8 @@ static void aw_emac_realize(DeviceState *dev, Error **errp)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_aw_emac_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->id, s);
+ object_get_typename(OBJECT(dev)), dev->id,
+ &dev->mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
fifo8_create(&s->rx_fifo, RX_FIFO_SIZE);
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
index 24b3a0ff66..cb61a76417 100644
--- a/hw/net/cadence_gem.c
+++ b/hw/net/cadence_gem.c
@@ -1633,7 +1633,8 @@ static void gem_realize(DeviceState *dev, Error **errp)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_gem_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->id, s);
+ object_get_typename(OBJECT(dev)), dev->id,
+ &dev->mem_reentrancy_guard, s);
if (s->jumbo_max_len > MAX_FRAME_SIZE) {
error_setg(errp, "jumbo-max-len is greater than %d",
diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index 45b954e46c..abfcc6f69f 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -943,7 +943,8 @@ static void dp8393x_realize(DeviceState *dev, Error **errp)
"dp8393x-regs", SONIC_REG_COUNT << s->it_shift);
s->nic = qemu_new_nic(&net_dp83932_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->id, s);
+ object_get_typename(OBJECT(dev)), dev->id,
+ &dev->mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
s->watchdog = timer_new_ns(QEMU_CLOCK_VIRTUAL, dp8393x_watchdog, s);
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index 282d01e374..86da1ae39e 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -1733,7 +1733,8 @@ static void pci_e1000_realize(PCIDevice *pci_dev, Error **errp)
macaddr);
d->nic = qemu_new_nic(&net_e1000_info, &d->conf,
- object_get_typename(OBJECT(d)), dev->id, d);
+ object_get_typename(OBJECT(d)), dev->id,
+ &dev->mem_reentrancy_guard, d);
qemu_format_nic_info_str(qemu_get_queue(d->nic), macaddr);
diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c
index d35bc1f0b0..c6096fa848 100644
--- a/hw/net/e1000e.c
+++ b/hw/net/e1000e.c
@@ -340,7 +340,7 @@ e1000e_init_net_peer(E1000EState *s, PCIDevice *pci_dev, uint8_t *macaddr)
int i;
s->nic = qemu_new_nic(&net_e1000e_info, &s->conf,
- object_get_typename(OBJECT(s)), dev->id, s);
+ object_get_typename(OBJECT(s)), dev->id, &dev->mem_reentrancy_guard, s);
s->core.max_queue_num = s->conf.peers.queues ? s->conf.peers.queues - 1 : 0;
diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
index 16e95ef9cc..16ca4dda04 100644
--- a/hw/net/eepro100.c
+++ b/hw/net/eepro100.c
@@ -1865,7 +1865,9 @@ static void e100_nic_realize(PCIDevice *pci_dev, Error **errp)
nic_reset(s);
s->nic = qemu_new_nic(&net_eepro100_info, &s->conf,
- object_get_typename(OBJECT(pci_dev)), pci_dev->qdev.id, s);
+ object_get_typename(OBJECT(pci_dev)),
+ pci_dev->qdev.id,
+ &pci_dev->qdev.mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
TRACE(OTHER, logout("%s\n", qemu_get_queue(s->nic)->info_str));
diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c
index 1b82aec794..ba57a978d1 100644
--- a/hw/net/etraxfs_eth.c
+++ b/hw/net/etraxfs_eth.c
@@ -618,7 +618,8 @@ static void etraxfs_eth_realize(DeviceState *dev, Error **errp)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_etraxfs_info, &s->conf,
- object_get_typename(OBJECT(s)), dev->id, s);
+ object_get_typename(OBJECT(s)), dev->id,
+ &dev->mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
s->phy.read = tdk_read;
diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c
index bd9d62b559..f790613b52 100644
--- a/hw/net/fsl_etsec/etsec.c
+++ b/hw/net/fsl_etsec/etsec.c
@@ -391,7 +391,8 @@ static void etsec_realize(DeviceState *dev, Error **errp)
eTSEC *etsec = ETSEC_COMMON(dev);
etsec->nic = qemu_new_nic(&net_etsec_info, &etsec->conf,
- object_get_typename(OBJECT(dev)), dev->id, etsec);
+ object_get_typename(OBJECT(dev)), dev->id,
+ &dev->mem_reentrancy_guard, etsec);
qemu_format_nic_info_str(qemu_get_queue(etsec->nic), etsec->conf.macaddr.a);
etsec->ptimer = ptimer_init(etsec_timer_hit, etsec, PTIMER_POLICY_DEFAULT);
diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
index 25685ba3a9..781e7f352e 100644
--- a/hw/net/ftgmac100.c
+++ b/hw/net/ftgmac100.c
@@ -1111,7 +1111,8 @@ static void ftgmac100_realize(DeviceState *dev, Error **errp)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_ftgmac100_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->id, s);
+ object_get_typename(OBJECT(dev)), dev->id,
+ &dev->mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
}
diff --git a/hw/net/i82596.c b/hw/net/i82596.c
index ec21e2699a..dc64246f75 100644
--- a/hw/net/i82596.c
+++ b/hw/net/i82596.c
@@ -743,7 +743,7 @@ void i82596_common_init(DeviceState *dev, I82596State *s, NetClientInfo *info)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
}
s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)),
- dev->id, s);
+ dev->id, &dev->mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
if (USE_TIMER) {
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index 9c7035bc94..ed19ee9350 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -1310,7 +1310,7 @@ static void imx_eth_realize(DeviceState *dev, Error **errp)
s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf,
object_get_typename(OBJECT(dev)),
- dev->id, s);
+ dev->id, &dev->mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
}
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
index 6aff424cbe..942bce9ae6 100644
--- a/hw/net/lan9118.c
+++ b/hw/net/lan9118.c
@@ -1354,7 +1354,8 @@ static void lan9118_realize(DeviceState *dev, Error **errp)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_lan9118_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->id, s);
+ object_get_typename(OBJECT(dev)), dev->id,
+ &dev->mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
s->eeprom[0] = 0xa5;
for (i = 0; i < 6; i++) {
diff --git a/hw/net/mcf_fec.c b/hw/net/mcf_fec.c
index 25e3e453ab..a6be7bf413 100644
--- a/hw/net/mcf_fec.c
+++ b/hw/net/mcf_fec.c
@@ -643,7 +643,8 @@ static void mcf_fec_realize(DeviceState *dev, Error **errp)
mcf_fec_state *s = MCF_FEC_NET(dev);
s->nic = qemu_new_nic(&net_mcf_fec_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->id, s);
+ object_get_typename(OBJECT(dev)), dev->id,
+ &dev->mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
}
diff --git a/hw/net/mipsnet.c b/hw/net/mipsnet.c
index 2ade72dea0..8e925de867 100644
--- a/hw/net/mipsnet.c
+++ b/hw/net/mipsnet.c
@@ -255,7 +255,8 @@ static void mipsnet_realize(DeviceState *dev, Error **errp)
sysbus_init_irq(sbd, &s->irq);
s->nic = qemu_new_nic(&net_mipsnet_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->id, s);
+ object_get_typename(OBJECT(dev)), dev->id,
+ &dev->mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
}
diff --git a/hw/net/msf2-emac.c b/hw/net/msf2-emac.c
index 9278fdce0b..1efa3dbf01 100644
--- a/hw/net/msf2-emac.c
+++ b/hw/net/msf2-emac.c
@@ -527,7 +527,8 @@ static void msf2_emac_realize(DeviceState *dev, Error **errp)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_msf2_emac_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->id, s);
+ object_get_typename(OBJECT(dev)), dev->id,
+ &dev->mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
}
diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c
index dd6f6e34d3..30bd20c293 100644
--- a/hw/net/ne2000-isa.c
+++ b/hw/net/ne2000-isa.c
@@ -74,7 +74,8 @@ static void isa_ne2000_realizefn(DeviceState *dev, Error **errp)
ne2000_reset(s);
s->nic = qemu_new_nic(&net_ne2000_isa_info, &s->c,
- object_get_typename(OBJECT(dev)), dev->id, s);
+ object_get_typename(OBJECT(dev)), dev->id,
+ &dev->mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a);
}
diff --git a/hw/net/ne2000-pci.c b/hw/net/ne2000-pci.c
index 9e5d10859a..4f8a699081 100644
--- a/hw/net/ne2000-pci.c
+++ b/hw/net/ne2000-pci.c
@@ -71,7 +71,8 @@ static void pci_ne2000_realize(PCIDevice *pci_dev, Error **errp)
s->nic = qemu_new_nic(&net_ne2000_info, &s->c,
object_get_typename(OBJECT(pci_dev)),
- pci_dev->qdev.id, s);
+ pci_dev->qdev.id,
+ &pci_dev->qdev.mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a);
}
diff --git a/hw/net/npcm7xx_emc.c b/hw/net/npcm7xx_emc.c
index 7c892f820f..dd1d0ad3bc 100644
--- a/hw/net/npcm7xx_emc.c
+++ b/hw/net/npcm7xx_emc.c
@@ -802,7 +802,8 @@ static void npcm7xx_emc_realize(DeviceState *dev, Error **errp)
qemu_macaddr_default_if_unset(&emc->conf.macaddr);
emc->nic = qemu_new_nic(&net_npcm7xx_emc_info, &emc->conf,
- object_get_typename(OBJECT(dev)), dev->id, emc);
+ object_get_typename(OBJECT(dev)), dev->id,
+ &dev->mem_reentrancy_guard, emc);
qemu_format_nic_info_str(qemu_get_queue(emc->nic), emc->conf.macaddr.a);
}
diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c
index 0b3dc3146e..f96d6ea2cc 100644
--- a/hw/net/opencores_eth.c
+++ b/hw/net/opencores_eth.c
@@ -732,7 +732,8 @@ static void sysbus_open_eth_realize(DeviceState *dev, Error **errp)
sysbus_init_irq(sbd, &s->irq);
s->nic = qemu_new_nic(&net_open_eth_info, &s->conf,
- object_get_typename(OBJECT(s)), dev->id, s);
+ object_get_typename(OBJECT(s)), dev->id,
+ &dev->mem_reentrancy_guard, s);
}
static void qdev_open_eth_reset(DeviceState *dev)
diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c
index dcd3fc4948..da910a70bf 100644
--- a/hw/net/pcnet.c
+++ b/hw/net/pcnet.c
@@ -1718,7 +1718,8 @@ void pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
s->poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pcnet_poll_timer, s);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
- s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, s);
+ s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)),
+ dev->id, &dev->mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
/* Initialize the PROM */
diff --git a/hw/net/rocker/rocker_fp.c b/hw/net/rocker/rocker_fp.c
index cbeed65bd5..0d21948ada 100644
--- a/hw/net/rocker/rocker_fp.c
+++ b/hw/net/rocker/rocker_fp.c
@@ -241,8 +241,8 @@ FpPort *fp_port_alloc(Rocker *r, char *sw_name,
port->conf.bootindex = -1;
port->conf.peers = *peers;
- port->nic = qemu_new_nic(&fp_port_info, &port->conf,
- sw_name, NULL, port);
+ port->nic = qemu_new_nic(&fp_port_info, &port->conf, sw_name, NULL,
+ &DEVICE(r)->mem_reentrancy_guard, port);
qemu_format_nic_info_str(qemu_get_queue(port->nic),
port->conf.macaddr.a);
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
index 3ffb9dd22c..a3565c7159 100644
--- a/hw/net/rtl8139.c
+++ b/hw/net/rtl8139.c
@@ -3400,7 +3400,8 @@ static void pci_rtl8139_realize(PCIDevice *dev, Error **errp)
s->eeprom.contents[9] = s->conf.macaddr.a[4] | s->conf.macaddr.a[5] << 8;
s->nic = qemu_new_nic(&net_rtl8139_info, &s->conf,
- object_get_typename(OBJECT(dev)), d->id, s);
+ object_get_typename(OBJECT(dev)), d->id,
+ &d->mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
s->cplus_txbuffer = NULL;
diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c
index ad778cd8fc..4eda971ef3 100644
--- a/hw/net/smc91c111.c
+++ b/hw/net/smc91c111.c
@@ -783,7 +783,8 @@ static void smc91c111_realize(DeviceState *dev, Error **errp)
sysbus_init_irq(sbd, &s->irq);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_smc91c111_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->id, s);
+ object_get_typename(OBJECT(dev)), dev->id,
+ &dev->mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
/* ??? Save/restore. */
}
diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c
index a6876a936d..475d5f3a34 100644
--- a/hw/net/spapr_llan.c
+++ b/hw/net/spapr_llan.c
@@ -325,7 +325,8 @@ static void spapr_vlan_realize(SpaprVioDevice *sdev, Error **errp)
memcpy(&dev->perm_mac.a, &dev->nicconf.macaddr.a, sizeof(dev->perm_mac.a));
dev->nic = qemu_new_nic(&net_spapr_vlan_info, &dev->nicconf,
- object_get_typename(OBJECT(sdev)), sdev->qdev.id, dev);
+ object_get_typename(OBJECT(sdev)), sdev->qdev.id,
+ &sdev->qdev.mem_reentrancy_guard, dev);
qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a);
dev->rxp_timer = timer_new_us(QEMU_CLOCK_VIRTUAL, spapr_vlan_flush_rx_queue,
diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c
index 8dd60783d8..6768a6912f 100644
--- a/hw/net/stellaris_enet.c
+++ b/hw/net/stellaris_enet.c
@@ -492,7 +492,8 @@ static void stellaris_enet_realize(DeviceState *dev, Error **errp)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_stellaris_enet_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->id, s);
+ object_get_typename(OBJECT(dev)), dev->id,
+ &dev->mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
}
diff --git a/hw/net/sungem.c b/hw/net/sungem.c
index 3684a4d733..c12d44e9dc 100644
--- a/hw/net/sungem.c
+++ b/hw/net/sungem.c
@@ -1361,7 +1361,7 @@ static void sungem_realize(PCIDevice *pci_dev, Error **errp)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_sungem_info, &s->conf,
object_get_typename(OBJECT(dev)),
- dev->id, s);
+ dev->id, &dev->mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic),
s->conf.macaddr.a);
}
diff --git a/hw/net/sunhme.c b/hw/net/sunhme.c
index fc34905f87..fa98528d71 100644
--- a/hw/net/sunhme.c
+++ b/hw/net/sunhme.c
@@ -892,7 +892,8 @@ static void sunhme_realize(PCIDevice *pci_dev, Error **errp)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_sunhme_info, &s->conf,
- object_get_typename(OBJECT(d)), d->id, s);
+ object_get_typename(OBJECT(d)), d->id,
+ &d->mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
}
diff --git a/hw/net/tulip.c b/hw/net/tulip.c
index ca69f7ea5e..985c4c14a4 100644
--- a/hw/net/tulip.c
+++ b/hw/net/tulip.c
@@ -981,7 +981,8 @@ static void pci_tulip_realize(PCIDevice *pci_dev, Error **errp)
s->nic = qemu_new_nic(&net_tulip_info, &s->c,
object_get_typename(OBJECT(pci_dev)),
- pci_dev->qdev.id, s);
+ pci_dev->qdev.id,
+ &pci_dev->qdev.mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a);
}
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index ddaa8fa122..f5f07f8e63 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -3512,10 +3512,12 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
* Happen when virtio_net_set_netclient_name has been called.
*/
n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf,
- n->netclient_type, n->netclient_name, n);
+ n->netclient_type, n->netclient_name,
+ &dev->mem_reentrancy_guard, n);
} else {
n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf,
- object_get_typename(OBJECT(dev)), dev->id, n);
+ object_get_typename(OBJECT(dev)), dev->id,
+ &dev->mem_reentrancy_guard, n);
}
for (i = 0; i < n->max_queue_pairs; i++) {
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index f65af4e9ef..d4df039c55 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -2078,7 +2078,7 @@ static void vmxnet3_net_init(VMXNET3State *s)
s->nic = qemu_new_nic(&net_vmxnet3_info, &s->conf,
object_get_typename(OBJECT(s)),
- d->id, s);
+ d->id, &d->mem_reentrancy_guard, s);
s->peer_has_vhdr = vmxnet3_peer_has_vnet_hdr(s);
s->tx_sop = true;
diff --git a/hw/net/xen_nic.c b/hw/net/xen_nic.c
index 5c815b4f0c..3d0b7820d3 100644
--- a/hw/net/xen_nic.c
+++ b/hw/net/xen_nic.c
@@ -294,7 +294,8 @@ static int net_init(struct XenLegacyDevice *xendev)
}
netdev->nic = qemu_new_nic(&net_xen_info, &netdev->conf,
- "xen", NULL, netdev);
+ "xen", NULL,
+ &xendev->qdev.mem_reentrancy_guard, netdev);
snprintf(qemu_get_queue(netdev->nic)->info_str,
sizeof(qemu_get_queue(netdev->nic)->info_str),
diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c
index 0ab6ae91aa..1f4f277d84 100644
--- a/hw/net/xgmac.c
+++ b/hw/net/xgmac.c
@@ -402,7 +402,8 @@ static void xgmac_enet_realize(DeviceState *dev, Error **errp)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_xgmac_enet_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->id, s);
+ object_get_typename(OBJECT(dev)), dev->id,
+ &dev->mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
s->regs[XGMAC_ADDR_HIGH(0)] = (s->conf.macaddr.a[5] << 8) |
diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c
index 990ff3a1c2..8a34243803 100644
--- a/hw/net/xilinx_axienet.c
+++ b/hw/net/xilinx_axienet.c
@@ -968,7 +968,8 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_xilinx_enet_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->id, s);
+ object_get_typename(OBJECT(dev)), dev->id,
+ &dev->mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
tdk_init(&s->TEMAC.phy);
diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c
index 6e09f7e422..80cb869e22 100644
--- a/hw/net/xilinx_ethlite.c
+++ b/hw/net/xilinx_ethlite.c
@@ -235,7 +235,8 @@ static void xilinx_ethlite_realize(DeviceState *dev, Error **errp)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_xilinx_ethlite_info, &s->conf,
- object_get_typename(OBJECT(dev)), dev->id, s);
+ object_get_typename(OBJECT(dev)), dev->id,
+ &dev->mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
}
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index 6c49c16015..ae447a8bc3 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -1362,7 +1362,8 @@ static void usb_net_realize(USBDevice *dev, Error **errp)
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_usbnet_info, &s->conf,
- object_get_typename(OBJECT(s)), s->dev.qdev.id, s);
+ object_get_typename(OBJECT(s)), s->dev.qdev.id,
+ &s->dev.qdev.mem_reentrancy_guard, s);
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
snprintf(s->usbstring_mac, sizeof(s->usbstring_mac),
"%02x%02x%02x%02x%02x%02x",
diff --git a/include/net/net.h b/include/net/net.h
index 523136c7ac..1457b6c014 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -145,6 +145,7 @@ NICState *qemu_new_nic(NetClientInfo *info,
NICConf *conf,
const char *model,
const char *name,
+ MemReentrancyGuard *reentrancy_guard,
void *opaque);
void qemu_del_nic(NICState *nic);
NetClientState *qemu_get_subqueue(NICState *nic, int queue_index);
diff --git a/net/net.c b/net/net.c
index f0d14dbfc1..669e194c4b 100644
--- a/net/net.c
+++ b/net/net.c
@@ -299,6 +299,7 @@ NICState *qemu_new_nic(NetClientInfo *info,
NICConf *conf,
const char *model,
const char *name,
+ MemReentrancyGuard *reentrancy_guard,
void *opaque)
{
NetClientState **peers = conf->peers.ncs;
--
2.41.0

View File

@ -1,105 +0,0 @@
From d58671091daf8c325a6f1cd87737d94b5fb51d12 Mon Sep 17 00:00:00 2001
From: Jon Maloy <jmaloy@redhat.com>
Date: Thu, 23 Nov 2023 11:30:46 -0500
Subject: [PATCH 2/4] net: Update MemReentrancyGuard for NIC
RH-Author: Jon Maloy <jmaloy@redhat.com>
RH-MergeRequest: 331: net: Provide MemReentrancyGuard * to qemu_new_nic()
RH-Jira: RHEL-7309
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
RH-Acked-by: Jason Wang <jasowang@redhat.com>
RH-Commit: [2/2] b116efe725dd838c2cab9bd2240112f3c6c46d6a (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2)
Jira: https://issues.redhat.com/browse/RHEL-7309
CVE: CVE-2023-3019
Upstream: Merged
commit 9050f976e447444ea6ee2ba12c9f77e4b0dc54bc
Author: Akihiko Odaki <akihiko.odaki@daynix.com>
Date: Thu Jun 1 12:18:59 2023 +0900
net: Update MemReentrancyGuard for NIC
Recently MemReentrancyGuard was added to DeviceState to record that the
device is engaging in I/O. The network device backend needs to update it
when delivering a packet to a device.
This implementation follows what bottom half does, but it does not add
a tracepoint for the case that the network device backend started
delivering a packet to a device which is already engaging in I/O. This
is because such reentrancy frequently happens for
qemu_flush_queued_packets() and is insignificant.
Fixes: CVE-2023-3019
Reported-by: Alexander Bulekov <alxndr@bu.edu>
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Acked-by: Alexander Bulekov <alxndr@bu.edu>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
include/net/net.h | 1 +
net/net.c | 14 ++++++++++++++
2 files changed, 15 insertions(+)
diff --git a/include/net/net.h b/include/net/net.h
index 1457b6c014..11d4564ea1 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -112,6 +112,7 @@ struct NetClientState {
typedef struct NICState {
NetClientState *ncs;
NICConf *conf;
+ MemReentrancyGuard *reentrancy_guard;
void *opaque;
bool peer_deleted;
} NICState;
diff --git a/net/net.c b/net/net.c
index 669e194c4b..b3008a52b7 100644
--- a/net/net.c
+++ b/net/net.c
@@ -312,6 +312,7 @@ NICState *qemu_new_nic(NetClientInfo *info,
nic = g_malloc0(info->size + sizeof(NetClientState) * queues);
nic->ncs = (void *)nic + info->size;
nic->conf = conf;
+ nic->reentrancy_guard = reentrancy_guard,
nic->opaque = opaque;
for (i = 0; i < queues; i++) {
@@ -767,6 +768,7 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
int iovcnt,
void *opaque)
{
+ MemReentrancyGuard *owned_reentrancy_guard;
NetClientState *nc = opaque;
int ret;
@@ -779,12 +781,24 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender,
return 0;
}
+ if (nc->info->type != NET_CLIENT_DRIVER_NIC ||
+ qemu_get_nic(nc)->reentrancy_guard->engaged_in_io) {
+ owned_reentrancy_guard = NULL;
+ } else {
+ owned_reentrancy_guard = qemu_get_nic(nc)->reentrancy_guard;
+ owned_reentrancy_guard->engaged_in_io = true;
+ }
+
if (nc->info->receive_iov && !(flags & QEMU_NET_PACKET_FLAG_RAW)) {
ret = nc->info->receive_iov(nc, iov, iovcnt);
} else {
ret = nc_sendv_compat(nc, iov, iovcnt, flags);
}
+ if (owned_reentrancy_guard) {
+ owned_reentrancy_guard->engaged_in_io = false;
+ }
+
if (ret == 0) {
nc->receive_disabled = 1;
}
--
2.41.0

View File

@ -1,209 +0,0 @@
From 5cdbc87ab24a8cc4cf926158ec429d43d8a45f15 Mon Sep 17 00:00:00 2001
From: Jon Maloy <jmaloy@redhat.com>
Date: Wed, 5 Jun 2024 19:56:51 -0400
Subject: [PATCH 1/5] qcow2: Don't open data_file with BDRV_O_NO_IO
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Jon Maloy <jmaloy@redhat.com>
RH-MergeRequest: 5: EMBARGOED CVE-2024-4467 for rhel-8.10.z (PRDSC)
RH-Jira: RHEL-35616
RH-CVE: CVE-2024-4467
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
RH-Commit: [1/5] 2e72d21c14d86645cf68eec78f49d5cc5d77581f
Conflicts: qcow2_do_open(): missing boolean ´open_data_file'.
We assume it to be true.
commit f9843ce5c519901654a7d8ba43ee95ce25ca13c2
Author: Kevin Wolf <kwolf@redhat.com>
Date: Thu Apr 11 15:06:01 2024 +0200
qcow2: Don't open data_file with BDRV_O_NO_IO
One use case for 'qemu-img info' is verifying that untrusted images
don't reference an unwanted external file, be it as a backing file or an
external data file. To make sure that calling 'qemu-img info' can't
already have undesired side effects with a malicious image, just don't
open the data file at all with BDRV_O_NO_IO. If nothing ever tries to do
I/O, we don't need to have it open.
This changes the output of iotests case 061, which used 'qemu-img info'
to show that opening an image with an invalid data file fails. After
this patch, it succeeds. Replace this part of the test with a qemu-io
call, but keep the final 'qemu-img info' to show that the invalid data
file is correctly displayed in the output.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
Upstream: N/A, embargoed
Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
block/qcow2.c | 87 +++++++++++++++++++++++---------------
tests/qemu-iotests/061 | 6 ++-
tests/qemu-iotests/061.out | 8 +++-
3 files changed, 62 insertions(+), 39 deletions(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index d509016756..6ee1919612 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1613,50 +1613,67 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
goto fail;
}
- /* Open external data file */
- s->data_file = bdrv_open_child(NULL, options, "data-file", bs,
- &child_of_bds, BDRV_CHILD_DATA,
- true, errp);
- if (*errp) {
- ret = -EINVAL;
- goto fail;
- }
+ if (flags & BDRV_O_NO_IO) {
+ /*
+ * Don't open the data file for 'qemu-img info' so that it can be used
+ * to verify that an untrusted qcow2 image doesn't refer to external
+ * files.
+ *
+ * Note: This still makes has_data_file() return true.
+ */
+ if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
+ s->data_file = NULL;
+ } else {
+ s->data_file = bs->file;
+ }
+ qdict_extract_subqdict(options, NULL, "data-file.");
+ qdict_del(options, "data-file");
+ } else {
+ /* Open external data file */
+ s->data_file = bdrv_open_child(NULL, options, "data-file", bs,
+ &child_of_bds, BDRV_CHILD_DATA,
+ true, errp);
+ if (*errp) {
+ ret = -EINVAL;
+ goto fail;
+ }
- if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
- if (!s->data_file && s->image_data_file) {
- s->data_file = bdrv_open_child(s->image_data_file, options,
- "data-file", bs, &child_of_bds,
- BDRV_CHILD_DATA, false, errp);
+ if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) {
+ if (!s->data_file && s->image_data_file) {
+ s->data_file = bdrv_open_child(s->image_data_file, options,
+ "data-file", bs, &child_of_bds,
+ BDRV_CHILD_DATA, false, errp);
+ if (!s->data_file) {
+ ret = -EINVAL;
+ goto fail;
+ }
+ }
if (!s->data_file) {
+ error_setg(errp, "'data-file' is required for this image");
ret = -EINVAL;
goto fail;
}
- }
- if (!s->data_file) {
- error_setg(errp, "'data-file' is required for this image");
- ret = -EINVAL;
- goto fail;
- }
- /* No data here */
- bs->file->role &= ~BDRV_CHILD_DATA;
+ /* No data here */
+ bs->file->role &= ~BDRV_CHILD_DATA;
- /* Must succeed because we have given up permissions if anything */
- bdrv_child_refresh_perms(bs, bs->file, &error_abort);
- } else {
- if (s->data_file) {
- error_setg(errp, "'data-file' can only be set for images with an "
- "external data file");
- ret = -EINVAL;
- goto fail;
- }
+ /* Must succeed because we have given up permissions if anything */
+ bdrv_child_refresh_perms(bs, bs->file, &error_abort);
+ } else {
+ if (s->data_file) {
+ error_setg(errp, "'data-file' can only be set for images with an "
+ "external data file");
+ ret = -EINVAL;
+ goto fail;
+ }
- s->data_file = bs->file;
+ s->data_file = bs->file;
- if (data_file_is_raw(bs)) {
- error_setg(errp, "data-file-raw requires a data file");
- ret = -EINVAL;
- goto fail;
+ if (data_file_is_raw(bs)) {
+ error_setg(errp, "data-file-raw requires a data file");
+ ret = -EINVAL;
+ goto fail;
+ }
}
}
diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
index 9507c223bd..6a5bd47efc 100755
--- a/tests/qemu-iotests/061
+++ b/tests/qemu-iotests/061
@@ -322,12 +322,14 @@ $QEMU_IMG amend -o "data_file=foo" "$TEST_IMG"
echo
_make_test_img -o "compat=1.1,data_file=$TEST_IMG.data" 64M
$QEMU_IMG amend -o "data_file=foo" "$TEST_IMG"
-_img_info --format-specific
+$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt
+$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io
TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts
echo
$QEMU_IMG amend -o "data_file=" --image-opts "data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG"
-_img_info --format-specific
+$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt
+$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io
TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts
echo
diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out
index 7ecbd4dea8..99b2307a23 100644
--- a/tests/qemu-iotests/061.out
+++ b/tests/qemu-iotests/061.out
@@ -545,7 +545,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
qemu-img: data-file can only be set for images that use an external data file
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 data_file=TEST_DIR/t.IMGFMT.data
-qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Could not open 'foo': No such file or directory
+qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open 'foo': No such file or directory
+read 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 64 MiB (67108864 bytes)
@@ -560,7 +562,9 @@ Format specific information:
corrupt: false
extended l2: false
-qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'data-file' is required for this image
+qemu-io: can't open device TEST_DIR/t.IMGFMT: 'data-file' is required for this image
+read 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 64 MiB (67108864 bytes)
--
2.39.3

View File

@ -1,56 +0,0 @@
From 76e75a129e59a33103aa7d1d92074ddcef556980 Mon Sep 17 00:00:00 2001
From: Thomas Huth <thuth@redhat.com>
Date: Tue, 12 Sep 2023 11:24:40 +0200
Subject: [PATCH 3/5] redhat: Update linux-headers for kvm_s390_vm_cpu_uv_feat
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 321: Enable Secure Execution Crypto Passthrough for KVM on s390x
RH-Bugzilla: 2111390
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
RH-Commit: [3/5] f1329f5ce5f66033ead7777384dcc1613cad1226
Upstream Status: rhel-only
This hunk is part of upstream commit da3c22c74a3c
("linux-headers: Update to Linux v6.6-rc1"), but since that
commit updates a lot of files and does not apply cleanly,
we only focus on the necessary change here.
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
linux-headers/asm-s390/kvm.h | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/linux-headers/asm-s390/kvm.h b/linux-headers/asm-s390/kvm.h
index f053b8304a..6706bdc5cc 100644
--- a/linux-headers/asm-s390/kvm.h
+++ b/linux-headers/asm-s390/kvm.h
@@ -158,6 +158,22 @@ struct kvm_s390_vm_cpu_subfunc {
__u8 reserved[1728];
};
+#define KVM_S390_VM_CPU_PROCESSOR_UV_FEAT_GUEST 6
+#define KVM_S390_VM_CPU_MACHINE_UV_FEAT_GUEST 7
+
+#define KVM_S390_VM_CPU_UV_FEAT_NR_BITS 64
+struct kvm_s390_vm_cpu_uv_feat {
+ union {
+ struct {
+ __u64 : 4;
+ __u64 ap : 1; /* bit 4 */
+ __u64 ap_intr : 1; /* bit 5 */
+ __u64 : 58;
+ };
+ __u64 feat;
+ };
+};
+
/* kvm attributes for crypto */
#define KVM_S390_VM_CRYPTO_ENABLE_AES_KW 0
#define KVM_S390_VM_CRYPTO_ENABLE_DEA_KW 1
--
2.41.0

View File

@ -1,44 +0,0 @@
From eb60b6cab9550a62f0b20a9e6d69547d651e3020 Mon Sep 17 00:00:00 2001
From: Janosch Frank <frankja@linux.ibm.com>
Date: Wed, 23 Aug 2023 16:22:15 +0200
Subject: [PATCH 1/5] s390x/ap: fix missing subsystem reset registration
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 321: Enable Secure Execution Crypto Passthrough for KVM on s390x
RH-Bugzilla: 2111390
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
RH-Commit: [1/5] 4ebe81bb6cc4fc137ca4ebc9c0cebdedc421cc91
A subsystem reset contains a reset of AP resources which has been
missing. Adding the AP bridge to the list of device types that need
reset fixes this issue.
Reviewed-by: Jason J. Herne <jjherne@linux.ibm.com>
Reviewed-by: Tony Krowiak <akrowiak@linux.ibm.com>
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
Fixes: a51b3153 ("s390x/ap: base Adjunct Processor (AP) object model")
Message-ID: <20230823142219.1046522-2-seiden@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
(cherry picked from commit 297ec01f0b9864ea8209ca0ddc6643b4c0574bdb)
---
hw/s390x/s390-virtio-ccw.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 4a7cd21cac..412d73715a 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -100,6 +100,7 @@ static const char *const reset_dev_types[] = {
"s390-flic",
"diag288",
TYPE_S390_PCI_HOST_BRIDGE,
+ TYPE_AP_BRIDGE,
};
static void subsystem_reset(void)
--
2.41.0

View File

@ -1,68 +0,0 @@
From 05b145a8d5b1c2f796069cdd81826c00cf7c983e Mon Sep 17 00:00:00 2001
From: Janosch Frank <frankja@linux.ibm.com>
Date: Fri, 1 Sep 2023 11:48:51 +0000
Subject: [PATCH 2/5] s390x: do a subsystem reset before the unprotect on
reboot
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 321: Enable Secure Execution Crypto Passthrough for KVM on s390x
RH-Bugzilla: 2111390
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
RH-Commit: [2/5] ea430d236e1a20ddad7095d2e6d10f741f9a1907
Bound APQNs have to be reset before tearing down the secure config via
s390_machine_unprotect(). Otherwise the Ultravisor will return a error
code.
So let's do a subsystem_reset() which includes a AP reset before the
unprotect call. We'll do a full device_reset() afterwards which will
reset some devices twice. That's ok since we can't move the
device_reset() before the unprotect as it includes a CPU clear reset
which the Ultravisor does not expect at that point in time.
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
Message-ID: <20230901114851.154357-1-frankja@linux.ibm.com>
Tested-by: Viktor Mihajlovski <mihajlov@linux.ibm.com>
Acked-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
(cherry picked from commit ef1535901a07f2e49fa25c8bcee7f0b73801d824)
Conflicts:
hw/s390x/s390-virtio-ccw.c
(contextual conflict due to missing commit 7966d70f6f6b)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/s390x/s390-virtio-ccw.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 412d73715a..17146469ee 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -430,10 +430,20 @@ static void s390_machine_reset(MachineState *machine)
switch (reset_type) {
case S390_RESET_EXTERNAL:
case S390_RESET_REIPL:
+ /*
+ * Reset the subsystem which includes a AP reset. If a PV
+ * guest had APQNs attached the AP reset is a prerequisite to
+ * unprotecting since the UV checks if all APQNs are reset.
+ */
+ subsystem_reset();
if (s390_is_pv()) {
s390_machine_unprotect(ms);
}
+ /*
+ * Device reset includes CPU clear resets so this has to be
+ * done AFTER the unprotect call above.
+ */
qemu_devices_reset();
s390_crypto_reset();
--
2.41.0

View File

@ -1,106 +0,0 @@
From 52ad0cc8a82f7a4c3581146fb4d2046898163c4e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= <clg@redhat.com>
Date: Tue, 23 Jan 2024 13:59:24 +0100
Subject: [PATCH 1/3] s390x/pci: avoid double enable/disable of aif
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Cédric Le Goater <clg@redhat.com>
RH-MergeRequest: 349: s390x: Fix reset ordering of passthrough ISM devices
RH-Jira: RHEL-22411
RH-Acked-by: Thomas Huth <thuth@redhat.com>
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
RH-Commit: [1/3] 450e4ca607d801bce93415994250374d70fb72f6
JIRA: https://issues.redhat.com/browse/RHEL-22411
commit 07b2c8e034d80ff92e202405c494d2ff80fcf848
Author: Matthew Rosato <mjrosato@linux.ibm.com>
Date: Thu Jan 18 13:51:49 2024 -0500
s390x/pci: avoid double enable/disable of aif
Use a flag to keep track of whether AIF is currently enabled. This can be
used to avoid enabling/disabling AIF multiple times as well as to determine
whether or not it should be disabled during reset processing.
Fixes: d0bc7091c2 ("s390x/pci: enable adapter event notification for interpreted devices")
Reported-by: Cédric Le Goater <clg@redhat.com>
Reviewed-by: Eric Farman <farman@linux.ibm.com>
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
Message-ID: <20240118185151.265329-2-mjrosato@linux.ibm.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Cédric Le Goater <clg@redhat.com>
---
hw/s390x/s390-pci-kvm.c | 25 +++++++++++++++++++++++--
include/hw/s390x/s390-pci-bus.h | 1 +
2 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/hw/s390x/s390-pci-kvm.c b/hw/s390x/s390-pci-kvm.c
index ff41e4106d..1ee510436c 100644
--- a/hw/s390x/s390-pci-kvm.c
+++ b/hw/s390x/s390-pci-kvm.c
@@ -27,6 +27,7 @@ bool s390_pci_kvm_interp_allowed(void)
int s390_pci_kvm_aif_enable(S390PCIBusDevice *pbdev, ZpciFib *fib, bool assist)
{
+ int rc;
struct kvm_s390_zpci_op args = {
.fh = pbdev->fh,
.op = KVM_S390_ZPCIOP_REG_AEN,
@@ -38,15 +39,35 @@ int s390_pci_kvm_aif_enable(S390PCIBusDevice *pbdev, ZpciFib *fib, bool assist)
.u.reg_aen.flags = (assist) ? 0 : KVM_S390_ZPCIOP_REGAEN_HOST
};
- return kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, &args);
+ if (pbdev->aif) {
+ return -EINVAL;
+ }
+
+ rc = kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, &args);
+ if (rc == 0) {
+ pbdev->aif = true;
+ }
+
+ return rc;
}
int s390_pci_kvm_aif_disable(S390PCIBusDevice *pbdev)
{
+ int rc;
+
struct kvm_s390_zpci_op args = {
.fh = pbdev->fh,
.op = KVM_S390_ZPCIOP_DEREG_AEN
};
- return kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, &args);
+ if (!pbdev->aif) {
+ return -EINVAL;
+ }
+
+ rc = kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, &args);
+ if (rc == 0) {
+ pbdev->aif = false;
+ }
+
+ return rc;
}
diff --git a/include/hw/s390x/s390-pci-bus.h b/include/hw/s390x/s390-pci-bus.h
index e0a9f9385b..7a658f5e30 100644
--- a/include/hw/s390x/s390-pci-bus.h
+++ b/include/hw/s390x/s390-pci-bus.h
@@ -361,6 +361,7 @@ struct S390PCIBusDevice {
bool unplug_requested;
bool interp;
bool forwarding_assist;
+ bool aif;
QTAILQ_ENTRY(S390PCIBusDevice) link;
};
--
2.41.0

View File

@ -1,137 +0,0 @@
From dda71c431be22772f3241af45b62737c988e85d4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= <clg@redhat.com>
Date: Tue, 23 Jan 2024 13:59:24 +0100
Subject: [PATCH 3/3] s390x/pci: drive ISM reset from subsystem reset
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Cédric Le Goater <clg@redhat.com>
RH-MergeRequest: 349: s390x: Fix reset ordering of passthrough ISM devices
RH-Jira: RHEL-22411
RH-Acked-by: Thomas Huth <thuth@redhat.com>
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
RH-Commit: [3/3] 42e89595dd5e24538a2d3f075391b4534497eece
JIRA: https://issues.redhat.com/browse/RHEL-22411
commit 68c691ca99a2538d6a53a70ce8a9ce06ee307ff1
Author: Matthew Rosato <mjrosato@linux.ibm.com>
Date: Thu Jan 18 13:51:51 2024 -0500
s390x/pci: drive ISM reset from subsystem reset
ISM devices are sensitive to manipulation of the IOMMU, so the ISM device
needs to be reset before the vfio-pci device is reset (triggering a full
UNMAP). In order to ensure this occurs, trigger ISM device resets from
subsystem_reset before triggering the PCI bus reset (which will also
trigger vfio-pci reset). This only needs to be done for ISM devices
which were enabled for use by the guest.
Further, ensure that AIF is disabled as part of the reset event.
Fixes: ef1535901a ("s390x: do a subsystem reset before the unprotect on reboot")
Fixes: 03451953c7 ("s390x/pci: reset ISM passthrough devices on shutdown and system reset")
Reported-by: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
Message-ID: <20240118185151.265329-4-mjrosato@linux.ibm.com>
Reviewed-by: Eric Farman <farman@linux.ibm.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Cédric Le Goater <clg@redhat.com>
---
hw/s390x/s390-pci-bus.c | 26 +++++++++++++++++---------
hw/s390x/s390-virtio-ccw.c | 8 ++++++++
include/hw/s390x/s390-pci-bus.h | 1 +
3 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index 2d92848b0f..a8953693b9 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -160,20 +160,12 @@ static void s390_pci_shutdown_notifier(Notifier *n, void *opaque)
pci_device_reset(pbdev->pdev);
}
-static void s390_pci_reset_cb(void *opaque)
-{
- S390PCIBusDevice *pbdev = opaque;
-
- pci_device_reset(pbdev->pdev);
-}
-
static void s390_pci_perform_unplug(S390PCIBusDevice *pbdev)
{
HotplugHandler *hotplug_ctrl;
if (pbdev->pft == ZPCI_PFT_ISM) {
notifier_remove(&pbdev->shutdown_notifier);
- qemu_unregister_reset(s390_pci_reset_cb, pbdev);
}
/* Unplug the PCI device */
@@ -1137,7 +1129,6 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
if (pbdev->pft == ZPCI_PFT_ISM) {
pbdev->shutdown_notifier.notify = s390_pci_shutdown_notifier;
qemu_register_shutdown_notifier(&pbdev->shutdown_notifier);
- qemu_register_reset(s390_pci_reset_cb, pbdev);
}
} else {
pbdev->fh |= FH_SHM_EMUL;
@@ -1284,6 +1275,23 @@ static void s390_pci_enumerate_bridge(PCIBus *bus, PCIDevice *pdev,
pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, s->bus_no, 1);
}
+void s390_pci_ism_reset(void)
+{
+ S390pciState *s = s390_get_phb();
+
+ S390PCIBusDevice *pbdev, *next;
+
+ /* Trigger reset event for each passthrough ISM device currently in-use */
+ QTAILQ_FOREACH_SAFE(pbdev, &s->zpci_devs, link, next) {
+ if (pbdev->interp && pbdev->pft == ZPCI_PFT_ISM &&
+ pbdev->fh & FH_MASK_ENABLE) {
+ s390_pci_kvm_aif_disable(pbdev);
+
+ pci_device_reset(pbdev->pdev);
+ }
+ }
+}
+
static void s390_pcihost_reset(DeviceState *dev)
{
S390pciState *s = S390_PCI_HOST_BRIDGE(dev);
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 94434c3bb1..51e5b39888 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -108,6 +108,14 @@ static void subsystem_reset(void)
DeviceState *dev;
int i;
+ /*
+ * ISM firmware is sensitive to unexpected changes to the IOMMU, which can
+ * occur during reset of the vfio-pci device (unmap of entire aperture).
+ * Ensure any passthrough ISM devices are reset now, while CPUs are paused
+ * but before vfio-pci cleanup occurs.
+ */
+ s390_pci_ism_reset();
+
for (i = 0; i < ARRAY_SIZE(reset_dev_types); i++) {
dev = DEVICE(object_resolve_path_type("", reset_dev_types[i], NULL));
if (dev) {
diff --git a/include/hw/s390x/s390-pci-bus.h b/include/hw/s390x/s390-pci-bus.h
index 7a658f5e30..2bfad5563a 100644
--- a/include/hw/s390x/s390-pci-bus.h
+++ b/include/hw/s390x/s390-pci-bus.h
@@ -401,5 +401,6 @@ S390PCIBusDevice *s390_pci_find_dev_by_target(S390pciState *s,
const char *target);
S390PCIBusDevice *s390_pci_find_next_avail_dev(S390pciState *s,
S390PCIBusDevice *pbdev);
+void s390_pci_ism_reset(void);
#endif
--
2.41.0

View File

@ -1,71 +0,0 @@
From fe70e87ef8d2f7e538867052e06012051919083f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= <clg@redhat.com>
Date: Tue, 23 Jan 2024 13:59:24 +0100
Subject: [PATCH 2/3] s390x/pci: refresh fh before disabling aif
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Cédric Le Goater <clg@redhat.com>
RH-MergeRequest: 349: s390x: Fix reset ordering of passthrough ISM devices
RH-Jira: RHEL-22411
RH-Acked-by: Thomas Huth <thuth@redhat.com>
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
RH-Commit: [2/3] 4a7d3fccdac508253bd7e5765973a08482022edb
JIRA: https://issues.redhat.com/browse/RHEL-22411
commit 30e35258e25c75c9d799c34fd89afcafffb37084
Author: Matthew Rosato <mjrosato@linux.ibm.com>
Date: Thu Jan 18 13:51:50 2024 -0500
s390x/pci: refresh fh before disabling aif
Typically we refresh the host fh during CLP enable, however it's possible
that the device goes through multiple reset events before the guest
performs another CLP enable. Let's handle this for now by refreshing the
host handle from vfio before disabling aif.
Fixes: 03451953c7 ("s390x/pci: reset ISM passthrough devices on shutdown and system reset")
Reported-by: Cédric Le Goater <clg@redhat.com>
Reviewed-by: Eric Farman <farman@linux.ibm.com>
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
Message-ID: <20240118185151.265329-3-mjrosato@linux.ibm.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Cédric Le Goater <clg@redhat.com>
---
hw/s390x/s390-pci-kvm.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/hw/s390x/s390-pci-kvm.c b/hw/s390x/s390-pci-kvm.c
index 1ee510436c..9eef4fc3ec 100644
--- a/hw/s390x/s390-pci-kvm.c
+++ b/hw/s390x/s390-pci-kvm.c
@@ -18,6 +18,7 @@
#include "hw/s390x/s390-pci-bus.h"
#include "hw/s390x/s390-pci-kvm.h"
#include "hw/s390x/s390-pci-inst.h"
+#include "hw/s390x/s390-pci-vfio.h"
#include "cpu_models.h"
bool s390_pci_kvm_interp_allowed(void)
@@ -64,6 +65,14 @@ int s390_pci_kvm_aif_disable(S390PCIBusDevice *pbdev)
return -EINVAL;
}
+ /*
+ * The device may have already been reset but we still want to relinquish
+ * the guest ISC, so always be sure to use an up-to-date host fh.
+ */
+ if (!s390_pci_get_host_fh(pbdev, &args.fh)) {
+ return -EPERM;
+ }
+
rc = kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, &args);
if (rc == 0) {
pbdev->aif = false;
--
2.41.0

View File

@ -1,51 +0,0 @@
From 52969f8a75ac7ba115e044cd94208984c18eee41 Mon Sep 17 00:00:00 2001
From: Thomas Huth <thuth@redhat.com>
Date: Mon, 15 Jan 2024 14:00:04 +0100
Subject: [PATCH 2/5] s390x/pv: remove semicolon from macro definition
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 348: s390x: Provide some more useful information if decryption of a PV image fails
RH-Jira: RHEL-18214
RH-Acked-by: Jon Maloy <jmaloy@redhat.com>
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
RH-Commit: [2/5] 52a04c945a584746ff30bed516ad97bab75ac821
JIRA: https://issues.redhat.com/browse/RHEL-18214
commit 36c182bbe680d64f0868522bb9256b5b8eccf280
Author: Claudio Imbrenda <imbrenda@linux.ibm.com>
Date: Mon Oct 10 17:10:41 2022 +0200
s390x/pv: remove semicolon from macro definition
Remove spurious semicolon at the end of the macro s390_pv_cmd
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Acked-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <20221010151041.89071-1-imbrenda@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/s390x/pv.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/s390x/pv.c b/hw/s390x/pv.c
index 749e5db1ce..8a1c71436b 100644
--- a/hw/s390x/pv.c
+++ b/hw/s390x/pv.c
@@ -51,7 +51,7 @@ static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data)
* This macro lets us pass the command as a string to the function so
* we can print it on an error.
*/
-#define s390_pv_cmd(cmd, data) __s390_pv_cmd(cmd, #cmd, data);
+#define s390_pv_cmd(cmd, data) __s390_pv_cmd(cmd, #cmd, data)
#define s390_pv_cmd_exit(cmd, data) \
{ \
int rc; \
--
2.41.0

View File

@ -1,194 +0,0 @@
From 885d04faf5edb787341aab6917fd2de743e029ac Mon Sep 17 00:00:00 2001
From: Steffen Eiden <seiden@linux.ibm.com>
Date: Wed, 23 Aug 2023 16:22:19 +0200
Subject: [PATCH 5/5] target/s390x: AP-passthrough for PV guests
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 321: Enable Secure Execution Crypto Passthrough for KVM on s390x
RH-Bugzilla: 2111390
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
RH-Commit: [5/5] 9bf3dfd78fb030a22db7bb756a2cb7f54a0a8d82
Enabling AP-passthrough(AP-pt) for PV-guest by using the new CPU
features for PV-AP-pt of KVM.
As usual QEMU first checks which CPU features are available and then
sets them if available and selected by user. An additional check is done
to verify that PV-AP can only be enabled if "regular" AP-pt is enabled
as well. Note that KVM itself does not enforce this restriction.
Reviewed-by: Michael Mueller <mimu@linux.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Message-ID: <20230823142219.1046522-6-seiden@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
(cherry picked from commit 5ac951519c23d9eaf7dc9e2dcbcbc7d9a745ffe7)
Conflicts:
target/s390x/gen-features.c
(simple contextual conflict due to missing S390_FEAT_PAIE)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
target/s390x/cpu_features.h | 1 +
target/s390x/cpu_features_def.h.inc | 4 ++
target/s390x/cpu_models.c | 2 +
target/s390x/gen-features.c | 2 +
target/s390x/kvm/kvm.c | 70 +++++++++++++++++++++++++++++
5 files changed, 79 insertions(+)
diff --git a/target/s390x/cpu_features.h b/target/s390x/cpu_features.h
index 87463f064d..a9bd68a2e1 100644
--- a/target/s390x/cpu_features.h
+++ b/target/s390x/cpu_features.h
@@ -43,6 +43,7 @@ typedef enum {
S390_FEAT_TYPE_KDSA,
S390_FEAT_TYPE_SORTL,
S390_FEAT_TYPE_DFLTCC,
+ S390_FEAT_TYPE_UV_FEAT_GUEST,
} S390FeatType;
/* Definition of a CPU feature */
diff --git a/target/s390x/cpu_features_def.h.inc b/target/s390x/cpu_features_def.h.inc
index e86662bb3b..aa1f51f2a8 100644
--- a/target/s390x/cpu_features_def.h.inc
+++ b/target/s390x/cpu_features_def.h.inc
@@ -378,3 +378,7 @@ DEF_FEAT(DEFLATE_GHDT, "dfltcc-gdht", DFLTCC, 1, "DFLTCC GDHT")
DEF_FEAT(DEFLATE_CMPR, "dfltcc-cmpr", DFLTCC, 2, "DFLTCC CMPR")
DEF_FEAT(DEFLATE_XPND, "dfltcc-xpnd", DFLTCC, 4, "DFLTCC XPND")
DEF_FEAT(DEFLATE_F0, "dfltcc-f0", DFLTCC, 192, "DFLTCC format 0 parameter-block")
+
+/* Features exposed via the UV-CALL instruction */
+DEF_FEAT(UV_FEAT_AP, "appv", UV_FEAT_GUEST, 4, "AP instructions installed for secure guests")
+DEF_FEAT(UV_FEAT_AP_INTR, "appvi", UV_FEAT_GUEST, 5, "AP instructions interruption support for secure guests")
diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c
index 11e06cc51f..454485e706 100644
--- a/target/s390x/cpu_models.c
+++ b/target/s390x/cpu_models.c
@@ -467,6 +467,8 @@ static void check_consistency(const S390CPUModel *model)
{ S390_FEAT_DIAG_318, S390_FEAT_EXTENDED_LENGTH_SCCB },
{ S390_FEAT_NNPA, S390_FEAT_VECTOR },
{ S390_FEAT_RDP, S390_FEAT_LOCAL_TLB_CLEARING },
+ { S390_FEAT_UV_FEAT_AP, S390_FEAT_AP },
+ { S390_FEAT_UV_FEAT_AP_INTR, S390_FEAT_UV_FEAT_AP },
};
int i;
diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c
index 7cb1a6ec10..b789288c82 100644
--- a/target/s390x/gen-features.c
+++ b/target/s390x/gen-features.c
@@ -575,6 +575,8 @@ static uint16_t full_GEN16_GA1[] = {
S390_FEAT_BEAR_ENH,
S390_FEAT_RDP,
S390_FEAT_PAI,
+ S390_FEAT_UV_FEAT_AP,
+ S390_FEAT_UV_FEAT_AP_INTR,
};
diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c
index eb8ca4c780..a963866ef4 100644
--- a/target/s390x/kvm/kvm.c
+++ b/target/s390x/kvm/kvm.c
@@ -2308,6 +2308,42 @@ static bool ap_enabled(const S390FeatBitmap features)
return test_bit(S390_FEAT_AP, features);
}
+static bool uv_feat_supported(void)
+{
+ return kvm_vm_check_attr(kvm_state, KVM_S390_VM_CPU_MODEL,
+ KVM_S390_VM_CPU_PROCESSOR_UV_FEAT_GUEST);
+}
+
+static int query_uv_feat_guest(S390FeatBitmap features)
+{
+ struct kvm_s390_vm_cpu_uv_feat prop = {};
+ struct kvm_device_attr attr = {
+ .group = KVM_S390_VM_CPU_MODEL,
+ .attr = KVM_S390_VM_CPU_MACHINE_UV_FEAT_GUEST,
+ .addr = (uint64_t) &prop,
+ };
+ int rc;
+
+ /* AP support check is currently the only user of the UV feature test */
+ if (!(uv_feat_supported() && ap_available())) {
+ return 0;
+ }
+
+ rc = kvm_vm_ioctl(kvm_state, KVM_GET_DEVICE_ATTR, &attr);
+ if (rc) {
+ return rc;
+ }
+
+ if (prop.ap) {
+ set_bit(S390_FEAT_UV_FEAT_AP, features);
+ }
+ if (prop.ap_intr) {
+ set_bit(S390_FEAT_UV_FEAT_AP_INTR, features);
+ }
+
+ return 0;
+}
+
static int kvm_to_feat[][2] = {
{ KVM_S390_VM_CPU_FEAT_ESOP, S390_FEAT_ESOP },
{ KVM_S390_VM_CPU_FEAT_SIEF2, S390_FEAT_SIE_F2 },
@@ -2502,11 +2538,38 @@ void kvm_s390_get_host_cpu_model(S390CPUModel *model, Error **errp)
set_bit(S390_FEAT_DIAG_318, model->features);
}
+ /* Test for Ultravisor features that influence secure guest behavior */
+ query_uv_feat_guest(model->features);
+
/* strip of features that are not part of the maximum model */
bitmap_and(model->features, model->features, model->def->full_feat,
S390_FEAT_MAX);
}
+static int configure_uv_feat_guest(const S390FeatBitmap features)
+{
+ struct kvm_s390_vm_cpu_uv_feat uv_feat = {};
+ struct kvm_device_attr attribute = {
+ .group = KVM_S390_VM_CPU_MODEL,
+ .attr = KVM_S390_VM_CPU_PROCESSOR_UV_FEAT_GUEST,
+ .addr = (__u64) &uv_feat,
+ };
+
+ /* AP support check is currently the only user of the UV feature test */
+ if (!(uv_feat_supported() && ap_enabled(features))) {
+ return 0;
+ }
+
+ if (test_bit(S390_FEAT_UV_FEAT_AP, features)) {
+ uv_feat.ap = 1;
+ }
+ if (test_bit(S390_FEAT_UV_FEAT_AP_INTR, features)) {
+ uv_feat.ap_intr = 1;
+ }
+
+ return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attribute);
+}
+
static void kvm_s390_configure_apie(bool interpret)
{
uint64_t attr = interpret ? KVM_S390_VM_CRYPTO_ENABLE_APIE :
@@ -2578,6 +2641,13 @@ void kvm_s390_apply_cpu_model(const S390CPUModel *model, Error **errp)
if (ap_enabled(model->features)) {
kvm_s390_configure_apie(true);
}
+
+ /* configure UV-features for the guest indicated via query / test_bit */
+ rc = configure_uv_feat_guest(model->features);
+ if (rc) {
+ error_setg(errp, "KVM: Error configuring CPU UV features %d", rc);
+ return;
+ }
}
void kvm_s390_restart_interrupt(S390CPU *cpu)
--
2.41.0

View File

@ -1,84 +0,0 @@
From 4aa08999f8502e9d6869352db89081319c2d7119 Mon Sep 17 00:00:00 2001
From: Thomas Huth <thuth@redhat.com>
Date: Fri, 17 Nov 2023 11:32:37 +0100
Subject: [PATCH 3/3] target/s390x/arch_dump: Add arch cleanup function for PV
dumps
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 323: Fix problem that secure execution guest might remain in "paused" state after failed dump
RH-Jira: RHEL-16696
RH-Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com>
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
RH-Commit: [3/3] 0bb389c9339b95f7ff6dc284526b0c8d5ef736b4
JIRA: https://issues.redhat.com/browse/RHEL-16696
commit d12a91e0baafce7b1cbacff7cf9339eeb0011732
Author: Janosch Frank <frankja@linux.ibm.com>
Date: Thu Nov 9 12:04:43 2023 +0000
target/s390x/arch_dump: Add arch cleanup function for PV dumps
PV dumps block vcpu runs until dump end is reached. If there's an
error between PV dump init and PV dump end the vm will never be able
to run again. One example of such an error is insufficient disk space
for the dump file.
Let's add a cleanup function that tries to do a dump end. The dump
completion data is discarded but there's no point in writing it to a
file anyway if there's a possibility that other PV dump data is
missing.
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20231109120443.185979-4-frankja@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
target/s390x/arch_dump.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/target/s390x/arch_dump.c b/target/s390x/arch_dump.c
index 7cdd4b7167..3b1f178dc3 100644
--- a/target/s390x/arch_dump.c
+++ b/target/s390x/arch_dump.c
@@ -439,6 +439,22 @@ static int arch_sections_write(DumpState *s, uint8_t *buff)
return 0;
}
+static void arch_cleanup(DumpState *s)
+{
+ g_autofree uint8_t *buff = NULL;
+ int rc;
+
+ if (!pv_dump_initialized) {
+ return;
+ }
+
+ buff = g_malloc(kvm_s390_pv_dmp_get_size_completion_data());
+ rc = kvm_s390_dump_completion_data(buff);
+ if (!rc) {
+ pv_dump_initialized = false;
+ }
+}
+
int cpu_get_dump_info(ArchDumpInfo *info,
const struct GuestPhysBlockList *guest_phys_blocks)
{
@@ -454,6 +470,7 @@ int cpu_get_dump_info(ArchDumpInfo *info,
info->arch_sections_add_fn = *arch_sections_add;
info->arch_sections_write_hdr_fn = *arch_sections_write_hdr;
info->arch_sections_write_fn = *arch_sections_write;
+ info->arch_cleanup_fn = *arch_cleanup;
}
return 0;
}
--
2.39.3

View File

@ -1,56 +0,0 @@
From f647258696cbdce78316b2d9ae513f9ae6f4a0b5 Mon Sep 17 00:00:00 2001
From: Thomas Huth <thuth@redhat.com>
Date: Fri, 17 Nov 2023 11:32:37 +0100
Subject: [PATCH 1/3] target/s390x/dump: Remove unneeded dump info function
pointer init
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 323: Fix problem that secure execution guest might remain in "paused" state after failed dump
RH-Jira: RHEL-16696
RH-Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com>
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
RH-Commit: [1/3] e3b0697ec76274f778fc523efb72f0cbca25cd77
JIRA: https://issues.redhat.com/browse/RHEL-16696
commit 816644b1219900875f47d7adf9bfb283f1b29aa0
Author: Janosch Frank <frankja@linux.ibm.com>
Date: Thu Nov 9 12:04:41 2023 +0000
target/s390x/dump: Remove unneeded dump info function pointer init
dump_state_prepare() now sets the function pointers to NULL so we only
need to touch them if we're going to use them.
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-ID: <20231109120443.185979-2-frankja@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
target/s390x/arch_dump.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/target/s390x/arch_dump.c b/target/s390x/arch_dump.c
index a7c44ba49d..7cdd4b7167 100644
--- a/target/s390x/arch_dump.c
+++ b/target/s390x/arch_dump.c
@@ -454,10 +454,6 @@ int cpu_get_dump_info(ArchDumpInfo *info,
info->arch_sections_add_fn = *arch_sections_add;
info->arch_sections_write_hdr_fn = *arch_sections_write_hdr;
info->arch_sections_write_fn = *arch_sections_write;
- } else {
- info->arch_sections_add_fn = NULL;
- info->arch_sections_write_hdr_fn = NULL;
- info->arch_sections_write_fn = NULL;
}
return 0;
}
--
2.39.3

View File

@ -1,111 +0,0 @@
From 57bcc768ac7d0614472e60cc2833b74a2a198d29 Mon Sep 17 00:00:00 2001
From: Steffen Eiden <seiden@linux.ibm.com>
Date: Wed, 23 Aug 2023 16:22:18 +0200
Subject: [PATCH 4/5] target/s390x/kvm: Refactor AP functionalities
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 321: Enable Secure Execution Crypto Passthrough for KVM on s390x
RH-Bugzilla: 2111390
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
RH-Commit: [4/5] 8ab2f8766931fb65a391aab590d0ccabd8ba8909
kvm_s390_set_attr() is a misleading name as it only sets attributes for
the KVM_S390_VM_CRYPTO group. Therefore, rename it to
kvm_s390_set_crypto_attr().
Add new functions ap_available() and ap_enabled() to avoid code
duplication later.
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Michael Mueller <mimu@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Message-ID: <20230823142219.1046522-5-seiden@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
(cherry picked from commit 354383c12294f2ee510204cfdc5aaed9f0c42171)
---
target/s390x/kvm/kvm.c | 24 +++++++++++++++++-------
1 file changed, 17 insertions(+), 7 deletions(-)
diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c
index 8d36c377b5..eb8ca4c780 100644
--- a/target/s390x/kvm/kvm.c
+++ b/target/s390x/kvm/kvm.c
@@ -251,7 +251,7 @@ static void kvm_s390_enable_cmma(void)
trace_kvm_enable_cmma(rc);
}
-static void kvm_s390_set_attr(uint64_t attr)
+static void kvm_s390_set_crypto_attr(uint64_t attr)
{
struct kvm_device_attr attribute = {
.group = KVM_S390_VM_CRYPTO,
@@ -276,7 +276,7 @@ static void kvm_s390_init_aes_kw(void)
}
if (kvm_vm_check_attr(kvm_state, KVM_S390_VM_CRYPTO, attr)) {
- kvm_s390_set_attr(attr);
+ kvm_s390_set_crypto_attr(attr);
}
}
@@ -290,7 +290,7 @@ static void kvm_s390_init_dea_kw(void)
}
if (kvm_vm_check_attr(kvm_state, KVM_S390_VM_CRYPTO, attr)) {
- kvm_s390_set_attr(attr);
+ kvm_s390_set_crypto_attr(attr);
}
}
@@ -2297,6 +2297,17 @@ static int configure_cpu_subfunc(const S390FeatBitmap features)
return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr);
}
+static bool ap_available(void)
+{
+ return kvm_vm_check_attr(kvm_state, KVM_S390_VM_CRYPTO,
+ KVM_S390_VM_CRYPTO_ENABLE_APIE);
+}
+
+static bool ap_enabled(const S390FeatBitmap features)
+{
+ return test_bit(S390_FEAT_AP, features);
+}
+
static int kvm_to_feat[][2] = {
{ KVM_S390_VM_CPU_FEAT_ESOP, S390_FEAT_ESOP },
{ KVM_S390_VM_CPU_FEAT_SIEF2, S390_FEAT_SIE_F2 },
@@ -2476,8 +2487,7 @@ void kvm_s390_get_host_cpu_model(S390CPUModel *model, Error **errp)
return;
}
/* for now, we can only provide the AP feature with HW support */
- if (kvm_vm_check_attr(kvm_state, KVM_S390_VM_CRYPTO,
- KVM_S390_VM_CRYPTO_ENABLE_APIE)) {
+ if (ap_available()) {
set_bit(S390_FEAT_AP, model->features);
}
@@ -2503,7 +2513,7 @@ static void kvm_s390_configure_apie(bool interpret)
KVM_S390_VM_CRYPTO_DISABLE_APIE;
if (kvm_vm_check_attr(kvm_state, KVM_S390_VM_CRYPTO, attr)) {
- kvm_s390_set_attr(attr);
+ kvm_s390_set_crypto_attr(attr);
}
}
@@ -2565,7 +2575,7 @@ void kvm_s390_apply_cpu_model(const S390CPUModel *model, Error **errp)
kvm_s390_enable_cmma();
}
- if (test_bit(S390_FEAT_AP, model->features)) {
+ if (ap_enabled(model->features)) {
kvm_s390_configure_apie(true);
}
}
--
2.41.0

View File

@ -1,207 +0,0 @@
From c1273f9e38f81f912cd2bd1dd4a43f9652766f76 Mon Sep 17 00:00:00 2001
From: Thomas Huth <thuth@redhat.com>
Date: Wed, 10 Jan 2024 15:29:16 +0100
Subject: [PATCH 5/5] target/s390x/kvm/pv: Provide some more useful information
if decryption fails
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Thomas Huth <thuth@redhat.com>
RH-MergeRequest: 348: s390x: Provide some more useful information if decryption of a PV image fails
RH-Jira: RHEL-18214
RH-Acked-by: Jon Maloy <jmaloy@redhat.com>
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
RH-Commit: [5/5] 087acaecfaa5921b409beb212123214fa79fe50c
JIRA: https://issues.redhat.com/browse/RHEL-18214
commit 7af51621b16ae86646cc2dc9dee30de8176ff761
Author: Thomas Huth <thuth@redhat.com>
Date: Wed Jan 10 15:29:16 2024 +0100
target/s390x/kvm/pv: Provide some more useful information if decryption fails
It's a common scenario to copy guest images from one host to another
to run the guest on the other machine. This (of course) does not work
with "secure execution" guests since they are encrypted with one certain
host key. However, if you still (accidentally) do it, you only get a
very user-unfriendly error message that looks like this:
qemu-system-s390x: KVM PV command 2 (KVM_PV_SET_SEC_PARMS) failed:
header rc 108 rrc 5 IOCTL rc: -22
Let's provide at least a somewhat nicer hint to the users so that they
are able to figure out what might have gone wrong.
Message-ID: <20240110142916.850605-1-thuth@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Conflicts:
target/s390x/kvm/pv.c
target/s390x/kvm/pv.h
(contextual conflict due to missing async-teardown in RHEL8)
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
hw/s390x/ipl.c | 5 ++---
hw/s390x/ipl.h | 2 +-
hw/s390x/s390-virtio-ccw.c | 5 ++++-
target/s390x/kvm/pv.c | 25 ++++++++++++++++++++-----
target/s390x/kvm/pv.h | 5 +++--
5 files changed, 30 insertions(+), 12 deletions(-)
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index c25e247426..c6cefdd3fe 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -709,7 +709,7 @@ static void s390_ipl_prepare_qipl(S390CPU *cpu)
cpu_physical_memory_unmap(addr, len, 1, len);
}
-int s390_ipl_prepare_pv_header(void)
+int s390_ipl_prepare_pv_header(Error **errp)
{
IplParameterBlock *ipib = s390_ipl_get_iplb_pv();
IPLBlockPV *ipib_pv = &ipib->pv;
@@ -718,8 +718,7 @@ int s390_ipl_prepare_pv_header(void)
cpu_physical_memory_read(ipib_pv->pv_header_addr, hdr,
ipib_pv->pv_header_len);
- rc = s390_pv_set_sec_parms((uintptr_t)hdr,
- ipib_pv->pv_header_len);
+ rc = s390_pv_set_sec_parms((uintptr_t)hdr, ipib_pv->pv_header_len, errp);
g_free(hdr);
return rc;
}
diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h
index dfc6dfd89c..f9cce33330 100644
--- a/hw/s390x/ipl.h
+++ b/hw/s390x/ipl.h
@@ -107,7 +107,7 @@ typedef union IplParameterBlock IplParameterBlock;
int s390_ipl_set_loadparm(uint8_t *loadparm);
void s390_ipl_update_diag308(IplParameterBlock *iplb);
-int s390_ipl_prepare_pv_header(void);
+int s390_ipl_prepare_pv_header(Error **errp);
int s390_ipl_pv_unpack(void);
void s390_ipl_prepare_cpu(S390CPU *cpu);
IplParameterBlock *s390_ipl_get_iplb(void);
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 7bfa5b4e8f..94434c3bb1 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -374,7 +374,7 @@ static int s390_machine_protect(S390CcwMachineState *ms)
}
/* Set SE header and unpack */
- rc = s390_ipl_prepare_pv_header();
+ rc = s390_ipl_prepare_pv_header(&local_err);
if (rc) {
goto out_err;
}
@@ -393,6 +393,9 @@ static int s390_machine_protect(S390CcwMachineState *ms)
return rc;
out_err:
+ if (local_err) {
+ error_report_err(local_err);
+ }
s390_machine_unprotect(ms);
return rc;
}
diff --git a/target/s390x/kvm/pv.c b/target/s390x/kvm/pv.c
index e14db4f41a..ae75063777 100644
--- a/target/s390x/kvm/pv.c
+++ b/target/s390x/kvm/pv.c
@@ -27,7 +27,8 @@ static bool info_valid;
static struct kvm_s390_pv_info_vm info_vm;
static struct kvm_s390_pv_info_dump info_dump;
-static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data)
+static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data,
+ int *pvrc)
{
struct kvm_pv_cmd pv_cmd = {
.cmd = cmd,
@@ -44,6 +45,9 @@ static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data)
"IOCTL rc: %d", cmd, cmdname, pv_cmd.rc, pv_cmd.rrc,
rc);
}
+ if (pvrc) {
+ *pvrc = pv_cmd.rc;
+ }
return rc;
}
@@ -51,12 +55,13 @@ static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data)
* This macro lets us pass the command as a string to the function so
* we can print it on an error.
*/
-#define s390_pv_cmd(cmd, data) __s390_pv_cmd(cmd, #cmd, data)
+#define s390_pv_cmd(cmd, data) __s390_pv_cmd(cmd, #cmd, data, NULL)
+#define s390_pv_cmd_pvrc(cmd, data, pvrc) __s390_pv_cmd(cmd, #cmd, data, pvrc)
#define s390_pv_cmd_exit(cmd, data) \
{ \
int rc; \
\
- rc = __s390_pv_cmd(cmd, #cmd, data);\
+ rc = __s390_pv_cmd(cmd, #cmd, data, NULL); \
if (rc) { \
exit(1); \
} \
@@ -108,14 +113,24 @@ void s390_pv_vm_disable(void)
s390_pv_cmd_exit(KVM_PV_DISABLE, NULL);
}
-int s390_pv_set_sec_parms(uint64_t origin, uint64_t length)
+int s390_pv_set_sec_parms(uint64_t origin, uint64_t length, Error **errp)
{
+ int ret, pvrc;
struct kvm_s390_pv_sec_parm args = {
.origin = origin,
.length = length,
};
- return s390_pv_cmd(KVM_PV_SET_SEC_PARMS, &args);
+ ret = s390_pv_cmd_pvrc(KVM_PV_SET_SEC_PARMS, &args, &pvrc);
+ if (ret) {
+ error_setg(errp, "Failed to set secure execution parameters");
+ if (pvrc == 0x108) {
+ error_append_hint(errp, "Please check whether the image is "
+ "correctly encrypted for this host\n");
+ }
+ }
+
+ return ret;
}
/*
diff --git a/target/s390x/kvm/pv.h b/target/s390x/kvm/pv.h
index 9360aa1091..6868c3f4ac 100644
--- a/target/s390x/kvm/pv.h
+++ b/target/s390x/kvm/pv.h
@@ -41,7 +41,7 @@ static inline bool s390_is_pv(void)
int s390_pv_query_info(void);
int s390_pv_vm_enable(void);
void s390_pv_vm_disable(void);
-int s390_pv_set_sec_parms(uint64_t origin, uint64_t length);
+int s390_pv_set_sec_parms(uint64_t origin, uint64_t length, Error **errp);
int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak);
void s390_pv_prep_reset(void);
int s390_pv_verify(void);
@@ -60,7 +60,8 @@ static inline bool s390_is_pv(void) { return false; }
static inline int s390_pv_query_info(void) { return 0; }
static inline int s390_pv_vm_enable(void) { return 0; }
static inline void s390_pv_vm_disable(void) {}
-static inline int s390_pv_set_sec_parms(uint64_t origin, uint64_t length) { return 0; }
+static inline int s390_pv_set_sec_parms(uint64_t origin, uint64_t length,
+ Error **errp) { return 0; }
static inline int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak) { return 0; }
static inline void s390_pv_prep_reset(void) {}
static inline int s390_pv_verify(void) { return 0; }
--
2.41.0

View File

@ -1,151 +0,0 @@
From b5a7e5e22a52d11034b997d2bd363c3f83f168e9 Mon Sep 17 00:00:00 2001
From: Jon Maloy <jmaloy@redhat.com>
Date: Fri, 24 Nov 2023 12:17:53 -0500
Subject: [PATCH 2/2] tests/qtest: ahci-test: add test exposing reset issue
with pending callback
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Jon Maloy <jmaloy@redhat.com>
RH-MergeRequest: 335: hw/ide: reset: cancel async DMA operation before resetting state
RH-Jira: RHEL-15437
RH-Acked-by: Hanna Czenczek <hreitz@redhat.com>
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Commit: [2/2] 364e0703d22d69a4c1cfcff250ad0a3c81ada7b2 (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2)
JIRA: https://issues.redhat.com/browse/RHEL-15437
CVE: CVE-2023-5088
Upstream: Merged
commit cc610857bbd3551f4b86ae2299336b5d9aa0db2b
Author: Fiona Ebner <f.ebner@proxmox.com>
Date: Wed Sep 6 15:09:22 2023 +0200
tests/qtest: ahci-test: add test exposing reset issue with pending callback
Before commit "hw/ide: reset: cancel async DMA operation before
resetting state", this test would fail, because a reset with a
pending write operation would lead to an unsolicited write to the
first sector of the disk.
The test writes a pattern to the beginning of the disk and verifies
that it is still intact after a reset with a pending operation. It
also checks that the pending operation actually completes correctly.
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
Message-ID: <20230906130922.142845-2-f.ebner@proxmox.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
tests/qtest/ahci-test.c | 86 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 85 insertions(+), 1 deletion(-)
diff --git a/tests/qtest/ahci-test.c b/tests/qtest/ahci-test.c
index 8073ccc205..b4d15566e1 100644
--- a/tests/qtest/ahci-test.c
+++ b/tests/qtest/ahci-test.c
@@ -1425,6 +1425,89 @@ static void test_reset(void)
ahci_shutdown(ahci);
}
+static void test_reset_pending_callback(void)
+{
+ AHCIQState *ahci;
+ AHCICommand *cmd;
+ uint8_t port;
+ uint64_t ptr1;
+ uint64_t ptr2;
+
+ int bufsize = 4 * 1024;
+ int speed = bufsize + (bufsize / 2);
+ int offset1 = 0;
+ int offset2 = bufsize / AHCI_SECTOR_SIZE;
+
+ g_autofree unsigned char *tx1 = g_malloc(bufsize);
+ g_autofree unsigned char *tx2 = g_malloc(bufsize);
+ g_autofree unsigned char *rx1 = g_malloc0(bufsize);
+ g_autofree unsigned char *rx2 = g_malloc0(bufsize);
+
+ /* Uses throttling to make test independent of specific environment. */
+ ahci = ahci_boot_and_enable("-drive if=none,id=drive0,file=%s,"
+ "cache=writeback,format=%s,"
+ "throttling.bps-write=%d "
+ "-M q35 "
+ "-device ide-hd,drive=drive0 ",
+ tmp_path, imgfmt, speed);
+
+ port = ahci_port_select(ahci);
+ ahci_port_clear(ahci, port);
+
+ ptr1 = ahci_alloc(ahci, bufsize);
+ ptr2 = ahci_alloc(ahci, bufsize);
+
+ g_assert(ptr1 && ptr2);
+
+ /* Need two different patterns. */
+ do {
+ generate_pattern(tx1, bufsize, AHCI_SECTOR_SIZE);
+ generate_pattern(tx2, bufsize, AHCI_SECTOR_SIZE);
+ } while (memcmp(tx1, tx2, bufsize) == 0);
+
+ qtest_bufwrite(ahci->parent->qts, ptr1, tx1, bufsize);
+ qtest_bufwrite(ahci->parent->qts, ptr2, tx2, bufsize);
+
+ /* Write to beginning of disk to check it wasn't overwritten later. */
+ ahci_guest_io(ahci, port, CMD_WRITE_DMA_EXT, ptr1, bufsize, offset1);
+
+ /* Issue asynchronously to get a pending callback during reset. */
+ cmd = ahci_command_create(CMD_WRITE_DMA_EXT);
+ ahci_command_adjust(cmd, offset2, ptr2, bufsize, 0);
+ ahci_command_commit(ahci, cmd, port);
+ ahci_command_issue_async(ahci, cmd);
+
+ ahci_set(ahci, AHCI_GHC, AHCI_GHC_HR);
+
+ ahci_command_free(cmd);
+
+ /* Wait for throttled write to finish. */
+ sleep(1);
+
+ /* Start again. */
+ ahci_clean_mem(ahci);
+ ahci_pci_enable(ahci);
+ ahci_hba_enable(ahci);
+ port = ahci_port_select(ahci);
+ ahci_port_clear(ahci, port);
+
+ /* Read and verify. */
+ ahci_guest_io(ahci, port, CMD_READ_DMA_EXT, ptr1, bufsize, offset1);
+ qtest_bufread(ahci->parent->qts, ptr1, rx1, bufsize);
+ g_assert_cmphex(memcmp(tx1, rx1, bufsize), ==, 0);
+
+ ahci_guest_io(ahci, port, CMD_READ_DMA_EXT, ptr2, bufsize, offset2);
+ qtest_bufread(ahci->parent->qts, ptr2, rx2, bufsize);
+ g_assert_cmphex(memcmp(tx2, rx2, bufsize), ==, 0);
+
+ ahci_free(ahci, ptr1);
+ ahci_free(ahci, ptr2);
+
+ ahci_clean_mem(ahci);
+
+ ahci_shutdown(ahci);
+}
+
static void test_ncq_simple(void)
{
AHCIQState *ahci;
@@ -1929,7 +2012,8 @@ int main(int argc, char **argv)
qtest_add_func("/ahci/migrate/dma/halted", test_migrate_halted_dma);
qtest_add_func("/ahci/max", test_max);
- qtest_add_func("/ahci/reset", test_reset);
+ qtest_add_func("/ahci/reset/simple", test_reset);
+ qtest_add_func("/ahci/reset/pending_callback", test_reset_pending_callback);
qtest_add_func("/ahci/io/ncq/simple", test_ncq_simple);
qtest_add_func("/ahci/migrate/ncq/simple", test_migrate_ncq);
--
2.41.0

View File

@ -1,118 +0,0 @@
From 4069f8f55d070b5a1eb2bf894a517ea9fb648bbd Mon Sep 17 00:00:00 2001
From: Jon Maloy <jmaloy@redhat.com>
Date: Tue, 5 Mar 2024 11:36:15 -0500
Subject: [PATCH 2/3] ui/clipboard: mark type as not available when there is no
data
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Jon Maloy <jmaloy@redhat.com>
RH-MergeRequest: 353: ui/clipboard: mark type as not available when there is no data
RH-Jira: RHEL-19628
RH-Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com>
RH-Acked-by: Gerd Hoffmann <None>
RH-Commit: [2/2] fa0edf7a362a16978e2377cf61f36ff227d186b2 (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2)
JIRA: https://issues.redhat.com/browse/RHEL-19628
CVE: CVE-2023-6683
Upstream: Merged
Conflicts:
- The function g_memdup2() is used by this commit, but is not present in
this code version. It looks safe to introduce it in a preceding commit,
instead of reverting to the less safe g_memdup(), so that is what we do.
- There is a second upstream commit covering this CVE:
commit 9c416582611b ("ui/clipboard: add asserts for update and request")
which is based on several other previous commits not present in this version.
Re-applying these, or trying to adapt the code, is too intrusive and risky
given that it only introduces two diagnostic asserts which are not essential
for solving the CVE.
We therefore omit that commit.
commit 405484b29f6548c7b86549b0f961b906337aa68a
Author: Fiona Ebner <f.ebner@proxmox.com>
Date: Wed Jan 24 11:57:48 2024 +0100
ui/clipboard: mark type as not available when there is no data
With VNC, a client can send a non-extended VNC_MSG_CLIENT_CUT_TEXT
message with len=0. In qemu_clipboard_set_data(), the clipboard info
will be updated setting data to NULL (because g_memdup(data, size)
returns NULL when size is 0). If the client does not set the
VNC_ENCODING_CLIPBOARD_EXT feature when setting up the encodings, then
the 'request' callback for the clipboard peer is not initialized.
Later, because data is NULL, qemu_clipboard_request() can be reached
via vdagent_chr_write() and vdagent_clipboard_recv_request() and
there, the clipboard owner's 'request' callback will be attempted to
be called, but that is a NULL pointer.
In particular, this can happen when using the KRDC (22.12.3) VNC
client.
Another scenario leading to the same issue is with two clients (say
noVNC and KRDC):
The noVNC client sets the extension VNC_FEATURE_CLIPBOARD_EXT and
initializes its cbpeer.
The KRDC client does not, but triggers a vnc_client_cut_text() (note
it's not the _ext variant)). There, a new clipboard info with it as
the 'owner' is created and via qemu_clipboard_set_data() is called,
which in turn calls qemu_clipboard_update() with that info.
In qemu_clipboard_update(), the notifier for the noVNC client will be
called, i.e. vnc_clipboard_notify() and also set vs->cbinfo for the
noVNC client. The 'owner' in that clipboard info is the clipboard peer
for the KRDC client, which did not initialize the 'request' function.
That sounds correct to me, it is the owner of that clipboard info.
Then when noVNC sends a VNC_MSG_CLIENT_CUT_TEXT message (it did set
the VNC_FEATURE_CLIPBOARD_EXT feature correctly, so a check for it
passes), that clipboard info is passed to qemu_clipboard_request() and
the original segfault still happens.
Fix the issue by handling updates with size 0 differently. In
particular, mark in the clipboard info that the type is not available.
While at it, switch to g_memdup2(), because g_memdup() is deprecated.
Cc: qemu-stable@nongnu.org
Fixes: CVE-2023-6683
Reported-by: Markus Frank <m.frank@proxmox.com>
Suggested-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Tested-by: Markus Frank <m.frank@proxmox.com>
Message-ID: <20240124105749.204610-1-f.ebner@proxmox.com>
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
ui/clipboard.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/ui/clipboard.c b/ui/clipboard.c
index d7b008d62a..b8c795f2e2 100644
--- a/ui/clipboard.c
+++ b/ui/clipboard.c
@@ -123,9 +123,15 @@ void qemu_clipboard_set_data(QemuClipboardPeer *peer,
}
g_free(info->types[type].data);
- info->types[type].data = g_memdup(data, size);
- info->types[type].size = size;
- info->types[type].available = true;
+ if (size) {
+ info->types[type].data = g_memdup2(data, size);
+ info->types[type].size = size;
+ info->types[type].available = true;
+ } else {
+ info->types[type].data = NULL;
+ info->types[type].size = 0;
+ info->types[type].available = false;
+ }
if (update) {
qemu_clipboard_update(info);
--
2.41.0

View File

@ -1,55 +0,0 @@
From 8a233fd50c4ab973ef4a3c4ac7daf83e5c90aabc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
Date: Mon, 11 Sep 2023 18:04:47 +0400
Subject: [PATCH 4/4] ui: fix crash when there are no active_console
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Marc-André Lureau <marcandre.lureau@redhat.com>
RH-MergeRequest: 338: ui: fix crash when there are no active_console
RH-Jira: RHEL-2600
RH-Acked-by: Gerd Hoffmann <None>
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
RH-Commit: [1/1] c58d1d76558dbc7ee2a8193a1e7a9b87a79ac385
JIRA: https://issues.redhat.com/browse/RHEL-2600
Thread 1 "qemu-system-x86" received signal SIGSEGV, Segmentation fault.
0x0000555555888630 in dpy_ui_info_supported (con=0x0) at ../ui/console.c:812
812 return con->hw_ops->ui_info != NULL;
(gdb) bt
#0 0x0000555555888630 in dpy_ui_info_supported (con=0x0) at ../ui/console.c:812
#1 0x00005555558a44b1 in protocol_client_msg (vs=0x5555578c76c0, data=0x5555581e93f0 <incomplete sequence \373>, len=24) at ../ui/vnc.c:2585
#2 0x00005555558a19ac in vnc_client_read (vs=0x5555578c76c0) at ../ui/vnc.c:1607
#3 0x00005555558a1ac2 in vnc_client_io (ioc=0x5555581eb0e0, condition=G_IO_IN, opaque=0x5555578c76c0) at ../ui/vnc.c:1635
Fixes:
https://issues.redhat.com/browse/RHEL-2600
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Albert Esteve <aesteve@redhat.com>
(cherry picked from commit 48a35e12faf90a896c5aa4755812201e00d60316)
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
ui/console.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/ui/console.c b/ui/console.c
index 29a3e3f0f5..df3426bd8a 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1525,6 +1525,9 @@ bool dpy_ui_info_supported(QemuConsole *con)
if (con == NULL) {
con = active_console;
}
+ if (con == NULL) {
+ return false;
+ }
return con->hw_ops->ui_info != NULL;
}
--
2.41.0

View File

@ -1,76 +0,0 @@
From efbf51a42b51665fd70ea49b9c583a208cfd2deb Mon Sep 17 00:00:00 2001
From: Jon Maloy <jmaloy@redhat.com>
Date: Tue, 4 Jul 2023 10:41:22 +0200
Subject: [PATCH] ui/vnc-clipboard: fix infinite loop in inflate_buffer
(CVE-2023-3255)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Jon Maloy <jmaloy@redhat.com>
RH-MergeRequest: 316: ui/vnc-clipboard: fix infinite loop in inflate_buffer (CVE-2023-3255)
RH-Bugzilla: 2218488
RH-Acked-by: Mauro Matteo Cascella <None>
RH-Commit: [1/1] f3cb05fb6e40261da5fe10f003fa3e57920469bb (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2)
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2218488
CVE: CVE-2023-3255
Upstream: Merged
commit d921fea338c1059a27ce7b75309d7a2e485f710b
Author: Mauro Matteo Cascella <mcascell@redhat.com>
Date: Tue Jul 4 10:41:22 2023 +0200
ui/vnc-clipboard: fix infinite loop in inflate_buffer (CVE-2023-3255)
A wrong exit condition may lead to an infinite loop when inflating a
valid zlib buffer containing some extra bytes in the `inflate_buffer`
function. The bug only occurs post-authentication. Return the buffer
immediately if the end of the compressed data has been reached
(Z_STREAM_END).
Fixes: CVE-2023-3255
Fixes: 0bf41cab ("ui/vnc: clipboard support")
Reported-by: Kevin Denis <kevin.denis@synacktiv.com>
Signed-off-by: Mauro Matteo Cascella <mcascell@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Tested-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20230704084210.101822-1-mcascell@redhat.com>
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
ui/vnc-clipboard.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/ui/vnc-clipboard.c b/ui/vnc-clipboard.c
index 67284b556c..c84599cfdb 100644
--- a/ui/vnc-clipboard.c
+++ b/ui/vnc-clipboard.c
@@ -51,8 +51,11 @@ static uint8_t *inflate_buffer(uint8_t *in, uint32_t in_len, uint32_t *size)
ret = inflate(&stream, Z_FINISH);
switch (ret) {
case Z_OK:
- case Z_STREAM_END:
break;
+ case Z_STREAM_END:
+ *size = stream.total_out;
+ inflateEnd(&stream);
+ return out;
case Z_BUF_ERROR:
out_len <<= 1;
if (out_len > (1 << 20)) {
@@ -67,11 +70,6 @@ static uint8_t *inflate_buffer(uint8_t *in, uint32_t in_len, uint32_t *size)
}
}
- *size = stream.total_out;
- inflateEnd(&stream);
-
- return out;
-
err_end:
inflateEnd(&stream);
err:
--
2.41.0

View File

@ -1,69 +0,0 @@
From a728c0b522997e8e63bf6b64b202a7ae48693d02 Mon Sep 17 00:00:00 2001
From: Prasad Pandit <ppandit@redhat.com>
Date: Fri, 18 Aug 2023 16:38:12 +0530
Subject: [PATCH 3/4] vhost: release memory_listener object in error path
RH-Author: Prasad Pandit <None>
RH-MergeRequest: 337: vhost: release memory_listener object in error path
RH-Jira: RHEL-7567
RH-Acked-by: Peter Xu <peterx@redhat.com>
RH-Acked-by: Jon Maloy <jmaloy@redhat.com>
RH-Commit: [1/1] 1e377a2f6f148e11a452d11107d839521354e2ca
Jira: https://issues.redhat.com/browse/RHEL-7567
commit 1e3ffb34f764f8ac4c003b2b2e6a775b2b073a16
Author: Prasad J Pandit <pjp@fedoraproject.org>
Date: Mon May 29 17:13:32 2023 +0530
vhost: release memory_listener object in error path
vhost_dev_start function does not release memory_listener object
in case of an error. This may crash the guest when vhost is unable
to set memory table:
stack trace of thread 125653:
Program terminated with signal SIGSEGV, Segmentation fault
#0 memory_listener_register (qemu-kvm + 0x6cda0f)
#1 vhost_dev_start (qemu-kvm + 0x699301)
#2 vhost_net_start (qemu-kvm + 0x45b03f)
#3 virtio_net_set_status (qemu-kvm + 0x665672)
#4 qmp_set_link (qemu-kvm + 0x548fd5)
#5 net_vhost_user_event (qemu-kvm + 0x552c45)
#6 tcp_chr_connect (qemu-kvm + 0x88d473)
#7 tcp_chr_new_client (qemu-kvm + 0x88cf83)
#8 tcp_chr_accept (qemu-kvm + 0x88b429)
#9 qio_net_listener_channel_func (qemu-kvm + 0x7ac07c)
#10 g_main_context_dispatch (libglib-2.0.so.0 + 0x54e2f)
Release memory_listener objects in the error path.
Signed-off-by: Prasad Pandit <pjp@fedoraproject.org>
Message-Id: <20230529114333.31686-2-ppandit@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Fixes: c471ad0e9b ("vhost_net: device IOTLB support")
Cc: qemu-stable@nongnu.org
Acked-by: Jason Wang <jasowang@redhat.com>
---
hw/virtio/vhost.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 437347ad01..639029aa76 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1818,6 +1818,9 @@ fail_vq:
}
fail_mem:
+ if (vhost_dev_has_iommu(hdev)) {
+ memory_listener_unregister(&hdev->iommu_listener);
+ }
fail_features:
hdev->started = false;
--
2.41.0

View File

@ -1,92 +0,0 @@
From 7ad4fc282b1f96d619ce2f9f7ed9049c3b894dd4 Mon Sep 17 00:00:00 2001
From: Jon Maloy <jmaloy@redhat.com>
Date: Thu, 18 Jul 2024 09:42:42 -0400
Subject: [PATCH 1/6] virtio-gpu: free BHs, by implementing unrealize
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Jon Maloy <jmaloy@redhat.com>
RH-MergeRequest: 380: QEMU: virtio: DMA reentrancy issue leads to double free vulnerability
RH-Jira: RHEL-32276
RH-Acked-by: Gerd Hoffmann <None>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Commit: [1/6] d05c10426afac428d775669748f0aa689c23e787 (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2)
JIRA: https://issues.redhat.com/browse/RHEL-32276
CVE: CVE-2024-3446
Upstream: Merged
commit 957d77863e4564454eb97f8f371096843daf4678
Author: Marc-André Lureau <marcandre.lureau@redhat.com>
Date: Wed Jul 26 21:39:28 2023 +0400
virtio-gpu: free BHs, by implementing unrealize
Acked-by: Dongwon Kim <dongwon.kim@intel.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20230726173929.690601-2-marcandre.lureau@redhat.com>
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
hw/display/virtio-gpu-base.c | 2 +-
hw/display/virtio-gpu.c | 10 ++++++++++
include/hw/virtio/virtio-gpu.h | 1 +
3 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c
index c8da4806e0..e3ff9dcf38 100644
--- a/hw/display/virtio-gpu-base.c
+++ b/hw/display/virtio-gpu-base.c
@@ -223,7 +223,7 @@ virtio_gpu_base_set_features(VirtIODevice *vdev, uint64_t features)
trace_virtio_gpu_features(((features & virgl) == virgl));
}
-static void
+void
virtio_gpu_base_device_unrealize(DeviceState *qdev)
{
VirtIOGPUBase *g = VIRTIO_GPU_BASE(qdev);
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index ecf9079145..e230e5091f 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -1341,6 +1341,15 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
QTAILQ_INIT(&g->fenceq);
}
+static void virtio_gpu_device_unrealize(DeviceState *qdev)
+{
+ VirtIOGPU *g = VIRTIO_GPU(qdev);
+
+ g_clear_pointer(&g->ctrl_bh, qemu_bh_delete);
+ g_clear_pointer(&g->cursor_bh, qemu_bh_delete);
+ virtio_gpu_base_device_unrealize(qdev);
+}
+
void virtio_gpu_reset(VirtIODevice *vdev)
{
VirtIOGPU *g = VIRTIO_GPU(vdev);
@@ -1436,6 +1445,7 @@ static void virtio_gpu_class_init(ObjectClass *klass, void *data)
vgbc->gl_flushed = virtio_gpu_handle_gl_flushed;
vdc->realize = virtio_gpu_device_realize;
+ vdc->unrealize = virtio_gpu_device_unrealize;
vdc->reset = virtio_gpu_reset;
vdc->get_config = virtio_gpu_get_config;
vdc->set_config = virtio_gpu_set_config;
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index acfba7c76c..4367d005f1 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -235,6 +235,7 @@ bool virtio_gpu_base_device_realize(DeviceState *qdev,
VirtIOHandleOutput ctrl_cb,
VirtIOHandleOutput cursor_cb,
Error **errp);
+void virtio_gpu_base_device_unrealize(DeviceState *qdev);
void virtio_gpu_base_reset(VirtIOGPUBase *g);
void virtio_gpu_base_fill_display_info(VirtIOGPUBase *g,
struct virtio_gpu_resp_display_info *dpy_info);
--
2.39.3

View File

@ -1,143 +0,0 @@
From 29328e9693aeae1c980a859d4966deda9f54242d Mon Sep 17 00:00:00 2001
From: Jon Maloy <jmaloy@redhat.com>
Date: Thu, 18 Jul 2024 09:36:06 -0400
Subject: [PATCH 2/6] virtio-gpu: reset gfx resources in main thread
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Jon Maloy <jmaloy@redhat.com>
RH-MergeRequest: 380: QEMU: virtio: DMA reentrancy issue leads to double free vulnerability
RH-Jira: RHEL-32276
RH-Acked-by: Gerd Hoffmann <None>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Commit: [2/6] a97eef1e6e85b44c08d17adcdc468e857e48a17e (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2)
JIRA: https://issues.redhat.com/browse/RHEL-32276
CVE: CVE-2024-3446
Upstream: Merged
commit a41e2d97f92b48552988b3cc62dce79d62f60dcc
Author: Marc-André Lureau <marcandre.lureau@redhat.com>
Date: Wed Jul 26 21:39:29 2023 +0400
virtio-gpu: reset gfx resources in main thread
Calling OpenGL from different threads can have bad consequences if not
carefully reviewed. It's not generally supported. In my case, I was
debugging a crash in glDeleteTextures from OPENGL32.DLL, where I asked
qemu for gl=es, and thus ANGLE implementation was expected. libepoxy did
resolution of the global pointer for glGenTexture to the GLES version
from the main thread. But it resolved glDeleteTextures to the GL
version, because it was done from a different thread without correct
context. Oops.
Let's stick to the main thread for GL calls by using a BH.
Note: I didn't use atomics for reset_finished check, assuming the BQL
will provide enough of sync, but I might be wrong.
Acked-by: Dongwon Kim <dongwon.kim@intel.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20230726173929.690601-3-marcandre.lureau@redhat.com>
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
hw/display/virtio-gpu.c | 35 +++++++++++++++++++++++++++++++---
include/hw/virtio/virtio-gpu.h | 3 +++
2 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index e230e5091f..c28ce1ea72 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -14,6 +14,7 @@
#include "qemu/osdep.h"
#include "qemu/units.h"
#include "qemu/iov.h"
+#include "sysemu/cpus.h"
#include "ui/console.h"
#include "trace.h"
#include "sysemu/dma.h"
@@ -42,6 +43,7 @@ virtio_gpu_find_check_resource(VirtIOGPU *g, uint32_t resource_id,
static void virtio_gpu_cleanup_mapping(VirtIOGPU *g,
struct virtio_gpu_simple_resource *res);
+static void virtio_gpu_reset_bh(void *opaque);
void virtio_gpu_update_cursor_data(VirtIOGPU *g,
struct virtio_gpu_scanout *s,
@@ -1336,6 +1338,8 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
&qdev->mem_reentrancy_guard);
g->cursor_bh = qemu_bh_new_guarded(virtio_gpu_cursor_bh, g,
&qdev->mem_reentrancy_guard);
+ g->reset_bh = qemu_bh_new(virtio_gpu_reset_bh, g);
+ qemu_cond_init(&g->reset_cond);
QTAILQ_INIT(&g->reslist);
QTAILQ_INIT(&g->cmdq);
QTAILQ_INIT(&g->fenceq);
@@ -1347,19 +1351,44 @@ static void virtio_gpu_device_unrealize(DeviceState *qdev)
g_clear_pointer(&g->ctrl_bh, qemu_bh_delete);
g_clear_pointer(&g->cursor_bh, qemu_bh_delete);
+ g_clear_pointer(&g->reset_bh, qemu_bh_delete);
+ qemu_cond_destroy(&g->reset_cond);
virtio_gpu_base_device_unrealize(qdev);
}
-void virtio_gpu_reset(VirtIODevice *vdev)
+static void virtio_gpu_reset_bh(void *opaque)
{
- VirtIOGPU *g = VIRTIO_GPU(vdev);
+ VirtIOGPU *g = VIRTIO_GPU(opaque);
struct virtio_gpu_simple_resource *res, *tmp;
- struct virtio_gpu_ctrl_command *cmd;
+ int i = 0;
QTAILQ_FOREACH_SAFE(res, &g->reslist, next, tmp) {
virtio_gpu_resource_destroy(g, res);
}
+ for (i = 0; i < g->parent_obj.conf.max_outputs; i++) {
+ dpy_gfx_replace_surface(g->parent_obj.scanout[i].con, NULL);
+ }
+
+ g->reset_finished = true;
+ qemu_cond_signal(&g->reset_cond);
+}
+
+void virtio_gpu_reset(VirtIODevice *vdev)
+{
+ VirtIOGPU *g = VIRTIO_GPU(vdev);
+ struct virtio_gpu_ctrl_command *cmd;
+
+ if (qemu_in_vcpu_thread()) {
+ g->reset_finished = false;
+ qemu_bh_schedule(g->reset_bh);
+ while (!g->reset_finished) {
+ qemu_cond_wait_iothread(&g->reset_cond);
+ }
+ } else {
+ virtio_gpu_reset_bh(g);
+ }
+
while (!QTAILQ_EMPTY(&g->cmdq)) {
cmd = QTAILQ_FIRST(&g->cmdq);
QTAILQ_REMOVE(&g->cmdq, cmd, next);
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 4367d005f1..f3578c1325 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -166,6 +166,9 @@ struct VirtIOGPU {
QEMUBH *ctrl_bh;
QEMUBH *cursor_bh;
+ QEMUBH *reset_bh;
+ QemuCond reset_cond;
+ bool reset_finished;
QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist;
QTAILQ_HEAD(, virtio_gpu_ctrl_command) cmdq;
--
2.39.3

View File

@ -1,90 +0,0 @@
From c3146dd39fb274ffbd70d20f8ba9e13562fb21ad Mon Sep 17 00:00:00 2001
From: Jon Maloy <jmaloy@redhat.com>
Date: Tue, 5 Mar 2024 16:38:49 -0500
Subject: [PATCH 3/3] virtio-net: correctly copy vnet header when flushing TX
RH-Author: Jon Maloy <jmaloy@redhat.com>
RH-MergeRequest: 354: virtio-net: correctly copy vnet header when flushing TX
RH-Jira: RHEL-19496
RH-Acked-by: Jason Wang <jasowang@redhat.com>
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
RH-Commit: [1/1] 445b601da86a64298b776879fa0f30a4bf6c16f5 (redhat/rhel/src/qemu-kvm/jons-qemu-kvm-2)
JIRA: https://issues.redhat.com/browse/RHEL-19496
CVE: CVE-2023-6693
Upstream: Merged
commit 2220e8189fb94068dbad333228659fbac819abb0
Author: Jason Wang <jasowang@redhat.com>
Date: Tue Jan 2 11:29:01 2024 +0800
virtio-net: correctly copy vnet header when flushing TX
When HASH_REPORT is negotiated, the guest_hdr_len might be larger than
the size of the mergeable rx buffer header. Using
virtio_net_hdr_mrg_rxbuf during the header swap might lead a stack
overflow in this case. Fixing this by using virtio_net_hdr_v1_hash
instead.
Reported-by: Xiao Lei <leixiao.nop@zju.edu.cn>
Cc: Yuri Benditovich <yuri.benditovich@daynix.com>
Cc: qemu-stable@nongnu.org
Cc: Mauro Matteo Cascella <mcascell@redhat.com>
Fixes: CVE-2023-6693
Fixes: e22f0603fb2f ("virtio-net: reference implementation of hash report")
Reviewed-by: Michael Tokarev <mjt@tls.msk.ru>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Jon Maloy <jmaloy@redhat.com>
---
hw/net/virtio-net.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index f5f07f8e63..7d459726d4 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -602,6 +602,11 @@ static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs,
n->mergeable_rx_bufs = mergeable_rx_bufs;
+ /*
+ * Note: when extending the vnet header, please make sure to
+ * change the vnet header copying logic in virtio_net_flush_tx()
+ * as well.
+ */
if (version_1) {
n->guest_hdr_len = hash_report ?
sizeof(struct virtio_net_hdr_v1_hash) :
@@ -2535,7 +2540,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
ssize_t ret;
unsigned int out_num;
struct iovec sg[VIRTQUEUE_MAX_SIZE], sg2[VIRTQUEUE_MAX_SIZE + 1], *out_sg;
- struct virtio_net_hdr_mrg_rxbuf mhdr;
+ struct virtio_net_hdr_v1_hash vhdr;
elem = virtqueue_pop(q->tx_vq, sizeof(VirtQueueElement));
if (!elem) {
@@ -2552,7 +2557,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
}
if (n->has_vnet_hdr) {
- if (iov_to_buf(out_sg, out_num, 0, &mhdr, n->guest_hdr_len) <
+ if (iov_to_buf(out_sg, out_num, 0, &vhdr, n->guest_hdr_len) <
n->guest_hdr_len) {
virtio_error(vdev, "virtio-net header incorrect");
virtqueue_detach_element(q->tx_vq, elem, 0);
@@ -2560,8 +2565,8 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
return -EINVAL;
}
if (n->needs_vnet_hdr_swap) {
- virtio_net_hdr_swap(vdev, (void *) &mhdr);
- sg2[0].iov_base = &mhdr;
+ virtio_net_hdr_swap(vdev, (void *) &vhdr);
+ sg2[0].iov_base = &vhdr;
sg2[0].iov_len = n->guest_hdr_len;
out_num = iov_copy(&sg2[1], ARRAY_SIZE(sg2) - 1,
out_sg, out_num,
--
2.41.0

View File

@ -1,49 +0,0 @@
From a38e51982522910475ec051f81116639254a2955 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Thu, 30 May 2024 13:10:29 +0200
Subject: [PATCH 5/5] vnc: increase max display size
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RH-Author: Marc-André Lureau <marcandre.lureau@redhat.com>
RH-MergeRequest: 391: vnc: increase max display size
RH-Jira: RHEL-50854
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
RH-Commit: [1/1] 8d79bbc6949ca7264f6701121b47e946eb8ac824
Resolves:
https://issues.redhat.com/browse/RHEL-50854
It's 2024. 4k display resolutions are a thing these days.
Raise width and height limits of the qemu vnc server.
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1596
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Message-ID: <20240530111029.1726329-1-kraxel@redhat.com>
(cherry picked from commit 1f1736a8f16d27a99abd371caaeedc10e6411d15)
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
ui/vnc.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/ui/vnc.h b/ui/vnc.h
index a7149831f9..4d44957cc2 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -81,8 +81,8 @@ typedef void VncSendHextileTile(VncState *vs,
/* VNC_MAX_WIDTH must be a multiple of VNC_DIRTY_PIXELS_PER_BIT. */
-#define VNC_MAX_WIDTH ROUND_UP(2560, VNC_DIRTY_PIXELS_PER_BIT)
-#define VNC_MAX_HEIGHT 2048
+#define VNC_MAX_WIDTH ROUND_UP(5120, VNC_DIRTY_PIXELS_PER_BIT)
+#define VNC_MAX_HEIGHT 2160
/* VNC_DIRTY_BITS is the number of bits in the dirty bitmap. */
#define VNC_DIRTY_BITS (VNC_MAX_WIDTH / VNC_DIRTY_PIXELS_PER_BIT)
--
2.39.3

Some files were not shown because too many files have changed in this diff Show More