From 86ffd40d11b0d54d9ef7acd541cc45ad80600854b92a3e342e210f514a0e8370 Mon Sep 17 00:00:00 2001 From: Bruce Rogers Date: Tue, 30 Mar 2021 20:27:28 +0000 Subject: [PATCH] Accepting request 882222 from home:bfrogers:branches:Virtualization - Switch method of splitting off hw-s390x-virtio-gpu-ccw.so as a module to what was accepted upstream (bsc#1181103) * Patches dropped: hw-s390x-modularize-virtio-gpu-ccw.patch * Patches added: s390x-add-have_virtio_ccw.patch s390x-modularize-virtio-gpu-ccw.patch s390x-move-S390_ADAPTER_SUPPRESSIBLE.patch - Fix OOB access in sdhci interface (CVE-2020-17380, bsc#1175144, CVE-2020-25085, bsc#1176681, CVE-2021-3409, bsc#1182282) hw-sd-sd-Actually-perform-the-erase-oper.patch hw-sd-sd-Fix-build-error-when-DEBUG_SD-i.patch hw-sd-sdhci-Correctly-set-the-controller.patch hw-sd-sdhci-Don-t-transfer-any-data-when.patch hw-sd-sdhci-Don-t-write-to-SDHC_SYSAD-re.patch hw-sd-sdhci-Limit-block-size-only-when-S.patch hw-sd-sdhci-Reset-the-data-pointer-of-s-.patch hw-sd-sd-Move-the-sd_block_-read-write-a.patch hw-sd-sd-Skip-write-protect-groups-check.patch - Fix potential privilege escalation in virtiofsd tool (CVE-2021-20263, bsc#1183373) tools-virtiofsd-Replace-the-word-whiteli.patch viriofsd-Add-support-for-FUSE_HANDLE_KIL.patch virtiofsd-extract-lo_do_open-from-lo_ope.patch virtiofsd-optionally-return-inode-pointe.patch virtiofsd-prevent-opening-of-special-fil.patch virtiofs-drop-remapped-security.capabili.patch virtiofsd-Save-error-code-early-at-the-f.patch - Fix OOB access (stack overflow) in rtl8139 NIC emulation (CVE-2021-3416, bsc#1182968) net-introduce-qemu_receive_packet.patch rtl8139-switch-to-use-qemu_receive_packe.patch - Fix OOB access (stack overflow) in other NIC emulations (CVE-2021-3416) cadence_gem-switch-to-use-qemu_receive_p.patch dp8393x-switch-to-use-qemu_receive_packe.patch e1000-switch-to-use-qemu_receive_packet-.patch lan9118-switch-to-use-qemu_receive_packe.patch msf2-mac-switch-to-use-qemu_receive_pack.patch pcnet-switch-to-use-qemu_receive_packet-.patch sungem-switch-to-use-qemu_receive_packet.patch tx_pkt-switch-to-use-qemu_receive_packet.patch - Fix heap overflow in MSIx emulation (CVE-2020-27821, bsc#1179686) memory-clamp-cached-translation-in-case-.patch - Include upstream patches designated as stable material and reviewed for applicability to include here hw-arm-virt-Disable-pl011-clock-migratio.patch xen-block-Fix-removal-of-backend-instanc.patch - Fix package scripts to not use hard coded paths for temporary working directories and log files (bsc#1182425) OBS-URL: https://build.opensuse.org/request/show/882222 OBS-URL: https://build.opensuse.org/package/show/Virtualization/qemu?expand=0&rev=632 --- ...-Fully-restart-unreclaim-loop-CVE-20.patch | 2 +- PPC-KVM-Disable-mmu-notifier-check.patch | 2 +- ...k-Fix-deadlock-in-bdrv_co_yield_to_d.patch | 2 +- block-Fix-locking-in-qmp_block_resize.patch | 2 +- bundles.tar.xz | 4 +- ...nce_gem-switch-to-use-qemu_receive_p.patch | 39 ++ config.sh | 8 +- ...93x-switch-to-use-qemu_receive_packe.patch | 36 ++ ...0-switch-to-use-qemu_receive_packet-.patch | 36 ++ ...rm-virt-Disable-pl011-clock-migratio.patch | 87 +++++ hw-s390x-modularize-virtio-gpu-ccw.patch | 248 ------------- ...d-sd-Actually-perform-the-erase-oper.patch | 69 ++++ ...d-sd-Fix-build-error-when-DEBUG_SD-i.patch | 35 ++ ...d-sd-Move-the-sd_block_-read-write-a.patch | 83 +++++ ...d-sd-Skip-write-protect-groups-check.patch | 71 ++++ ...d-sdhci-Correctly-set-the-controller.patch | 70 ++++ ...d-sdhci-Don-t-transfer-any-data-when.patch | 87 +++++ ...d-sdhci-Don-t-write-to-SDHC_SYSAD-re.patch | 105 ++++++ ...d-sdhci-Limit-block-size-only-when-S.patch | 52 +++ ...d-sdhci-Reset-the-data-pointer-of-s-.patch | 95 +++++ ...sts-Fix-_send_qemu_cmd-with-bash-5.1.patch | 2 +- ...118-switch-to-use-qemu_receive_packe.patch | 37 ++ ...ry-clamp-cached-translation-in-case-.patch | 137 +++++++ ...le-for-virtio-gpu-pre-load-module-to.patch | 4 +- ...-mac-switch-to-use-qemu_receive_pack.patch | 36 ++ net-introduce-qemu_receive_packet.patch | 171 +++++++++ ...t-switch-to-use-qemu_receive_packet-.patch | 38 ++ qemu.changes | 58 +++ qemu.spec | 230 +++++++----- ...handle-case-of-chardev-spice-module-.patch | 2 +- ...139-switch-to-use-qemu_receive_packe.patch | 39 ++ s390x-add-have_virtio_ccw.patch | 50 +++ s390x-modularize-virtio-gpu-ccw.patch | 87 +++++ s390x-move-S390_ADAPTER_SUPPRESSIBLE.patch | 96 +++++ ...em-switch-to-use-qemu_receive_packet.patch | 38 ++ ...s-virtiofsd-Replace-the-word-whiteli.patch | 93 +++++ ...kt-switch-to-use-qemu_receive_packet.patch | 36 ++ update_git.sh | 153 ++++---- ...ofsd-Add-support-for-FUSE_HANDLE_KIL.patch | 335 ++++++++++++++++++ ...iofs-drop-remapped-security.capabili.patch | 208 +++++++++++ ...iofsd-Save-error-code-early-at-the-f.patch | 87 +++++ ...iofsd-extract-lo_do_open-from-lo_ope.patch | 145 ++++++++ ...iofsd-optionally-return-inode-pointe.patch | 108 ++++++ ...iofsd-prevent-opening-of-special-fil.patch | 298 ++++++++++++++++ ...add-block-resize-support-for-xen-dis.patch | 2 +- ...block-Fix-removal-of-backend-instanc.patch | 49 +++ ...disk-Add-suse-specific-flush-disable.patch | 2 +- 47 files changed, 3259 insertions(+), 415 deletions(-) create mode 100644 cadence_gem-switch-to-use-qemu_receive_p.patch create mode 100644 dp8393x-switch-to-use-qemu_receive_packe.patch create mode 100644 e1000-switch-to-use-qemu_receive_packet-.patch create mode 100644 hw-arm-virt-Disable-pl011-clock-migratio.patch delete mode 100644 hw-s390x-modularize-virtio-gpu-ccw.patch create mode 100644 hw-sd-sd-Actually-perform-the-erase-oper.patch create mode 100644 hw-sd-sd-Fix-build-error-when-DEBUG_SD-i.patch create mode 100644 hw-sd-sd-Move-the-sd_block_-read-write-a.patch create mode 100644 hw-sd-sd-Skip-write-protect-groups-check.patch create mode 100644 hw-sd-sdhci-Correctly-set-the-controller.patch create mode 100644 hw-sd-sdhci-Don-t-transfer-any-data-when.patch create mode 100644 hw-sd-sdhci-Don-t-write-to-SDHC_SYSAD-re.patch create mode 100644 hw-sd-sdhci-Limit-block-size-only-when-S.patch create mode 100644 hw-sd-sdhci-Reset-the-data-pointer-of-s-.patch create mode 100644 lan9118-switch-to-use-qemu_receive_packe.patch create mode 100644 memory-clamp-cached-translation-in-case-.patch create mode 100644 msf2-mac-switch-to-use-qemu_receive_pack.patch create mode 100644 net-introduce-qemu_receive_packet.patch create mode 100644 pcnet-switch-to-use-qemu_receive_packet-.patch create mode 100644 rtl8139-switch-to-use-qemu_receive_packe.patch create mode 100644 s390x-add-have_virtio_ccw.patch create mode 100644 s390x-modularize-virtio-gpu-ccw.patch create mode 100644 s390x-move-S390_ADAPTER_SUPPRESSIBLE.patch create mode 100644 sungem-switch-to-use-qemu_receive_packet.patch create mode 100644 tools-virtiofsd-Replace-the-word-whiteli.patch create mode 100644 tx_pkt-switch-to-use-qemu_receive_packet.patch create mode 100644 viriofsd-Add-support-for-FUSE_HANDLE_KIL.patch create mode 100644 virtiofs-drop-remapped-security.capabili.patch create mode 100644 virtiofsd-Save-error-code-early-at-the-f.patch create mode 100644 virtiofsd-extract-lo_do_open-from-lo_ope.patch create mode 100644 virtiofsd-optionally-return-inode-pointe.patch create mode 100644 virtiofsd-prevent-opening-of-special-fil.patch create mode 100644 xen-block-Fix-removal-of-backend-instanc.patch diff --git a/9pfs-Fully-restart-unreclaim-loop-CVE-20.patch b/9pfs-Fully-restart-unreclaim-loop-CVE-20.patch index f7d93ac4..bdf9d1c8 100644 --- a/9pfs-Fully-restart-unreclaim-loop-CVE-20.patch +++ b/9pfs-Fully-restart-unreclaim-loop-CVE-20.patch @@ -3,7 +3,7 @@ Date: Thu, 14 Jan 2021 17:04:12 +0100 Subject: 9pfs: Fully restart unreclaim loop (CVE-2021-20181) Git-commit: 89fbea8737e8f7b954745a1ffc4238d377055305 -Reference: bsc#1182137 +References: bsc#1182137 Depending on the client activity, the server can be asked to open a huge number of file descriptors and eventually hit RLIMIT_NOFILE. This is diff --git a/PPC-KVM-Disable-mmu-notifier-check.patch b/PPC-KVM-Disable-mmu-notifier-check.patch index 65bf621e..1289266c 100644 --- a/PPC-KVM-Disable-mmu-notifier-check.patch +++ b/PPC-KVM-Disable-mmu-notifier-check.patch @@ -14,7 +14,7 @@ Signed-off-by: Bruce Rogers 1 file changed, 2 insertions(+) diff --git a/softmmu/physmem.c b/softmmu/physmem.c -index 3027747c0302c0904db2568eabb8..402a33cb95d898db6a951563c168 100644 +index 2cd1de4a2c46814f10c60fc1b8e5..2b06d754afdea5215fead91d3419 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -1957,11 +1957,13 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr, diff --git a/block-Fix-deadlock-in-bdrv_co_yield_to_d.patch b/block-Fix-deadlock-in-bdrv_co_yield_to_d.patch index 291676f5..e9c4effe 100644 --- a/block-Fix-deadlock-in-bdrv_co_yield_to_d.patch +++ b/block-Fix-deadlock-in-bdrv_co_yield_to_d.patch @@ -2,7 +2,7 @@ From: Kevin Wolf Date: Thu, 3 Dec 2020 18:23:11 +0100 Subject: block: Fix deadlock in bdrv_co_yield_to_drain() -Git-commit 960d5fb3e8ee09bc5f1a5c84f66dce42a6cef920 +Git-commit: 960d5fb3e8ee09bc5f1a5c84f66dce42a6cef920 If bdrv_co_yield_to_drain() is called for draining a block node that runs in a different AioContext, it keeps that AioContext locked while it diff --git a/block-Fix-locking-in-qmp_block_resize.patch b/block-Fix-locking-in-qmp_block_resize.patch index 377601cb..113d105c 100644 --- a/block-Fix-locking-in-qmp_block_resize.patch +++ b/block-Fix-locking-in-qmp_block_resize.patch @@ -2,7 +2,7 @@ From: Kevin Wolf Date: Thu, 3 Dec 2020 18:23:10 +0100 Subject: block: Fix locking in qmp_block_resize() -Git-commit 8089eab2bd5fb160b038e64e14cf7ffb3f37091e +Git-commit: 8089eab2bd5fb160b038e64e14cf7ffb3f37091e The drain functions assume that we hold the AioContext lock of the drained block node. Make sure to actually take the lock. diff --git a/bundles.tar.xz b/bundles.tar.xz index aac01974..70b10930 100644 --- a/bundles.tar.xz +++ b/bundles.tar.xz @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5eea7b1721613d6f843d6e94469431d4382e88e106bff9ac121acfcab88df9fc -size 79240 +oid sha256:b1d2867d10746cf923467f5bddfbf443f001f1363dba4c9c099fc395ac8c2e75 +size 100056 diff --git a/cadence_gem-switch-to-use-qemu_receive_p.patch b/cadence_gem-switch-to-use-qemu_receive_p.patch new file mode 100644 index 00000000..bc3ce304 --- /dev/null +++ b/cadence_gem-switch-to-use-qemu_receive_p.patch @@ -0,0 +1,39 @@ +From: Alexander Bulekov +Date: Mon, 1 Mar 2021 14:33:43 -0500 +Subject: cadence_gem: switch to use qemu_receive_packet() for loopback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Git-commit: e73adfbeec9d4e008630c814759052ed945c3fed + +This patch switches to use qemu_receive_packet() which can detect +reentrancy and return early. + +This is intended to address CVE-2021-3416. + +Cc: Prasad J Pandit +Cc: qemu-stable@nongnu.org +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Alexander Bulekov +Signed-off-by: Jason Wang +Signed-off-by: Bruce Rogers +--- + hw/net/cadence_gem.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c +index 7a534691f1f43ab4fefaf2f82dc9..43b760e3f1b7fb9bf0d116361713 100644 +--- a/hw/net/cadence_gem.c ++++ b/hw/net/cadence_gem.c +@@ -1275,8 +1275,8 @@ static void gem_transmit(CadenceGEMState *s) + /* Send the packet somewhere */ + if (s->phy_loop || (s->regs[GEM_NWCTRL] & + GEM_NWCTRL_LOCALLOOP)) { +- gem_receive(qemu_get_queue(s->nic), s->tx_packet, +- total_bytes); ++ qemu_receive_packet(qemu_get_queue(s->nic), s->tx_packet, ++ total_bytes); + } else { + qemu_send_packet(qemu_get_queue(s->nic), s->tx_packet, + total_bytes); diff --git a/config.sh b/config.sh index 3dfe773b..de202fb4 100644 --- a/config.sh +++ b/config.sh @@ -4,6 +4,9 @@ # The next few VARIABLES are to be edited as required: +# Package name. (In multibuild, it's the base package). Used to ref spec file. +PKG=qemu + # Here is the git repo which tracks a separate upstream git based project # We take this approach so we can have our own tags and branches, and store # the patches in git for others to access outside of the bundle. @@ -27,11 +30,6 @@ NEXT_RELEASE_IS_MAJOR=1 # We can do so by specifing the value here: #SEABIOS_VERSION=1.13.0 -# Temporary directories used by this script -GIT_DIR=/dev/shm/qemu-factory-git-dir -CMP_DIR=/dev/shm/qemu-factory-cmp-dir -BUNDLE_DIR=/dev/shm/qemu-factory-bundle-dir - # In following, use 1 or 0 as needed (representing true or false respectively) NUMBERED_PATCHES=0 diff --git a/dp8393x-switch-to-use-qemu_receive_packe.patch b/dp8393x-switch-to-use-qemu_receive_packe.patch new file mode 100644 index 00000000..cafeac9d --- /dev/null +++ b/dp8393x-switch-to-use-qemu_receive_packe.patch @@ -0,0 +1,36 @@ +From: Jason Wang +Date: Wed, 24 Feb 2021 12:57:40 +0800 +Subject: dp8393x: switch to use qemu_receive_packet() for loopback packet +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Git-commit: 331d2ac9ea307c990dc86e6493e8f0c48d14bb33 + +This patch switches to use qemu_receive_packet() which can detect +reentrancy and return early. + +This is intended to address CVE-2021-3416. + +Cc: Prasad J Pandit +Cc: qemu-stable@nongnu.org +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Bruce Rogers +--- + hw/net/dp8393x.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c +index 205c0decc535724de568023e9f23..533a8304d0bc4b7b8a7750389cc0 100644 +--- a/hw/net/dp8393x.c ++++ b/hw/net/dp8393x.c +@@ -506,7 +506,7 @@ static void dp8393x_do_transmit_packets(dp8393xState *s) + s->regs[SONIC_TCR] |= SONIC_TCR_CRSL; + if (nc->info->can_receive(nc)) { + s->loopback_packet = 1; +- nc->info->receive(nc, s->tx_buffer, tx_len); ++ qemu_receive_packet(nc, s->tx_buffer, tx_len); + } + } else { + /* Transmit packet */ diff --git a/e1000-switch-to-use-qemu_receive_packet-.patch b/e1000-switch-to-use-qemu_receive_packet-.patch new file mode 100644 index 00000000..33d80fac --- /dev/null +++ b/e1000-switch-to-use-qemu_receive_packet-.patch @@ -0,0 +1,36 @@ +From: Jason Wang +Date: Wed, 24 Feb 2021 12:13:22 +0800 +Subject: e1000: switch to use qemu_receive_packet() for loopback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Git-commit: 1caff0340f49c93d535c6558a5138d20d475315c + +This patch switches to use qemu_receive_packet() which can detect +reentrancy and return early. + +This is intended to address CVE-2021-3416. + +Cc: Prasad J Pandit +Cc: qemu-stable@nongnu.org +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Jason Wang +Signed-off-by: Bruce Rogers +--- + hw/net/e1000.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/net/e1000.c b/hw/net/e1000.c +index 02a446b89bae0dec0acdefa54760..c3564c7ce814004f72ab42854542 100644 +--- a/hw/net/e1000.c ++++ b/hw/net/e1000.c +@@ -546,7 +546,7 @@ e1000_send_packet(E1000State *s, const uint8_t *buf, int size) + + NetClientState *nc = qemu_get_queue(s->nic); + if (s->phy_reg[PHY_CTRL] & MII_CR_LOOPBACK) { +- nc->info->receive(nc, buf, size); ++ qemu_receive_packet(nc, buf, size); + } else { + qemu_send_packet(nc, buf, size); + } diff --git a/hw-arm-virt-Disable-pl011-clock-migratio.patch b/hw-arm-virt-Disable-pl011-clock-migratio.patch new file mode 100644 index 00000000..a4f03cbe --- /dev/null +++ b/hw-arm-virt-Disable-pl011-clock-migratio.patch @@ -0,0 +1,87 @@ +From: Gavin Shan +Date: Thu, 18 Mar 2021 10:38:01 +0800 +Subject: hw/arm/virt: Disable pl011 clock migration if needed + +Git-commit: e6fa978d8343ec7cf20b9c8b2dcb390646242457 + +A clock is added by commit aac63e0e6ea3 ("hw/char/pl011: add a clock +input") since v5.2.0 which corresponds to virt-5.2 machine type. It +causes backwards migration failure from upstream to downstream (v5.1.0) +when the machine type is specified with virt-5.1. + +This fixes the issue by following instructions from section "Connecting +subsections to properties" in docs/devel/migration.rst. With this applied, +the PL011 clock is migrated based on the machine type. + + virt-5.2 or newer: migration + virt-5.1 or older: non-migration + +Cc: qemu-stable@nongnu.org # v5.2.0+ +Fixes: aac63e0e6ea3 ("hw/char/pl011: add a clock input") +Suggested-by: Andrew Jones +Signed-off-by: Gavin Shan +Reviewed-by: Andrew Jones +Message-id: 20210318023801.18287-1-gshan@redhat.com +Signed-off-by: Peter Maydell +Signed-off-by: Bruce Rogers +--- + hw/char/pl011.c | 9 +++++++++ + hw/core/machine.c | 1 + + include/hw/char/pl011.h | 1 + + 3 files changed, 11 insertions(+) + +diff --git a/hw/char/pl011.c b/hw/char/pl011.c +index ede16c781c9abcbeaf3ffb8f5c73..74cfa6cd663e397fdc4ba6d3bfe9 100644 +--- a/hw/char/pl011.c ++++ b/hw/char/pl011.c +@@ -321,10 +321,18 @@ static const MemoryRegionOps pl011_ops = { + .endianness = DEVICE_NATIVE_ENDIAN, + }; + ++static bool pl011_clock_needed(void *opaque) ++{ ++ PL011State *s = PL011(opaque); ++ ++ return s->migrate_clk; ++} ++ + static const VMStateDescription vmstate_pl011_clock = { + .name = "pl011/clock", + .version_id = 1, + .minimum_version_id = 1, ++ .needed = pl011_clock_needed, + .fields = (VMStateField[]) { + VMSTATE_CLOCK(clk, PL011State), + VMSTATE_END_OF_LIST() +@@ -362,6 +370,7 @@ static const VMStateDescription vmstate_pl011 = { + + static Property pl011_properties[] = { + DEFINE_PROP_CHR("chardev", PL011State, chr), ++ DEFINE_PROP_BOOL("migrate-clk", PL011State, migrate_clk, true), + DEFINE_PROP_END_OF_LIST(), + }; + +diff --git a/hw/core/machine.c b/hw/core/machine.c +index 9e83400ecbfdd1c8ab20a54ff39c..72ceba57def38ca9dd5c683a71c4 100644 +--- a/hw/core/machine.c ++++ b/hw/core/machine.c +@@ -36,6 +36,7 @@ GlobalProperty hw_compat_5_1[] = { + { "virtio-scsi-device", "num_queues", "1"}, + { "nvme", "use-intel-id", "on"}, + { "pvpanic", "events", "1"}, /* PVPANIC_PANICKED */ ++ { "pl011", "migrate-clk", "off" }, + }; + const size_t hw_compat_5_1_len = G_N_ELEMENTS(hw_compat_5_1); + +diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h +index 33e5e5317b82caaf39078a10b821..dc2c90eedca7b5f23d9db0c3a4ec 100644 +--- a/include/hw/char/pl011.h ++++ b/include/hw/char/pl011.h +@@ -50,6 +50,7 @@ struct PL011State { + CharBackend chr; + qemu_irq irq[6]; + Clock *clk; ++ bool migrate_clk; + const unsigned char *id; + }; + diff --git a/hw-s390x-modularize-virtio-gpu-ccw.patch b/hw-s390x-modularize-virtio-gpu-ccw.patch deleted file mode 100644 index e4e3a426..00000000 --- a/hw-s390x-modularize-virtio-gpu-ccw.patch +++ /dev/null @@ -1,248 +0,0 @@ -From: Halil Pasic -Date: Tue, 2 Mar 2021 18:35:44 +0100 -Subject: hw/s390x: modularize virtio-gpu-ccw - -Git-commit: 0000000000000000000000000000000000000000 -References: bsc#1181103 - -Since the virtio-gpu-ccw device depends on the hw-display-virtio-gpu -module, which provides the type virtio-gpu-device, packaging the -hw-display-virtio-gpu module as a separate package that may or may not -be installed along with the qemu package leads to problems. Namely if -the hw-display-virtio-gpu is absent, qemu continues to advertise -virtio-gpu-ccw, but it aborts not only when one attempts using -virtio-gpu-ccw, but also when libvirtd's capability probing tries -to instantiate the type to introspect it. - -Let us thus introduce a module named hw-s390x-virtio-gpu-ccw that -is going to provide the virtio-gpu-ccw device. The hw-s390x prefix -was chosen because it is not a portable device. Because registering -virtio-gpu-ccw would make non-s390x emulator fail due to a missing -parent type, if built as a module, before registering it, we check -if the ancestor types are already registered. - -With virtio-gpu-ccw built as a module, the correct way to package a -modularized qemu is to require that hw-display-virtio-gpu must be -installed whenever the module hw-s390x-virtio-gpu-ccw. - -The definition S390_ADAPTER_SUPPRESSIBLE was moved to "cpu.h", per -suggestion of Thomas Huth. From interface design perspective, IMHO, not -a good thing as it belongs to the public interface of -css_register_io_adapters(). We did this because CONFIG_KVM requeires -NEED_CPU_H and Thomas, and other commenters did not like the -consequences of that. - -Moving the interrupt related declarations to s390_flic.h was suggested -by Cornelia Huck. - -Signed-off-by: Halil Pasic -Signed-off-by: Bruce Rogers ---- - hw/s390x/meson.build | 7 ++++- - hw/s390x/virtio-ccw-gpu.c | 5 ++++ - include/hw/s390x/css.h | 7 ----- - include/hw/s390x/s390_flic.h | 3 +++ - include/qom/object.h | 10 ++++++++ - qom/object.c | 50 ++++++++++++++++++++++++++++++++++++ - target/s390x/cpu.h | 9 ++++--- - util/module.c | 1 + - 8 files changed, 81 insertions(+), 11 deletions(-) - -diff --git a/hw/s390x/meson.build b/hw/s390x/meson.build -index e53b7a69930a27dd030994ab6a54..1c7baa629cd71f3b62b69dc0cf7c 100644 ---- a/hw/s390x/meson.build -+++ b/hw/s390x/meson.build -@@ -34,7 +34,6 @@ virtio_ss.add(files('virtio-ccw.c')) - virtio_ss.add(when: 'CONFIG_VIRTIO_BALLOON', if_true: files('virtio-ccw-balloon.c')) - virtio_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio-ccw-blk.c')) - virtio_ss.add(when: 'CONFIG_VIRTIO_CRYPTO', if_true: files('virtio-ccw-crypto.c')) --virtio_ss.add(when: 'CONFIG_VIRTIO_GPU', if_true: files('virtio-ccw-gpu.c')) - virtio_ss.add(when: 'CONFIG_VIRTIO_INPUT', if_true: files('virtio-ccw-input.c')) - virtio_ss.add(when: 'CONFIG_VIRTIO_NET', if_true: files('virtio-ccw-net.c')) - virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-ccw-rng.c')) -@@ -46,3 +45,9 @@ virtio_ss.add(when: 'CONFIG_VHOST_USER_FS', if_true: files('vhost-user-fs-ccw.c' - s390x_ss.add_all(when: 'CONFIG_VIRTIO_CCW', if_true: virtio_ss) - - hw_arch += {'s390x': s390x_ss} -+ -+hw_s390x_modules = {} -+virtio_gpu_ccw_ss = ss.source_set() -+virtio_gpu_ccw_ss.add(when: 'CONFIG_VIRTIO_GPU', if_true: [files('virtio-ccw-gpu.c'), pixman]) -+hw_s390x_modules += {'virtio-gpu-ccw': virtio_gpu_ccw_ss} -+modules += {'hw-s390x': hw_s390x_modules} -diff --git a/hw/s390x/virtio-ccw-gpu.c b/hw/s390x/virtio-ccw-gpu.c -index c301e2586bde8aff7333ea029c02..ccdf6ac20f3946e9480b8aae4d99 100644 ---- a/hw/s390x/virtio-ccw-gpu.c -+++ b/hw/s390x/virtio-ccw-gpu.c -@@ -62,6 +62,11 @@ static const TypeInfo virtio_ccw_gpu = { - - static void virtio_ccw_gpu_register(void) - { -+#ifdef CONFIG_MODULES -+ if (!type_ancestors_registered(&virtio_ccw_gpu)) { -+ return; -+ } -+#endif - type_register_static(&virtio_ccw_gpu); - } - -diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h -index 08c869ab0afc18f34fb28056ce29..7858666307a1baaf2586dce56c07 100644 ---- a/include/hw/s390x/css.h -+++ b/include/hw/s390x/css.h -@@ -12,7 +12,6 @@ - #ifndef CSS_H - #define CSS_H - --#include "cpu.h" - #include "hw/s390x/adapter.h" - #include "hw/s390x/s390_flic.h" - #include "hw/s390x/ioinst.h" -@@ -233,12 +232,6 @@ uint32_t css_get_adapter_id(CssIoAdapterType type, uint8_t isc); - void css_register_io_adapters(CssIoAdapterType type, bool swap, bool maskable, - uint8_t flags, Error **errp); - --#ifndef CONFIG_KVM --#define S390_ADAPTER_SUPPRESSIBLE 0x01 --#else --#define S390_ADAPTER_SUPPRESSIBLE KVM_S390_ADAPTER_SUPPRESSIBLE --#endif -- - #ifndef CONFIG_USER_ONLY - SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid, - uint16_t schid); -diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h -index e91b15d2d6af5feb2e7e7284bfbd..3907a13d07664bad96d466b3d20a 100644 ---- a/include/hw/s390x/s390_flic.h -+++ b/include/hw/s390x/s390_flic.h -@@ -134,6 +134,9 @@ void s390_flic_init(void); - S390FLICState *s390_get_flic(void); - QEMUS390FLICState *s390_get_qemu_flic(S390FLICState *fs); - S390FLICStateClass *s390_get_flic_class(S390FLICState *fs); -+void s390_crw_mchk(void); -+void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, -+ uint32_t io_int_parm, uint32_t io_int_word); - bool ais_needed(void *opaque); - - #endif /* HW_S390_FLIC_H */ -diff --git a/include/qom/object.h b/include/qom/object.h -index d378f13a116a6845966489e7436e..990bdb601b2a5c7caeba5340c880 100644 ---- a/include/qom/object.h -+++ b/include/qom/object.h -@@ -814,6 +814,16 @@ ObjectClass *object_get_class(Object *obj); - */ - const char *object_get_typename(const Object *obj); - -+/** -+ * type_ancestors_registered: -+ * @info: The #TypeInfo of the type -+ * -+ * Returns: true if all the ancestor types, that is classes and interfaces this -+ * type inherits form are all already registered, false if there is an ancestor -+ * that ain't registered yet -+ */ -+bool type_ancestors_registered(const TypeInfo *info); -+ - /** - * type_register_static: - * @info: The #TypeInfo of the new type. -diff --git a/qom/object.c b/qom/object.c -index 10653552334549241cd5672d7a02..8b8cd1bdc9d176af921315b9cc2f 100644 ---- a/qom/object.c -+++ b/qom/object.c -@@ -281,6 +281,56 @@ static void object_property_free(gpointer data) - g_free(prop); - } - -+static TypeImpl *type_get_parent_const(const TypeImpl *ti) -+{ -+ return ti->parent_type ? ti->parent_type : type_get_by_name(ti->parent); -+} -+ -+ -+static bool __type_ancestors_registered(const TypeImpl *ti) -+{ -+ TypeImpl *parent; -+ int i; -+ -+ if (!ti) { -+ return false; -+ } -+ -+ if (ti->class) { -+ /* fully initialized */ -+ return true; -+ } -+ -+ for (i = 0; i < ti->num_interfaces; i++) { -+ if (!type_get_by_name(ti->interfaces[i].typename)) { -+ return false; -+ } -+ } -+ if (ti->parent) { -+ parent = type_get_parent_const(ti); -+ if (!parent) { -+ return false; -+ } -+ return __type_ancestors_registered(parent); -+ } -+ return true; -+} -+ -+bool type_ancestors_registered(const TypeInfo *info) -+{ -+ int i; -+ -+ for (i = 0; info->interfaces && info->interfaces[i].type; i++) { -+ if (!type_get_by_name(info->interfaces[i].type)) { -+ return false; -+ } -+ } -+ if (info->parent) { -+ return __type_ancestors_registered(type_get_by_name(info->parent)); -+ } -+ return true; -+} -+ - static void type_initialize(TypeImpl *ti) - { - TypeImpl *parent; -diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h -index 60d434d5edd55c59cfe7e345967c..b434b905c0ae337c62ddcc9d7e34 100644 ---- a/target/s390x/cpu.h -+++ b/target/s390x/cpu.h -@@ -40,6 +40,12 @@ - - #define S390_MAX_CPUS 248 - -+#ifndef CONFIG_KVM -+#define S390_ADAPTER_SUPPRESSIBLE 0x01 -+#else -+#define S390_ADAPTER_SUPPRESSIBLE KVM_S390_ADAPTER_SUPPRESSIBLE -+#endif -+ - typedef struct PSW { - uint64_t mask; - uint64_t addr; -@@ -806,9 +812,6 @@ int cpu_s390x_signal_handler(int host_signum, void *pinfo, void *puc); - - - /* interrupt.c */ --void s390_crw_mchk(void); --void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, -- uint32_t io_int_parm, uint32_t io_int_word); - #define RA_IGNORED 0 - void s390_program_interrupt(CPUS390XState *env, uint32_t code, uintptr_t ra); - /* service interrupts are floating therefore we must not pass an cpustate */ -diff --git a/util/module.c b/util/module.c -index c65060c167df236d6e2163472708..cbe89fede628c3674e49194ee688 100644 ---- a/util/module.c -+++ b/util/module.c -@@ -304,6 +304,7 @@ static struct { - { "virtio-gpu-pci-base", "hw-", "display-virtio-gpu-pci" }, - { "virtio-gpu-pci", "hw-", "display-virtio-gpu-pci" }, - { "vhost-user-gpu-pci", "hw-", "display-virtio-gpu-pci" }, -+ { "virtio-gpu-ccw", "hw-", "s390x-virtio-gpu-ccw" }, - { "virtio-vga-base", "hw-", "display-virtio-vga" }, - { "virtio-vga", "hw-", "display-virtio-vga" }, - { "vhost-user-vga", "hw-", "display-virtio-vga" }, diff --git a/hw-sd-sd-Actually-perform-the-erase-oper.patch b/hw-sd-sd-Actually-perform-the-erase-oper.patch new file mode 100644 index 00000000..013def03 --- /dev/null +++ b/hw-sd-sd-Actually-perform-the-erase-oper.patch @@ -0,0 +1,69 @@ +From: Bin Meng +Date: Sat, 20 Feb 2021 16:58:13 +0800 +Subject: hw/sd: sd: Actually perform the erase operation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Git-commit: 818a5cdcfcf0a55d60b59b2cb74482ef4ba6b205 +References: bsc#1175144, CVE-2020-17380, bsc#1176681, CVE-2020-25085 +References: bsc#1182282, CVE-2021-3409 + +At present the sd_erase() does not erase the requested range of card +data to 0xFFs. Let's make the erase operation actually happen. + +Signed-off-by: Bin Meng +Message-Id: <1613811493-58815-1-git-send-email-bmeng.cn@gmail.com> +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Bruce Rogers +--- + hw/sd/sd.c | 22 +++++++++++++--------- + 1 file changed, 13 insertions(+), 9 deletions(-) + +diff --git a/hw/sd/sd.c b/hw/sd/sd.c +index 6719cda1a0db8e6afa04c2b23915..26a5ae4d202656b4d04547cac8b8 100644 +--- a/hw/sd/sd.c ++++ b/hw/sd/sd.c +@@ -779,10 +779,12 @@ static void sd_blk_write(SDState *sd, uint64_t addr, uint32_t len) + + static void sd_erase(SDState *sd) + { +- int i; + uint64_t erase_start = sd->erase_start; + uint64_t erase_end = sd->erase_end; + bool sdsc = true; ++ uint64_t wpnum; ++ uint64_t erase_addr; ++ int erase_len = 1 << HWBLOCK_SHIFT; + + trace_sdcard_erase(sd->erase_start, sd->erase_end); + if (sd->erase_start == INVALID_ADDRESS +@@ -811,17 +813,19 @@ static void sd_erase(SDState *sd) + sd->erase_end = INVALID_ADDRESS; + sd->csd[14] |= 0x40; + +- /* Only SDSC cards support write protect groups */ +- if (sdsc) { +- erase_start = sd_addr_to_wpnum(erase_start); +- erase_end = sd_addr_to_wpnum(erase_end); +- +- for (i = erase_start; i <= erase_end; i++) { +- assert(i < sd->wpgrps_size); +- if (test_bit(i, sd->wp_groups)) { ++ memset(sd->data, 0xff, erase_len); ++ for (erase_addr = erase_start; erase_addr <= erase_end; ++ erase_addr += erase_len) { ++ if (sdsc) { ++ /* Only SDSC cards support write protect groups */ ++ wpnum = sd_addr_to_wpnum(erase_addr); ++ assert(wpnum < sd->wpgrps_size); ++ if (test_bit(wpnum, sd->wp_groups)) { + sd->card_status |= WP_ERASE_SKIP; ++ continue; + } + } ++ BLK_WRITE_BLOCK(erase_addr, erase_len); + } + } + diff --git a/hw-sd-sd-Fix-build-error-when-DEBUG_SD-i.patch b/hw-sd-sd-Fix-build-error-when-DEBUG_SD-i.patch new file mode 100644 index 00000000..86599b2e --- /dev/null +++ b/hw-sd-sd-Fix-build-error-when-DEBUG_SD-i.patch @@ -0,0 +1,35 @@ +From: Bin Meng +Date: Sun, 28 Feb 2021 13:06:09 +0800 +Subject: hw/sd: sd: Fix build error when DEBUG_SD is on +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Git-commit: a78d9f27b73de3c42f376540bd1d1d0570eb1fa3 +References: bsc#1175144, CVE-2020-17380, bsc#1176681, CVE-2020-25085 +References: bsc#1182282, CVE-2021-3409 + +"qemu-common.h" should be included to provide the forward declaration +of qemu_hexdump() when DEBUG_SD is on. + +Signed-off-by: Bin Meng +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20210228050609.24779-1-bmeng.cn@gmail.com> +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Bruce Rogers +--- + hw/sd/sd.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/sd/sd.c b/hw/sd/sd.c +index a4ea365f4a74afd30dee5b16eebe..6719cda1a0db8e6afa04c2b23915 100644 +--- a/hw/sd/sd.c ++++ b/hw/sd/sd.c +@@ -46,6 +46,7 @@ + #include "qemu/timer.h" + #include "qemu/log.h" + #include "qemu/module.h" ++#include "qemu-common.h" + #include "sdmmc-internal.h" + #include "trace.h" + diff --git a/hw-sd-sd-Move-the-sd_block_-read-write-a.patch b/hw-sd-sd-Move-the-sd_block_-read-write-a.patch new file mode 100644 index 00000000..8bfa6c93 --- /dev/null +++ b/hw-sd-sd-Move-the-sd_block_-read-write-a.patch @@ -0,0 +1,83 @@ +From: Bin Meng +Date: Tue, 16 Feb 2021 23:02:21 +0800 +Subject: hw/sd: sd: Move the sd_block_{read, write} and macros ahead +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Git-commit: ce6ea2efc5fb308ebf11339276f60215fe0ec44c +References: bsc#1175144, CVE-2020-17380, bsc#1176681, CVE-2020-25085 +References: bsc#1182282, CVE-2021-3409 + +These APIs and macros may be referenced by functions that are +currently before them. Move them ahead a little bit. + +Signed-off-by: Bin Meng +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20210216150225.27996-5-bmeng.cn@gmail.com> +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Bruce Rogers +--- + hw/sd/sd.c | 42 +++++++++++++++++++++--------------------- + 1 file changed, 21 insertions(+), 21 deletions(-) + +diff --git a/hw/sd/sd.c b/hw/sd/sd.c +index 5cdcd54cfcbf467342b2e485ac3e..ac48140251de7845a01ab4ad656c 100644 +--- a/hw/sd/sd.c ++++ b/hw/sd/sd.c +@@ -755,6 +755,27 @@ void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert) + qemu_set_irq(insert, sd->blk ? blk_is_inserted(sd->blk) : 0); + } + ++static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len) ++{ ++ trace_sdcard_read_block(addr, len); ++ if (!sd->blk || blk_pread(sd->blk, addr, sd->data, len) < 0) { ++ fprintf(stderr, "sd_blk_read: read error on host side\n"); ++ } ++} ++ ++static void sd_blk_write(SDState *sd, uint64_t addr, uint32_t len) ++{ ++ trace_sdcard_write_block(addr, len); ++ if (!sd->blk || blk_pwrite(sd->blk, addr, sd->data, len, 0) < 0) { ++ fprintf(stderr, "sd_blk_write: write error on host side\n"); ++ } ++} ++ ++#define BLK_READ_BLOCK(a, len) sd_blk_read(sd, a, len) ++#define BLK_WRITE_BLOCK(a, len) sd_blk_write(sd, a, len) ++#define APP_READ_BLOCK(a, len) memset(sd->data, 0xec, len) ++#define APP_WRITE_BLOCK(a, len) ++ + static void sd_erase(SDState *sd) + { + int i; +@@ -1815,27 +1836,6 @@ send_response: + return rsplen; + } + +-static void sd_blk_read(SDState *sd, uint64_t addr, uint32_t len) +-{ +- trace_sdcard_read_block(addr, len); +- if (!sd->blk || blk_pread(sd->blk, addr, sd->data, len) < 0) { +- fprintf(stderr, "sd_blk_read: read error on host side\n"); +- } +-} +- +-static void sd_blk_write(SDState *sd, uint64_t addr, uint32_t len) +-{ +- trace_sdcard_write_block(addr, len); +- if (!sd->blk || blk_pwrite(sd->blk, addr, sd->data, len, 0) < 0) { +- fprintf(stderr, "sd_blk_write: write error on host side\n"); +- } +-} +- +-#define BLK_READ_BLOCK(a, len) sd_blk_read(sd, a, len) +-#define BLK_WRITE_BLOCK(a, len) sd_blk_write(sd, a, len) +-#define APP_READ_BLOCK(a, len) memset(sd->data, 0xec, len) +-#define APP_WRITE_BLOCK(a, len) +- + void sd_write_byte(SDState *sd, uint8_t value) + { + int i; diff --git a/hw-sd-sd-Skip-write-protect-groups-check.patch b/hw-sd-sd-Skip-write-protect-groups-check.patch new file mode 100644 index 00000000..2900274f --- /dev/null +++ b/hw-sd-sd-Skip-write-protect-groups-check.patch @@ -0,0 +1,71 @@ +From: Bin Meng +Date: Tue, 16 Feb 2021 23:02:22 +0800 +Subject: hw/sd: sd: Skip write protect groups check in sd_erase() for high + capacity cards +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Git-commit: 2473dc4022458dcc05ec367ce97edbef29d7e50c +References: bsc#1175144, CVE-2020-17380, bsc#1176681, CVE-2020-25085 +References: bsc#1182282, CVE-2021-3409 + +High capacity cards don't support write protection hence we should +not perform the write protect groups check in sd_erase() for them. + +Signed-off-by: Bin Meng +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <20210216150225.27996-6-bmeng.cn@gmail.com> +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Bruce Rogers +--- + hw/sd/sd.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +diff --git a/hw/sd/sd.c b/hw/sd/sd.c +index ac48140251de7845a01ab4ad656c..a4ea365f4a74afd30dee5b16eebe 100644 +--- a/hw/sd/sd.c ++++ b/hw/sd/sd.c +@@ -781,6 +781,7 @@ static void sd_erase(SDState *sd) + int i; + uint64_t erase_start = sd->erase_start; + uint64_t erase_end = sd->erase_end; ++ bool sdsc = true; + + trace_sdcard_erase(sd->erase_start, sd->erase_end); + if (sd->erase_start == INVALID_ADDRESS +@@ -795,6 +796,7 @@ static void sd_erase(SDState *sd) + /* High capacity memory card: erase units are 512 byte blocks */ + erase_start *= 512; + erase_end *= 512; ++ sdsc = false; + } + + if (sd->erase_start > sd->size || sd->erase_end > sd->size) { +@@ -804,16 +806,20 @@ static void sd_erase(SDState *sd) + return; + } + +- erase_start = sd_addr_to_wpnum(erase_start); +- erase_end = sd_addr_to_wpnum(erase_end); + sd->erase_start = INVALID_ADDRESS; + sd->erase_end = INVALID_ADDRESS; + sd->csd[14] |= 0x40; + +- for (i = erase_start; i <= erase_end; i++) { +- assert(i < sd->wpgrps_size); +- if (test_bit(i, sd->wp_groups)) { +- sd->card_status |= WP_ERASE_SKIP; ++ /* Only SDSC cards support write protect groups */ ++ if (sdsc) { ++ erase_start = sd_addr_to_wpnum(erase_start); ++ erase_end = sd_addr_to_wpnum(erase_end); ++ ++ for (i = erase_start; i <= erase_end; i++) { ++ assert(i < sd->wpgrps_size); ++ if (test_bit(i, sd->wp_groups)) { ++ sd->card_status |= WP_ERASE_SKIP; ++ } + } + } + } diff --git a/hw-sd-sdhci-Correctly-set-the-controller.patch b/hw-sd-sdhci-Correctly-set-the-controller.patch new file mode 100644 index 00000000..2803b1cd --- /dev/null +++ b/hw-sd-sdhci-Correctly-set-the-controller.patch @@ -0,0 +1,70 @@ +From: Bin Meng +Date: Wed, 3 Mar 2021 20:26:37 +0800 +Subject: hw/sd: sdhci: Correctly set the controller status for ADMA +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Git-commit: bc6f28995ff88f5d82c38afcfd65406f0ae375aa +References: bsc#1175144, CVE-2020-17380, bsc#1176681, CVE-2020-25085 +References: bsc#1182282, CVE-2021-3409 + +When an ADMA transfer is started, the codes forget to set the +controller status to indicate a transfer is in progress. + +With this fix, the following 2 reproducers: + +https://paste.debian.net/plain/1185136 +https://paste.debian.net/plain/1185141 + +cannot be reproduced with the following QEMU command line: + +$ qemu-system-x86_64 -nographic -machine accel=qtest -m 512M \ + -nodefaults -device sdhci-pci,sd-spec-version=3 \ + -drive if=sd,index=0,file=null-co://,format=raw,id=mydrive \ + -device sd-card,drive=mydrive -qtest stdio + +Cc: qemu-stable@nongnu.org +Fixes: CVE-2020-17380 +Fixes: CVE-2020-25085 +Fixes: CVE-2021-3409 +Fixes: d7dfca0807a0 ("hw/sdhci: introduce standard SD host controller") +Reported-by: Alexander Bulekov +Reported-by: Cornelius Aschermann (Ruhr-Universität Bochum) +Reported-by: Sergej Schumilo (Ruhr-Universität Bochum) +Reported-by: Simon Wörner (Ruhr-Universität Bochum) +Buglink: https://bugs.launchpad.net/qemu/+bug/1892960 +Buglink: https://bugs.launchpad.net/qemu/+bug/1909418 +Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1928146 +Tested-by: Alexander Bulekov +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Bin Meng +Message-Id: <20210303122639.20004-4-bmeng.cn@gmail.com> +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Bruce Rogers +--- + hw/sd/sdhci.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c +index 006426b64da916a3be86afcf75cf..a1639bbd39ca264fa24f27978d54 100644 +--- a/hw/sd/sdhci.c ++++ b/hw/sd/sdhci.c +@@ -769,7 +769,9 @@ static void sdhci_do_adma(SDHCIState *s) + + switch (dscr.attr & SDHC_ADMA_ATTR_ACT_MASK) { + case SDHC_ADMA_ATTR_ACT_TRAN: /* data transfer */ ++ s->prnsts |= SDHC_DATA_INHIBIT | SDHC_DAT_LINE_ACTIVE; + if (s->trnmod & SDHC_TRNS_READ) { ++ s->prnsts |= SDHC_DOING_READ; + while (length) { + if (s->data_count == 0) { + sdbus_read_data(&s->sdbus, s->fifo_buffer, block_size); +@@ -797,6 +799,7 @@ static void sdhci_do_adma(SDHCIState *s) + } + } + } else { ++ s->prnsts |= SDHC_DOING_WRITE; + while (length) { + begin = s->data_count; + if ((length + begin) < block_size) { diff --git a/hw-sd-sdhci-Don-t-transfer-any-data-when.patch b/hw-sd-sdhci-Don-t-transfer-any-data-when.patch new file mode 100644 index 00000000..e56e1c1a --- /dev/null +++ b/hw-sd-sdhci-Don-t-transfer-any-data-when.patch @@ -0,0 +1,87 @@ +From: Bin Meng +Date: Wed, 3 Mar 2021 20:26:35 +0800 +Subject: hw/sd: sdhci: Don't transfer any data when command time out +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Git-commit: b263d8f928001b5cfa2a993ea43b7a5b3a1811e8 +References: bsc#1175144, CVE-2020-17380, bsc#1176681, CVE-2020-25085 +References: bsc#1182282, CVE-2021-3409 + +At the end of sdhci_send_command(), it starts a data transfer if the +command register indicates data is associated. But the data transfer +should only be initiated when the command execution has succeeded. + +With this fix, the following reproducer: + +outl 0xcf8 0x80001810 +outl 0xcfc 0xe1068000 +outl 0xcf8 0x80001804 +outw 0xcfc 0x7 +write 0xe106802c 0x1 0x0f +write 0xe1068004 0xc 0x2801d10101fffffbff28a384 +write 0xe106800c 0x1f 0x9dacbbcad9e8f7061524334251606f7e8d9cabbac9d8e7f60514233241505f +write 0xe1068003 0x28 0x80d000251480d000252280d000253080d000253e80d000254c80d000255a80d000256880d0002576 +write 0xe1068003 0x1 0xfe + +cannot be reproduced with the following QEMU command line: + +$ qemu-system-x86_64 -nographic -M pc-q35-5.0 \ + -device sdhci-pci,sd-spec-version=3 \ + -drive if=sd,index=0,file=null-co://,format=raw,id=mydrive \ + -device sd-card,drive=mydrive \ + -monitor none -serial none -qtest stdio + +Cc: qemu-stable@nongnu.org +Fixes: CVE-2020-17380 +Fixes: CVE-2020-25085 +Fixes: CVE-2021-3409 +Fixes: d7dfca0807a0 ("hw/sdhci: introduce standard SD host controller") +Reported-by: Alexander Bulekov +Reported-by: Cornelius Aschermann (Ruhr-Universität Bochum) +Reported-by: Sergej Schumilo (Ruhr-Universität Bochum) +Reported-by: Simon Wörner (Ruhr-Universität Bochum) +Buglink: https://bugs.launchpad.net/qemu/+bug/1892960 +Buglink: https://bugs.launchpad.net/qemu/+bug/1909418 +Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1928146 +Acked-by: Alistair Francis +Tested-by: Alexander Bulekov +Tested-by: Philippe Mathieu-Daudé +Signed-off-by: Bin Meng +Message-Id: <20210303122639.20004-2-bmeng.cn@gmail.com> +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Bruce Rogers +--- + hw/sd/sdhci.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c +index 2f8b74a84f75ae72153dbffab8c1..5a4a156341eb1e330022f1128ba1 100644 +--- a/hw/sd/sdhci.c ++++ b/hw/sd/sdhci.c +@@ -326,6 +326,7 @@ static void sdhci_send_command(SDHCIState *s) + SDRequest request; + uint8_t response[16]; + int rlen; ++ bool timeout = false; + + s->errintsts = 0; + s->acmd12errsts = 0; +@@ -349,6 +350,7 @@ static void sdhci_send_command(SDHCIState *s) + trace_sdhci_response16(s->rspreg[3], s->rspreg[2], + s->rspreg[1], s->rspreg[0]); + } else { ++ timeout = true; + trace_sdhci_error("timeout waiting for command response"); + if (s->errintstsen & SDHC_EISEN_CMDTIMEOUT) { + s->errintsts |= SDHC_EIS_CMDTIMEOUT; +@@ -369,7 +371,7 @@ static void sdhci_send_command(SDHCIState *s) + + sdhci_update_irq(s); + +- if (s->blksize && (s->cmdreg & SDHC_CMD_DATA_PRESENT)) { ++ if (!timeout && s->blksize && (s->cmdreg & SDHC_CMD_DATA_PRESENT)) { + s->data_count = 0; + sdhci_data_transfer(s); + } diff --git a/hw-sd-sdhci-Don-t-write-to-SDHC_SYSAD-re.patch b/hw-sd-sdhci-Don-t-write-to-SDHC_SYSAD-re.patch new file mode 100644 index 00000000..25450ef3 --- /dev/null +++ b/hw-sd-sdhci-Don-t-write-to-SDHC_SYSAD-re.patch @@ -0,0 +1,105 @@ +From: Bin Meng +Date: Wed, 3 Mar 2021 20:26:36 +0800 +Subject: hw/sd: sdhci: Don't write to SDHC_SYSAD register when transfer is in + progress +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Git-commit: 8be45cc947832b3c02144c9d52921f499f2d77fe +References: bsc#1175144, CVE-2020-17380, bsc#1176681, CVE-2020-25085 +References: bsc#1182282, CVE-2021-3409 + +Per "SD Host Controller Standard Specification Version 7.00" +chapter 2.2.1 SDMA System Address Register: + +This register can be accessed only if no transaction is executing +(i.e., after a transaction has stopped). + +With this fix, the following reproducer: + +outl 0xcf8 0x80001010 +outl 0xcfc 0xfbefff00 +outl 0xcf8 0x80001001 +outl 0xcfc 0x06000000 +write 0xfbefff2c 0x1 0x05 +write 0xfbefff0f 0x1 0x37 +write 0xfbefff0a 0x1 0x01 +write 0xfbefff0f 0x1 0x29 +write 0xfbefff0f 0x1 0x02 +write 0xfbefff0f 0x1 0x03 +write 0xfbefff04 0x1 0x01 +write 0xfbefff05 0x1 0x01 +write 0xfbefff07 0x1 0x02 +write 0xfbefff0c 0x1 0x33 +write 0xfbefff0e 0x1 0x20 +write 0xfbefff0f 0x1 0x00 +write 0xfbefff2a 0x1 0x01 +write 0xfbefff0c 0x1 0x00 +write 0xfbefff03 0x1 0x00 +write 0xfbefff05 0x1 0x00 +write 0xfbefff2a 0x1 0x02 +write 0xfbefff0c 0x1 0x32 +write 0xfbefff01 0x1 0x01 +write 0xfbefff02 0x1 0x01 +write 0xfbefff03 0x1 0x01 + +cannot be reproduced with the following QEMU command line: + +$ qemu-system-x86_64 -nographic -machine accel=qtest -m 512M \ + -nodefaults -device sdhci-pci,sd-spec-version=3 \ + -drive if=sd,index=0,file=null-co://,format=raw,id=mydrive \ + -device sd-card,drive=mydrive -qtest stdio + +Cc: qemu-stable@nongnu.org +Fixes: CVE-2020-17380 +Fixes: CVE-2020-25085 +Fixes: CVE-2021-3409 +Fixes: d7dfca0807a0 ("hw/sdhci: introduce standard SD host controller") +Reported-by: Alexander Bulekov +Reported-by: Cornelius Aschermann (Ruhr-Universität Bochum) +Reported-by: Sergej Schumilo (Ruhr-Universität Bochum) +Reported-by: Simon Wörner (Ruhr-Universität Bochum) +Buglink: https://bugs.launchpad.net/qemu/+bug/1892960 +Buglink: https://bugs.launchpad.net/qemu/+bug/1909418 +Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1928146 +Tested-by: Alexander Bulekov +Signed-off-by: Bin Meng +Message-Id: <20210303122639.20004-3-bmeng.cn@gmail.com> +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Bruce Rogers +--- + hw/sd/sdhci.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c +index 5a4a156341eb1e330022f1128ba1..006426b64da916a3be86afcf75cf 100644 +--- a/hw/sd/sdhci.c ++++ b/hw/sd/sdhci.c +@@ -1122,15 +1122,17 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) + + switch (offset & ~0x3) { + case SDHC_SYSAD: +- s->sdmasysad = (s->sdmasysad & mask) | value; +- MASKED_WRITE(s->sdmasysad, mask, value); +- /* Writing to last byte of sdmasysad might trigger transfer */ +- if (!(mask & 0xFF000000) && TRANSFERRING_DATA(s->prnsts) && s->blkcnt && +- s->blksize && SDHC_DMA_TYPE(s->hostctl1) == SDHC_CTRL_SDMA) { +- if (s->trnmod & SDHC_TRNS_MULTI) { +- sdhci_sdma_transfer_multi_blocks(s); +- } else { +- sdhci_sdma_transfer_single_block(s); ++ if (!TRANSFERRING_DATA(s->prnsts)) { ++ s->sdmasysad = (s->sdmasysad & mask) | value; ++ MASKED_WRITE(s->sdmasysad, mask, value); ++ /* Writing to last byte of sdmasysad might trigger transfer */ ++ if (!(mask & 0xFF000000) && s->blkcnt && s->blksize && ++ SDHC_DMA_TYPE(s->hostctl1) == SDHC_CTRL_SDMA) { ++ if (s->trnmod & SDHC_TRNS_MULTI) { ++ sdhci_sdma_transfer_multi_blocks(s); ++ } else { ++ sdhci_sdma_transfer_single_block(s); ++ } + } + } + break; diff --git a/hw-sd-sdhci-Limit-block-size-only-when-S.patch b/hw-sd-sdhci-Limit-block-size-only-when-S.patch new file mode 100644 index 00000000..704d672e --- /dev/null +++ b/hw-sd-sdhci-Limit-block-size-only-when-S.patch @@ -0,0 +1,52 @@ +From: Bin Meng +Date: Wed, 3 Mar 2021 20:26:38 +0800 +Subject: hw/sd: sdhci: Limit block size only when SDHC_BLKSIZE register is + writable +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Git-commit: 5cd7aa3451b76bb19c0f6adc2b931f091e5d7fcd +References: bsc#1175144, CVE-2020-17380, bsc#1176681, CVE-2020-25085 +References: bsc#1182282, CVE-2021-3409 + +The codes to limit the maximum block size is only necessary when +SDHC_BLKSIZE register is writable. + +Tested-by: Alexander Bulekov +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Bin Meng +Message-Id: <20210303122639.20004-5-bmeng.cn@gmail.com> +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Bruce Rogers +--- + hw/sd/sdhci.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c +index a1639bbd39ca264fa24f27978d54..51c2a3ffde21314afe2a2c84fa1b 100644 +--- a/hw/sd/sdhci.c ++++ b/hw/sd/sdhci.c +@@ -1143,15 +1143,15 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) + if (!TRANSFERRING_DATA(s->prnsts)) { + MASKED_WRITE(s->blksize, mask, extract32(value, 0, 12)); + MASKED_WRITE(s->blkcnt, mask >> 16, value >> 16); +- } + +- /* Limit block size to the maximum buffer size */ +- if (extract32(s->blksize, 0, 12) > s->buf_maxsz) { +- qemu_log_mask(LOG_GUEST_ERROR, "%s: Size 0x%x is larger than " +- "the maximum buffer 0x%x\n", __func__, s->blksize, +- s->buf_maxsz); ++ /* Limit block size to the maximum buffer size */ ++ if (extract32(s->blksize, 0, 12) > s->buf_maxsz) { ++ qemu_log_mask(LOG_GUEST_ERROR, "%s: Size 0x%x is larger than " ++ "the maximum buffer 0x%x\n", __func__, s->blksize, ++ s->buf_maxsz); + +- s->blksize = deposit32(s->blksize, 0, 12, s->buf_maxsz); ++ s->blksize = deposit32(s->blksize, 0, 12, s->buf_maxsz); ++ } + } + + break; diff --git a/hw-sd-sdhci-Reset-the-data-pointer-of-s-.patch b/hw-sd-sdhci-Reset-the-data-pointer-of-s-.patch new file mode 100644 index 00000000..cecfa4c8 --- /dev/null +++ b/hw-sd-sdhci-Reset-the-data-pointer-of-s-.patch @@ -0,0 +1,95 @@ +From: Bin Meng +Date: Wed, 3 Mar 2021 20:26:39 +0800 +Subject: hw/sd: sdhci: Reset the data pointer of s->fifo_buffer[] when a + different block size is programmed +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Git-commit: cffb446e8fd19a14e1634c7a3a8b07be3f01d5c9 +References: bsc#1175144, CVE-2020-17380, bsc#1176681, CVE-2020-25085 +References: bsc#1182282, CVE-2021-3409 + +If the block size is programmed to a different value from the +previous one, reset the data pointer of s->fifo_buffer[] so that +s->fifo_buffer[] can be filled in using the new block size in +the next transfer. + +With this fix, the following reproducer: + +outl 0xcf8 0x80001010 +outl 0xcfc 0xe0000000 +outl 0xcf8 0x80001001 +outl 0xcfc 0x06000000 +write 0xe000002c 0x1 0x05 +write 0xe0000005 0x1 0x02 +write 0xe0000007 0x1 0x01 +write 0xe0000028 0x1 0x10 +write 0x0 0x1 0x23 +write 0x2 0x1 0x08 +write 0xe000000c 0x1 0x01 +write 0xe000000e 0x1 0x20 +write 0xe000000f 0x1 0x00 +write 0xe000000c 0x1 0x32 +write 0xe0000004 0x2 0x0200 +write 0xe0000028 0x1 0x00 +write 0xe0000003 0x1 0x40 + +cannot be reproduced with the following QEMU command line: + +$ qemu-system-x86_64 -nographic -machine accel=qtest -m 512M \ + -nodefaults -device sdhci-pci,sd-spec-version=3 \ + -drive if=sd,index=0,file=null-co://,format=raw,id=mydrive \ + -device sd-card,drive=mydrive -qtest stdio + +Cc: qemu-stable@nongnu.org +Fixes: CVE-2020-17380 +Fixes: CVE-2020-25085 +Fixes: CVE-2021-3409 +Fixes: d7dfca0807a0 ("hw/sdhci: introduce standard SD host controller") +Reported-by: Alexander Bulekov +Reported-by: Cornelius Aschermann (Ruhr-Universität Bochum) +Reported-by: Sergej Schumilo (Ruhr-Universität Bochum) +Reported-by: Simon Wörner (Ruhr-Universität Bochum) +Buglink: https://bugs.launchpad.net/qemu/+bug/1892960 +Buglink: https://bugs.launchpad.net/qemu/+bug/1909418 +Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1928146 +Tested-by: Alexander Bulekov +Signed-off-by: Bin Meng +Message-Id: <20210303122639.20004-6-bmeng.cn@gmail.com> +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Bruce Rogers +--- + hw/sd/sdhci.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c +index 51c2a3ffde21314afe2a2c84fa1b..3c35942161097989e626f5cfd887 100644 +--- a/hw/sd/sdhci.c ++++ b/hw/sd/sdhci.c +@@ -1141,6 +1141,8 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) + break; + case SDHC_BLKSIZE: + if (!TRANSFERRING_DATA(s->prnsts)) { ++ uint16_t blksize = s->blksize; ++ + MASKED_WRITE(s->blksize, mask, extract32(value, 0, 12)); + MASKED_WRITE(s->blkcnt, mask >> 16, value >> 16); + +@@ -1152,6 +1154,16 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) + + s->blksize = deposit32(s->blksize, 0, 12, s->buf_maxsz); + } ++ ++ /* ++ * If the block size is programmed to a different value from ++ * the previous one, reset the data pointer of s->fifo_buffer[] ++ * so that s->fifo_buffer[] can be filled in using the new block ++ * size in the next transfer. ++ */ ++ if (blksize != s->blksize) { ++ s->data_count = 0; ++ } + } + + break; diff --git a/iotests-Fix-_send_qemu_cmd-with-bash-5.1.patch b/iotests-Fix-_send_qemu_cmd-with-bash-5.1.patch index 2737de83..6ef7f7cc 100644 --- a/iotests-Fix-_send_qemu_cmd-with-bash-5.1.patch +++ b/iotests-Fix-_send_qemu_cmd-with-bash-5.1.patch @@ -2,7 +2,7 @@ From: Max Reitz Date: Thu, 17 Dec 2020 16:38:03 +0100 Subject: iotests: Fix _send_qemu_cmd with bash 5.1 -Git-commit 0e72078128229bf9efb542e396ab44bf91b91340 +Git-commit: 0e72078128229bf9efb542e396ab44bf91b91340 References: boo#1181054 With bash 5.1, the output of the following script changes: diff --git a/lan9118-switch-to-use-qemu_receive_packe.patch b/lan9118-switch-to-use-qemu_receive_packe.patch new file mode 100644 index 00000000..ae224ff6 --- /dev/null +++ b/lan9118-switch-to-use-qemu_receive_packe.patch @@ -0,0 +1,37 @@ +From: Alexander Bulekov +Date: Mon, 1 Mar 2021 14:35:30 -0500 +Subject: lan9118: switch to use qemu_receive_packet() for loopback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Git-commit: 37cee01784ff0df13e5209517e1b3594a5e792d1 + +This patch switches to use qemu_receive_packet() which can detect +reentrancy and return early. + +This is intended to address CVE-2021-3416. + +Cc: Prasad J Pandit +Cc: qemu-stable@nongnu.org +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Jason Wang +Signed-off-by: Bruce Rogers +--- + hw/net/lan9118.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c +index 13d469fe24fd8dd3a03eb2b60a58..da82dc1ad32be5e176aea93e7b11 100644 +--- a/hw/net/lan9118.c ++++ b/hw/net/lan9118.c +@@ -669,7 +669,7 @@ static void do_tx_packet(lan9118_state *s) + /* FIXME: Honor TX disable, and allow queueing of packets. */ + if (s->phy_control & 0x4000) { + /* This assumes the receive routine doesn't touch the VLANClient. */ +- lan9118_receive(qemu_get_queue(s->nic), s->txp->data, s->txp->len); ++ qemu_receive_packet(qemu_get_queue(s->nic), s->txp->data, s->txp->len); + } else { + qemu_send_packet(qemu_get_queue(s->nic), s->txp->data, s->txp->len); + } diff --git a/memory-clamp-cached-translation-in-case-.patch b/memory-clamp-cached-translation-in-case-.patch new file mode 100644 index 00000000..31c99f18 --- /dev/null +++ b/memory-clamp-cached-translation-in-case-.patch @@ -0,0 +1,137 @@ +From: Paolo Bonzini +Date: Tue, 1 Dec 2020 09:29:56 -0500 +Subject: memory: clamp cached translation in case it points to an MMIO region + +Git-commit: 4bfb024bc76973d40a359476dc0291f46e435442 +References: bsc#1179686, CVE-2020-27821 + +In using the address_space_translate_internal API, address_space_cache_init +forgot one piece of advice that can be found in the code for +address_space_translate_internal: + + /* MMIO registers can be expected to perform full-width accesses based only + * on their address, without considering adjacent registers that could + * decode to completely different MemoryRegions. When such registers + * exist (e.g. I/O ports 0xcf8 and 0xcf9 on most PC chipsets), MMIO + * regions overlap wildly. For this reason we cannot clamp the accesses + * here. + * + * If the length is small (as is the case for address_space_ldl/stl), + * everything works fine. If the incoming length is large, however, + * the caller really has to do the clamping through memory_access_size. + */ + +address_space_cache_init is exactly one such case where "the incoming length +is large", therefore we need to clamp the resulting length---not to +memory_access_size though, since we are not doing an access yet, but to +the size of the resulting section. This ensures that subsequent accesses +to the cached MemoryRegionSection will be in range. + +With this patch, the enclosed testcase notices that the used ring does +not fit into the MSI-X table and prints a "qemu-system-x86_64: Cannot map used" +error. + +Signed-off-by: Paolo Bonzini +Signed-off-by: Bruce Rogers +--- + softmmu/physmem.c | 10 ++++++++ + tests/qtest/fuzz-test.c | 51 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 61 insertions(+) + +diff --git a/softmmu/physmem.c b/softmmu/physmem.c +index 3027747c0302c0904db2568eabb8..2cd1de4a2c46814f10c60fc1b8e5 100644 +--- a/softmmu/physmem.c ++++ b/softmmu/physmem.c +@@ -3255,6 +3255,7 @@ int64_t address_space_cache_init(MemoryRegionCache *cache, + AddressSpaceDispatch *d; + hwaddr l; + MemoryRegion *mr; ++ Int128 diff; + + assert(len > 0); + +@@ -3263,6 +3264,15 @@ int64_t address_space_cache_init(MemoryRegionCache *cache, + d = flatview_to_dispatch(cache->fv); + cache->mrs = *address_space_translate_internal(d, addr, &cache->xlat, &l, true); + ++ /* ++ * cache->xlat is now relative to cache->mrs.mr, not to the section itself. ++ * Take that into account to compute how many bytes are there between ++ * cache->xlat and the end of the section. ++ */ ++ diff = int128_sub(cache->mrs.size, ++ int128_make64(cache->xlat - cache->mrs.offset_within_region)); ++ l = int128_get64(int128_min(diff, int128_make64(l))); ++ + mr = cache->mrs.mr; + memory_region_ref(mr); + if (memory_access_is_direct(mr, is_write)) { +diff --git a/tests/qtest/fuzz-test.c b/tests/qtest/fuzz-test.c +index 9cb4c42bdea5cefa23473ed41b10..28739248e24d0b41d8ea5defebb8 100644 +--- a/tests/qtest/fuzz-test.c ++++ b/tests/qtest/fuzz-test.c +@@ -47,6 +47,55 @@ static void test_lp1878642_pci_bus_get_irq_level_assert(void) + qtest_outl(s, 0x5d02, 0xebed205d); + } + ++/* ++ * Here a MemoryRegionCache pointed to an MMIO region but had a ++ * larger size than the underlying region. ++ */ ++static void test_mmio_oob_from_memory_region_cache(void) ++{ ++ QTestState *s; ++ ++ s = qtest_init("-M pc-q35-5.2 -display none -m 512M " ++ "-device virtio-scsi,num_queues=8,addr=03.0 "); ++ ++ qtest_outl(s, 0xcf8, 0x80001811); ++ qtest_outb(s, 0xcfc, 0x6e); ++ qtest_outl(s, 0xcf8, 0x80001824); ++ qtest_outl(s, 0xcf8, 0x80001813); ++ qtest_outl(s, 0xcfc, 0xa080000); ++ qtest_outl(s, 0xcf8, 0x80001802); ++ qtest_outl(s, 0xcfc, 0x5a175a63); ++ qtest_outb(s, 0x6e08, 0x9e); ++ qtest_writeb(s, 0x9f003, 0xff); ++ qtest_writeb(s, 0x9f004, 0x01); ++ qtest_writeb(s, 0x9e012, 0x0e); ++ qtest_writeb(s, 0x9e01b, 0x0e); ++ qtest_writeb(s, 0x9f006, 0x01); ++ qtest_writeb(s, 0x9f008, 0x01); ++ qtest_writeb(s, 0x9f00a, 0x01); ++ qtest_writeb(s, 0x9f00c, 0x01); ++ qtest_writeb(s, 0x9f00e, 0x01); ++ qtest_writeb(s, 0x9f010, 0x01); ++ qtest_writeb(s, 0x9f012, 0x01); ++ qtest_writeb(s, 0x9f014, 0x01); ++ qtest_writeb(s, 0x9f016, 0x01); ++ qtest_writeb(s, 0x9f018, 0x01); ++ qtest_writeb(s, 0x9f01a, 0x01); ++ qtest_writeb(s, 0x9f01c, 0x01); ++ qtest_writeb(s, 0x9f01e, 0x01); ++ qtest_writeb(s, 0x9f020, 0x01); ++ qtest_writeb(s, 0x9f022, 0x01); ++ qtest_writeb(s, 0x9f024, 0x01); ++ qtest_writeb(s, 0x9f026, 0x01); ++ qtest_writeb(s, 0x9f028, 0x01); ++ qtest_writeb(s, 0x9f02a, 0x01); ++ qtest_writeb(s, 0x9f02c, 0x01); ++ qtest_writeb(s, 0x9f02e, 0x01); ++ qtest_writeb(s, 0x9f030, 0x01); ++ qtest_outb(s, 0x6e10, 0x00); ++ qtest_quit(s); ++} ++ + int main(int argc, char **argv) + { + const char *arch = qtest_get_arch(); +@@ -58,6 +107,8 @@ int main(int argc, char **argv) + test_lp1878263_megasas_zero_iov_cnt); + qtest_add_func("fuzz/test_lp1878642_pci_bus_get_irq_level_assert", + test_lp1878642_pci_bus_get_irq_level_assert); ++ qtest_add_func("fuzz/test_mmio_oob_from_memory_region_cache", ++ test_mmio_oob_from_memory_region_cache); + } + + return g_test_run(); diff --git a/module-for-virtio-gpu-pre-load-module-to.patch b/module-for-virtio-gpu-pre-load-module-to.patch index fb6e5882..e50b2e2a 100644 --- a/module-for-virtio-gpu-pre-load-module-to.patch +++ b/module-for-virtio-gpu-pre-load-module-to.patch @@ -28,10 +28,10 @@ index 944d403cbd1535cc121af76a94f2..4b42dd285eeac1ba12e5c9e18ac0 100644 #endif diff --git a/qom/object.c b/qom/object.c -index 8b8cd1bdc9d176af921315b9cc2f..588f09ae22ba33bd6c3298995fc6 100644 +index 10653552334549241cd5672d7a02..6f301fec34d103b0b07bc41d107c 100644 --- a/qom/object.c +++ b/qom/object.c -@@ -566,6 +566,18 @@ static void object_initialize_with_type(Object *obj, size_t size, TypeImpl *type +@@ -516,6 +516,18 @@ static void object_initialize_with_type(Object *obj, size_t size, TypeImpl *type object_post_init_with_type(obj, type); } diff --git a/msf2-mac-switch-to-use-qemu_receive_pack.patch b/msf2-mac-switch-to-use-qemu_receive_pack.patch new file mode 100644 index 00000000..f81daca4 --- /dev/null +++ b/msf2-mac-switch-to-use-qemu_receive_pack.patch @@ -0,0 +1,36 @@ +From: Jason Wang +Date: Wed, 24 Feb 2021 13:00:01 +0800 +Subject: msf2-mac: switch to use qemu_receive_packet() for loopback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Git-commit: 26194a58f4eb83c5bdf4061a1628508084450ba1 + +This patch switches to use qemu_receive_packet() which can detect +reentrancy and return early. + +This is intended to address CVE-2021-3416. + +Cc: Prasad J Pandit +Cc: qemu-stable@nongnu.org +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Jason Wang +Signed-off-by: Bruce Rogers +--- + hw/net/msf2-emac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/net/msf2-emac.c b/hw/net/msf2-emac.c +index 32ba9e84124496fe22f165095d61..3e6206044f8b441c9222f28cc1ec 100644 +--- a/hw/net/msf2-emac.c ++++ b/hw/net/msf2-emac.c +@@ -158,7 +158,7 @@ static void msf2_dma_tx(MSF2EmacState *s) + * R_CFG1 bit 0 is set. + */ + if (s->regs[R_CFG1] & R_CFG1_LB_EN_MASK) { +- nc->info->receive(nc, buf, size); ++ qemu_receive_packet(nc, buf, size); + } else { + qemu_send_packet(nc, buf, size); + } diff --git a/net-introduce-qemu_receive_packet.patch b/net-introduce-qemu_receive_packet.patch new file mode 100644 index 00000000..4cb798dc --- /dev/null +++ b/net-introduce-qemu_receive_packet.patch @@ -0,0 +1,171 @@ +From: Jason Wang +Date: Wed, 24 Feb 2021 11:44:36 +0800 +Subject: net: introduce qemu_receive_packet() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Git-commit: 705df5466c98f3efdd2b68d3b31dad86858acad7 +References: bsc#1182968, CVE-2021-3416 +Some NIC supports loopback mode and this is done by calling +nc->info->receive() directly which in fact suppresses the effort of +reentrancy check that is done in qemu_net_queue_send(). + +Unfortunately we can't use qemu_net_queue_send() here since for +loopback there's no sender as peer, so this patch introduce a +qemu_receive_packet() which is used for implementing loopback mode +for a NIC with this check. + +NIC that supports loopback mode will be converted to this helper. + +This is intended to address CVE-2021-3416. + +Cc: Prasad J Pandit +Reviewed-by: Philippe Mathieu-Daudé +Cc: qemu-stable@nongnu.org +Signed-off-by: Jason Wang +Signed-off-by: Bruce Rogers +--- + include/net/net.h | 5 +++++ + include/net/queue.h | 8 ++++++++ + net/net.c | 38 +++++++++++++++++++++++++++++++------- + net/queue.c | 22 ++++++++++++++++++++++ + 4 files changed, 66 insertions(+), 7 deletions(-) + +diff --git a/include/net/net.h b/include/net/net.h +index 778fc787ca14d3e1bc6f59d76cc6..03f058ecb0c1e8d4f4d3a8cb6c58 100644 +--- a/include/net/net.h ++++ b/include/net/net.h +@@ -143,12 +143,17 @@ void *qemu_get_nic_opaque(NetClientState *nc); + void qemu_del_net_client(NetClientState *nc); + typedef void (*qemu_nic_foreach)(NICState *nic, void *opaque); + void qemu_foreach_nic(qemu_nic_foreach func, void *opaque); ++int qemu_can_receive_packet(NetClientState *nc); + int qemu_can_send_packet(NetClientState *nc); + ssize_t qemu_sendv_packet(NetClientState *nc, const struct iovec *iov, + int iovcnt); + ssize_t qemu_sendv_packet_async(NetClientState *nc, const struct iovec *iov, + int iovcnt, NetPacketSent *sent_cb); + ssize_t qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size); ++ssize_t qemu_receive_packet(NetClientState *nc, const uint8_t *buf, int size); ++ssize_t qemu_receive_packet_iov(NetClientState *nc, ++ const struct iovec *iov, ++ int iovcnt); + ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size); + ssize_t qemu_send_packet_async(NetClientState *nc, const uint8_t *buf, + int size, NetPacketSent *sent_cb); +diff --git a/include/net/queue.h b/include/net/queue.h +index c0269bb1dc436a912e2abc75db3b..9f2f289d7719ca1ed78604c37b65 100644 +--- a/include/net/queue.h ++++ b/include/net/queue.h +@@ -55,6 +55,14 @@ void qemu_net_queue_append_iov(NetQueue *queue, + + void qemu_del_net_queue(NetQueue *queue); + ++ssize_t qemu_net_queue_receive(NetQueue *queue, ++ const uint8_t *data, ++ size_t size); ++ ++ssize_t qemu_net_queue_receive_iov(NetQueue *queue, ++ const struct iovec *iov, ++ int iovcnt); ++ + ssize_t qemu_net_queue_send(NetQueue *queue, + NetClientState *sender, + unsigned flags, +diff --git a/net/net.c b/net/net.c +index af35fb2db7cd99933d20f8613ab3..cad72a791d3f173eaaa66b8feb50 100644 +--- a/net/net.c ++++ b/net/net.c +@@ -528,6 +528,17 @@ int qemu_set_vnet_be(NetClientState *nc, bool is_be) + #endif + } + ++int qemu_can_receive_packet(NetClientState *nc) ++{ ++ if (nc->receive_disabled) { ++ return 0; ++ } else if (nc->info->can_receive && ++ !nc->info->can_receive(nc)) { ++ return 0; ++ } ++ return 1; ++} ++ + int qemu_can_send_packet(NetClientState *sender) + { + int vm_running = runstate_is_running(); +@@ -540,13 +551,7 @@ int qemu_can_send_packet(NetClientState *sender) + return 1; + } + +- if (sender->peer->receive_disabled) { +- return 0; +- } else if (sender->peer->info->can_receive && +- !sender->peer->info->can_receive(sender->peer)) { +- return 0; +- } +- return 1; ++ return qemu_can_receive_packet(sender->peer); + } + + static ssize_t filter_receive_iov(NetClientState *nc, +@@ -679,6 +684,25 @@ ssize_t qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size) + return qemu_send_packet_async(nc, buf, size, NULL); + } + ++ssize_t qemu_receive_packet(NetClientState *nc, const uint8_t *buf, int size) ++{ ++ if (!qemu_can_receive_packet(nc)) { ++ return 0; ++ } ++ ++ return qemu_net_queue_receive(nc->incoming_queue, buf, size); ++} ++ ++ssize_t qemu_receive_packet_iov(NetClientState *nc, const struct iovec *iov, ++ int iovcnt) ++{ ++ if (!qemu_can_receive_packet(nc)) { ++ return 0; ++ } ++ ++ return qemu_net_queue_receive_iov(nc->incoming_queue, iov, iovcnt); ++} ++ + ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size) + { + return qemu_send_packet_async_with_flags(nc, QEMU_NET_PACKET_FLAG_RAW, +diff --git a/net/queue.c b/net/queue.c +index 19e32c80fda730604fe7febf421f..c872d51df8b58518a644a2a8f68b 100644 +--- a/net/queue.c ++++ b/net/queue.c +@@ -182,6 +182,28 @@ static ssize_t qemu_net_queue_deliver_iov(NetQueue *queue, + return ret; + } + ++ssize_t qemu_net_queue_receive(NetQueue *queue, ++ const uint8_t *data, ++ size_t size) ++{ ++ if (queue->delivering) { ++ return 0; ++ } ++ ++ return qemu_net_queue_deliver(queue, NULL, 0, data, size); ++} ++ ++ssize_t qemu_net_queue_receive_iov(NetQueue *queue, ++ const struct iovec *iov, ++ int iovcnt) ++{ ++ if (queue->delivering) { ++ return 0; ++ } ++ ++ return qemu_net_queue_deliver_iov(queue, NULL, 0, iov, iovcnt); ++} ++ + ssize_t qemu_net_queue_send(NetQueue *queue, + NetClientState *sender, + unsigned flags, diff --git a/pcnet-switch-to-use-qemu_receive_packet-.patch b/pcnet-switch-to-use-qemu_receive_packet-.patch new file mode 100644 index 00000000..87181047 --- /dev/null +++ b/pcnet-switch-to-use-qemu_receive_packet-.patch @@ -0,0 +1,38 @@ +From: Alexander Bulekov +Date: Mon, 1 Mar 2021 10:33:34 -0500 +Subject: pcnet: switch to use qemu_receive_packet() for loopback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Git-commit: 99ccfaa1edafd79f7a3a0ff7b58ae4da7c514928 + +This patch switches to use qemu_receive_packet() which can detect +reentrancy and return early. + +This is intended to address CVE-2021-3416. + +Cc: Prasad J Pandit +Cc: qemu-stable@nongnu.org +Buglink: https://bugs.launchpad.net/qemu/+bug/1917085 +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Jason Wang +Signed-off-by: Bruce Rogers +--- + hw/net/pcnet.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c +index f3f18d8598c43aca02ca138aa46e..dcd3fc49481b46a6d4bb7c726572 100644 +--- a/hw/net/pcnet.c ++++ b/hw/net/pcnet.c +@@ -1250,7 +1250,7 @@ txagain: + if (BCR_SWSTYLE(s) == 1) + add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS); + s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC; +- pcnet_receive(qemu_get_queue(s->nic), s->buffer, s->xmit_pos); ++ qemu_receive_packet(qemu_get_queue(s->nic), s->buffer, s->xmit_pos); + s->looptest = 0; + } else { + if (s->nic) { diff --git a/qemu.changes b/qemu.changes index 572ceb3c..f4471353 100644 --- a/qemu.changes +++ b/qemu.changes @@ -1,3 +1,61 @@ +------------------------------------------------------------------- +Tue Mar 30 17:30:11 UTC 2021 - Bruce Rogers + +- Switch method of splitting off hw-s390x-virtio-gpu-ccw.so as a + module to what was accepted upstream (bsc#1181103) +* Patches dropped: + hw-s390x-modularize-virtio-gpu-ccw.patch +* Patches added: + s390x-add-have_virtio_ccw.patch + s390x-modularize-virtio-gpu-ccw.patch + s390x-move-S390_ADAPTER_SUPPRESSIBLE.patch + +------------------------------------------------------------------- +Tue Mar 23 21:52:41 UTC 2021 - Bruce Rogers + +- Fix OOB access in sdhci interface (CVE-2020-17380, bsc#1175144, + CVE-2020-25085, bsc#1176681, CVE-2021-3409, bsc#1182282) + hw-sd-sd-Actually-perform-the-erase-oper.patch + hw-sd-sd-Fix-build-error-when-DEBUG_SD-i.patch + hw-sd-sdhci-Correctly-set-the-controller.patch + hw-sd-sdhci-Don-t-transfer-any-data-when.patch + hw-sd-sdhci-Don-t-write-to-SDHC_SYSAD-re.patch + hw-sd-sdhci-Limit-block-size-only-when-S.patch + hw-sd-sdhci-Reset-the-data-pointer-of-s-.patch + hw-sd-sd-Move-the-sd_block_-read-write-a.patch + hw-sd-sd-Skip-write-protect-groups-check.patch +- Fix potential privilege escalation in virtiofsd tool + (CVE-2021-20263, bsc#1183373) + tools-virtiofsd-Replace-the-word-whiteli.patch + viriofsd-Add-support-for-FUSE_HANDLE_KIL.patch + virtiofsd-extract-lo_do_open-from-lo_ope.patch + virtiofsd-optionally-return-inode-pointe.patch + virtiofsd-prevent-opening-of-special-fil.patch + virtiofs-drop-remapped-security.capabili.patch + virtiofsd-Save-error-code-early-at-the-f.patch +- Fix OOB access (stack overflow) in rtl8139 NIC emulation + (CVE-2021-3416, bsc#1182968) + net-introduce-qemu_receive_packet.patch + rtl8139-switch-to-use-qemu_receive_packe.patch +- Fix OOB access (stack overflow) in other NIC emulations + (CVE-2021-3416) + cadence_gem-switch-to-use-qemu_receive_p.patch + dp8393x-switch-to-use-qemu_receive_packe.patch + e1000-switch-to-use-qemu_receive_packet-.patch + lan9118-switch-to-use-qemu_receive_packe.patch + msf2-mac-switch-to-use-qemu_receive_pack.patch + pcnet-switch-to-use-qemu_receive_packet-.patch + sungem-switch-to-use-qemu_receive_packet.patch + tx_pkt-switch-to-use-qemu_receive_packet.patch +- Fix heap overflow in MSIx emulation (CVE-2020-27821, bsc#1179686) + memory-clamp-cached-translation-in-case-.patch +- Include upstream patches designated as stable material and + reviewed for applicability to include here + hw-arm-virt-Disable-pl011-clock-migratio.patch + xen-block-Fix-removal-of-backend-instanc.patch +- Fix package scripts to not use hard coded paths for temporary + working directories and log files (bsc#1182425) + ------------------------------------------------------------------- Wed Mar 17 13:07:33 UTC 2021 - Bruce Rogers diff --git a/qemu.spec b/qemu.spec index a8aee671..74fffb0f 100644 --- a/qemu.spec +++ b/qemu.spec @@ -137,84 +137,115 @@ Patch00001: block-Simplify-qmp_block_resize-error-pa.patch Patch00002: block-Fix-locking-in-qmp_block_resize.patch Patch00003: block-Fix-deadlock-in-bdrv_co_yield_to_d.patch Patch00004: audio-add-sanity-check.patch -Patch00005: build-no-pie-is-no-functional-linker-fla.patch -Patch00006: block-nfs-fix-int-overflow-in-nfs_client.patch -Patch00007: iotests-Fix-_send_qemu_cmd-with-bash-5.1.patch -Patch00008: tcg-Use-memset-for-large-vector-byte-rep.patch -Patch00009: hw-timer-slavio_timer-Allow-64-bit-acces.patch -Patch00010: target-arm-Fix-MTE0_ACTIVE.patch -Patch00011: target-arm-Don-t-decode-insns-in-the-XSc.patch -Patch00012: hw-net-lan9118-Fix-RX-Status-FIFO-PEEK-v.patch -Patch00013: 9pfs-Fully-restart-unreclaim-loop-CVE-20.patch -Patch00014: target-arm-Introduce-PREDDESC-field-defi.patch -Patch00015: target-arm-Update-PFIRST-PNEXT-for-pred_.patch -Patch00016: target-arm-Update-ZIP-UZP-TRN-for-pred_d.patch -Patch00017: target-arm-Update-REV-PUNPK-for-pred_des.patch -Patch00018: update-linux-headers-Include-const.h.patch -Patch00019: Update-linux-headers-to-5.11-rc2.patch -Patch00020: vfio-ccw-Connect-the-device-request-noti.patch -Patch00021: net-Fix-handling-of-id-in-netdev_add-and.patch -Patch00022: block-Separate-blk_is_writable-and-blk_s.patch -Patch00023: hw-intc-arm_gic-Fix-interrupt-ID-in-GICD.patch -Patch00024: virtio-move-use-disabled-flag-property-t.patch -Patch00025: qemu-nbd-Use-SOMAXCONN-for-socket-listen.patch -Patch00026: qemu-storage-daemon-Enable-object-add.patch -Patch00027: blockjob-Fix-crash-with-IOthread-when-bl.patch -Patch00028: monitor-Fix-assertion-failure-on-shutdow.patch -Patch00029: spice-app-avoid-crash-when-core-spice-mo.patch -Patch00030: i386-acpi-restore-device-paths-for-pre-5.patch -Patch00031: hw-s390x-fix-build-for-virtio-9p-ccw.patch -Patch00032: s390x-pci-restore-missing-Query-PCI-Func.patch -Patch00033: lsilogic-Use-PCIDevice-exit-instead-of-D.patch -Patch00034: vhost-user-blk-fix-blkcfg-num_queues-end.patch -Patch00035: e1000-fail-early-for-evil-descriptor.patch -Patch00036: hw-s390x-modularize-virtio-gpu-ccw.patch -Patch00037: net-vmxnet3-validate-configuration-value.patch -Patch00038: XXX-dont-dump-core-on-sigabort.patch -Patch00039: qemu-binfmt-conf-Modify-default-path.patch -Patch00040: qemu-cvs-gettimeofday.patch -Patch00041: qemu-cvs-ioctl_debug.patch -Patch00042: qemu-cvs-ioctl_nodirection.patch -Patch00043: linux-user-add-binfmt-wrapper-for-argv-0.patch -Patch00044: PPC-KVM-Disable-mmu-notifier-check.patch -Patch00045: linux-user-binfmt-support-host-binaries.patch -Patch00046: linux-user-Fake-proc-cpuinfo.patch -Patch00047: linux-user-use-target_ulong.patch -Patch00048: Make-char-muxer-more-robust-wrt-small-FI.patch -Patch00049: linux-user-lseek-explicitly-cast-non-set.patch -Patch00050: AIO-Reduce-number-of-threads-for-32bit-h.patch -Patch00051: xen_disk-Add-suse-specific-flush-disable.patch -Patch00052: qemu-bridge-helper-reduce-security-profi.patch -Patch00053: qemu-binfmt-conf-use-qemu-ARCH-binfmt.patch -Patch00054: roms-Makefile-pass-a-packaging-timestamp.patch -Patch00055: Raise-soft-address-space-limit-to-hard-l.patch -Patch00056: increase-x86_64-physical-bits-to-42.patch -Patch00057: i8254-Fix-migration-from-SLE11-SP2.patch -Patch00058: acpi_piix4-Fix-migration-from-SLE11-SP2.patch -Patch00059: Make-installed-scripts-explicitly-python.patch -Patch00060: hw-smbios-handle-both-file-formats-regar.patch -Patch00061: xen-add-block-resize-support-for-xen-dis.patch -Patch00062: tests-qemu-iotests-Triple-timeout-of-i-o.patch -Patch00063: tests-Fix-block-tests-to-be-compatible-w.patch -Patch00064: xen-ignore-live-parameter-from-xen-save-.patch -Patch00065: tests-change-error-message-in-test-162.patch -Patch00066: hw-intc-exynos4210_gic-provide-more-room.patch -Patch00067: configure-only-populate-roms-if-softmmu.patch -Patch00068: pc-bios-s390-ccw-net-avoid-warning-about.patch -Patch00069: roms-change-cross-compiler-naming-to-be-.patch -Patch00070: test-add-mapping-from-arch-of-i686-to-qe.patch -Patch00071: configure-remove-pkgversion-from-CONFIG_.patch -Patch00072: docs-add-SUSE-support-statements-to-html.patch -Patch00073: s390x-Fix-stringop-truncation-issue-repo.patch -Patch00074: Revert-qht-constify-qht_statistics_init.patch -Patch00075: qht-Revert-some-constification-in-qht.c.patch -Patch00076: meson-install-ivshmem-client-and-ivshmem.patch -Patch00077: Revert-roms-efirom-tests-uefi-test-tools.patch -Patch00078: Makefile-Don-t-check-pc-bios-as-pre-requ.patch -Patch00079: roms-Makefile-add-cross-file-to-qboot-me.patch -Patch00080: usb-Help-compiler-out-to-avoid-a-warning.patch -Patch00081: module-for-virtio-gpu-pre-load-module-to.patch -Patch00082: qom-handle-case-of-chardev-spice-module-.patch +Patch00005: memory-clamp-cached-translation-in-case-.patch +Patch00006: build-no-pie-is-no-functional-linker-fla.patch +Patch00007: block-nfs-fix-int-overflow-in-nfs_client.patch +Patch00008: iotests-Fix-_send_qemu_cmd-with-bash-5.1.patch +Patch00009: tcg-Use-memset-for-large-vector-byte-rep.patch +Patch00010: hw-timer-slavio_timer-Allow-64-bit-acces.patch +Patch00011: target-arm-Fix-MTE0_ACTIVE.patch +Patch00012: target-arm-Don-t-decode-insns-in-the-XSc.patch +Patch00013: hw-net-lan9118-Fix-RX-Status-FIFO-PEEK-v.patch +Patch00014: 9pfs-Fully-restart-unreclaim-loop-CVE-20.patch +Patch00015: target-arm-Introduce-PREDDESC-field-defi.patch +Patch00016: target-arm-Update-PFIRST-PNEXT-for-pred_.patch +Patch00017: target-arm-Update-ZIP-UZP-TRN-for-pred_d.patch +Patch00018: target-arm-Update-REV-PUNPK-for-pred_des.patch +Patch00019: update-linux-headers-Include-const.h.patch +Patch00020: Update-linux-headers-to-5.11-rc2.patch +Patch00021: vfio-ccw-Connect-the-device-request-noti.patch +Patch00022: net-Fix-handling-of-id-in-netdev_add-and.patch +Patch00023: block-Separate-blk_is_writable-and-blk_s.patch +Patch00024: hw-intc-arm_gic-Fix-interrupt-ID-in-GICD.patch +Patch00025: virtiofsd-extract-lo_do_open-from-lo_ope.patch +Patch00026: virtiofsd-optionally-return-inode-pointe.patch +Patch00027: virtiofsd-prevent-opening-of-special-fil.patch +Patch00028: virtio-move-use-disabled-flag-property-t.patch +Patch00029: qemu-nbd-Use-SOMAXCONN-for-socket-listen.patch +Patch00030: qemu-storage-daemon-Enable-object-add.patch +Patch00031: blockjob-Fix-crash-with-IOthread-when-bl.patch +Patch00032: monitor-Fix-assertion-failure-on-shutdow.patch +Patch00033: tools-virtiofsd-Replace-the-word-whiteli.patch +Patch00034: virtiofsd-Save-error-code-early-at-the-f.patch +Patch00035: viriofsd-Add-support-for-FUSE_HANDLE_KIL.patch +Patch00036: spice-app-avoid-crash-when-core-spice-mo.patch +Patch00037: i386-acpi-restore-device-paths-for-pre-5.patch +Patch00038: virtiofs-drop-remapped-security.capabili.patch +Patch00039: hw-s390x-fix-build-for-virtio-9p-ccw.patch +Patch00040: s390x-pci-restore-missing-Query-PCI-Func.patch +Patch00041: lsilogic-Use-PCIDevice-exit-instead-of-D.patch +Patch00042: vhost-user-blk-fix-blkcfg-num_queues-end.patch +Patch00043: e1000-fail-early-for-evil-descriptor.patch +Patch00044: net-introduce-qemu_receive_packet.patch +Patch00045: e1000-switch-to-use-qemu_receive_packet-.patch +Patch00046: dp8393x-switch-to-use-qemu_receive_packe.patch +Patch00047: msf2-mac-switch-to-use-qemu_receive_pack.patch +Patch00048: sungem-switch-to-use-qemu_receive_packet.patch +Patch00049: tx_pkt-switch-to-use-qemu_receive_packet.patch +Patch00050: rtl8139-switch-to-use-qemu_receive_packe.patch +Patch00051: pcnet-switch-to-use-qemu_receive_packet-.patch +Patch00052: cadence_gem-switch-to-use-qemu_receive_p.patch +Patch00053: lan9118-switch-to-use-qemu_receive_packe.patch +Patch00054: hw-sd-sd-Move-the-sd_block_-read-write-a.patch +Patch00055: hw-sd-sd-Skip-write-protect-groups-check.patch +Patch00056: hw-sd-sd-Fix-build-error-when-DEBUG_SD-i.patch +Patch00057: hw-sd-sd-Actually-perform-the-erase-oper.patch +Patch00058: hw-sd-sdhci-Don-t-transfer-any-data-when.patch +Patch00059: hw-sd-sdhci-Don-t-write-to-SDHC_SYSAD-re.patch +Patch00060: hw-sd-sdhci-Correctly-set-the-controller.patch +Patch00061: hw-sd-sdhci-Limit-block-size-only-when-S.patch +Patch00062: hw-sd-sdhci-Reset-the-data-pointer-of-s-.patch +Patch00063: xen-block-Fix-removal-of-backend-instanc.patch +Patch00064: hw-arm-virt-Disable-pl011-clock-migratio.patch +Patch00065: s390x-move-S390_ADAPTER_SUPPRESSIBLE.patch +Patch00066: s390x-add-have_virtio_ccw.patch +Patch00067: s390x-modularize-virtio-gpu-ccw.patch +Patch00068: net-vmxnet3-validate-configuration-value.patch +Patch00069: XXX-dont-dump-core-on-sigabort.patch +Patch00070: qemu-binfmt-conf-Modify-default-path.patch +Patch00071: qemu-cvs-gettimeofday.patch +Patch00072: qemu-cvs-ioctl_debug.patch +Patch00073: qemu-cvs-ioctl_nodirection.patch +Patch00074: linux-user-add-binfmt-wrapper-for-argv-0.patch +Patch00075: PPC-KVM-Disable-mmu-notifier-check.patch +Patch00076: linux-user-binfmt-support-host-binaries.patch +Patch00077: linux-user-Fake-proc-cpuinfo.patch +Patch00078: linux-user-use-target_ulong.patch +Patch00079: Make-char-muxer-more-robust-wrt-small-FI.patch +Patch00080: linux-user-lseek-explicitly-cast-non-set.patch +Patch00081: AIO-Reduce-number-of-threads-for-32bit-h.patch +Patch00082: xen_disk-Add-suse-specific-flush-disable.patch +Patch00083: qemu-bridge-helper-reduce-security-profi.patch +Patch00084: qemu-binfmt-conf-use-qemu-ARCH-binfmt.patch +Patch00085: roms-Makefile-pass-a-packaging-timestamp.patch +Patch00086: Raise-soft-address-space-limit-to-hard-l.patch +Patch00087: increase-x86_64-physical-bits-to-42.patch +Patch00088: i8254-Fix-migration-from-SLE11-SP2.patch +Patch00089: acpi_piix4-Fix-migration-from-SLE11-SP2.patch +Patch00090: Make-installed-scripts-explicitly-python.patch +Patch00091: hw-smbios-handle-both-file-formats-regar.patch +Patch00092: xen-add-block-resize-support-for-xen-dis.patch +Patch00093: tests-qemu-iotests-Triple-timeout-of-i-o.patch +Patch00094: tests-Fix-block-tests-to-be-compatible-w.patch +Patch00095: xen-ignore-live-parameter-from-xen-save-.patch +Patch00096: tests-change-error-message-in-test-162.patch +Patch00097: hw-intc-exynos4210_gic-provide-more-room.patch +Patch00098: configure-only-populate-roms-if-softmmu.patch +Patch00099: pc-bios-s390-ccw-net-avoid-warning-about.patch +Patch00100: roms-change-cross-compiler-naming-to-be-.patch +Patch00101: test-add-mapping-from-arch-of-i686-to-qe.patch +Patch00102: configure-remove-pkgversion-from-CONFIG_.patch +Patch00103: docs-add-SUSE-support-statements-to-html.patch +Patch00104: s390x-Fix-stringop-truncation-issue-repo.patch +Patch00105: Revert-qht-constify-qht_statistics_init.patch +Patch00106: qht-Revert-some-constification-in-qht.c.patch +Patch00107: meson-install-ivshmem-client-and-ivshmem.patch +Patch00108: Revert-roms-efirom-tests-uefi-test-tools.patch +Patch00109: Makefile-Don-t-check-pc-bios-as-pre-requ.patch +Patch00110: roms-Makefile-add-cross-file-to-qboot-me.patch +Patch00111: usb-Help-compiler-out-to-avoid-a-warning.patch +Patch00112: module-for-virtio-gpu-pre-load-module-to.patch +Patch00113: qom-handle-case-of-chardev-spice-module-.patch # Patches applied in roms/seabios/: Patch01000: seabios-use-python2-explicitly-as-needed.patch Patch01001: seabios-switch-to-python3-as-needed.patch @@ -1115,23 +1146,54 @@ This package records qemu testsuite results and represents successful testing. %patch00069 -p1 %patch00070 -p1 %patch00071 -p1 -%if %{legacy_qemu_kvm} %patch00072 -p1 -%endif %patch00073 -p1 %patch00074 -p1 %patch00075 -p1 %patch00076 -p1 %patch00077 -p1 %patch00078 -p1 -%ifarch aarch64 %patch00079 -p1 -%endif -%ifarch %arm %ix86 ppc %patch00080 -p1 -%endif %patch00081 -p1 %patch00082 -p1 +%patch00083 -p1 +%patch00084 -p1 +%patch00085 -p1 +%patch00086 -p1 +%patch00087 -p1 +%patch00088 -p1 +%patch00089 -p1 +%patch00090 -p1 +%patch00091 -p1 +%patch00092 -p1 +%patch00093 -p1 +%patch00094 -p1 +%patch00095 -p1 +%patch00096 -p1 +%patch00097 -p1 +%patch00098 -p1 +%patch00099 -p1 +%patch00100 -p1 +%patch00101 -p1 +%patch00102 -p1 +%if %{legacy_qemu_kvm} +%patch00103 -p1 +%endif +%patch00104 -p1 +%patch00105 -p1 +%patch00106 -p1 +%patch00107 -p1 +%patch00108 -p1 +%patch00109 -p1 +%ifarch aarch64 +%patch00110 -p1 +%endif +%ifarch %arm %ix86 ppc +%patch00111 -p1 +%endif +%patch00112 -p1 +%patch00113 -p1 %patch01000 -p1 %patch01001 -p1 %patch01002 -p1 diff --git a/qom-handle-case-of-chardev-spice-module-.patch b/qom-handle-case-of-chardev-spice-module-.patch index 74da860d..2fc61da1 100644 --- a/qom-handle-case-of-chardev-spice-module-.patch +++ b/qom-handle-case-of-chardev-spice-module-.patch @@ -14,7 +14,7 @@ Signed-off-by: Bruce Rogers 1 file changed, 6 insertions(+) diff --git a/qom/object.c b/qom/object.c -index 588f09ae22ba33bd6c3298995fc6..97880a0495a95de0adcfedaa4f69 100644 +index 6f301fec34d103b0b07bc41d107c..0dec164192a55d3d9d955d445db9 100644 --- a/qom/object.c +++ b/qom/object.c @@ -236,6 +236,12 @@ static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type) diff --git a/rtl8139-switch-to-use-qemu_receive_packe.patch b/rtl8139-switch-to-use-qemu_receive_packe.patch new file mode 100644 index 00000000..884a337e --- /dev/null +++ b/rtl8139-switch-to-use-qemu_receive_packe.patch @@ -0,0 +1,39 @@ +From: Alexander Bulekov +Date: Fri, 26 Feb 2021 13:47:53 -0500 +Subject: rtl8139: switch to use qemu_receive_packet() for loopback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Git-commit: 5311fb805a4403bba024e83886fa0e7572265de4 +References: bsc#1182968, CVE-2021-3416 + +This patch switches to use qemu_receive_packet() which can detect +reentrancy and return early. + +This is intended to address CVE-2021-3416. + +Cc: Prasad J Pandit +Cc: qemu-stable@nongnu.org +Buglink: https://bugs.launchpad.net/qemu/+bug/1910826 +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Jason Wang +Signed-off-by: Bruce Rogers +--- + hw/net/rtl8139.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c +index ba5ace1ab75cc91330f8f60b25c0..d2dd03e6a5866f4f549af2e97399 100644 +--- a/hw/net/rtl8139.c ++++ b/hw/net/rtl8139.c +@@ -1795,7 +1795,7 @@ static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size, + } + + DPRINTF("+++ transmit loopback mode\n"); +- rtl8139_do_receive(qemu_get_queue(s->nic), buf, size, do_interrupt); ++ qemu_receive_packet(qemu_get_queue(s->nic), buf, size); + + if (iov) { + g_free(buf2); diff --git a/s390x-add-have_virtio_ccw.patch b/s390x-add-have_virtio_ccw.patch new file mode 100644 index 00000000..7aebee48 --- /dev/null +++ b/s390x-add-have_virtio_ccw.patch @@ -0,0 +1,50 @@ +From: Gerd Hoffmann +Date: Wed, 17 Mar 2021 10:56:21 +0100 +Subject: s390x: add have_virtio_ccw + +Git-commit: 2dd9d8cfb4f3bd30d9cdfc2edba5cb7ee5917f4b +References: bsc#1181103 + +Introduce a symbol which can be used to prevent ccw modules +being loaded into system emulators without ccw support. + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Halil Pasic +Tested-by: Halil Pasic +Message-Id: <20210317095622.2839895-3-kraxel@redhat.com> +Signed-off-by: Gerd Hoffmann +Signed-off-by: Bruce Rogers +--- + hw/s390x/virtio-ccw.c | 2 ++ + hw/s390x/virtio-ccw.h | 5 +++++ + 2 files changed, 7 insertions(+) + +diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c +index 4582e94ae7dc4d75117ffc201047..82ec2889b0c7ce64bb96b9c67212 100644 +--- a/hw/s390x/virtio-ccw.c ++++ b/hw/s390x/virtio-ccw.c +@@ -35,6 +35,8 @@ + + #define NR_CLASSIC_INDICATOR_BITS 64 + ++bool have_virtio_ccw = true; ++ + static int virtio_ccw_dev_post_load(void *opaque, int version_id) + { + VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(opaque); +diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h +index 49a2b8ca42df799f1815f8af32d1..0168232e3b8db1da2a91dfd157db 100644 +--- a/hw/s390x/virtio-ccw.h ++++ b/hw/s390x/virtio-ccw.h +@@ -63,6 +63,11 @@ typedef struct VirtioBusClass VirtioCcwBusClass; + DECLARE_OBJ_CHECKERS(VirtioCcwBusState, VirtioCcwBusClass, + VIRTIO_CCW_BUS, TYPE_VIRTIO_CCW_BUS) + ++/* ++ * modules can reference this symbol to avoid being loaded ++ * into system emulators without ccw support ++ */ ++extern bool have_virtio_ccw; + + struct VirtIOCCWDeviceClass { + CCWDeviceClass parent_class; diff --git a/s390x-modularize-virtio-gpu-ccw.patch b/s390x-modularize-virtio-gpu-ccw.patch new file mode 100644 index 00000000..733559e3 --- /dev/null +++ b/s390x-modularize-virtio-gpu-ccw.patch @@ -0,0 +1,87 @@ +From: Gerd Hoffmann +Date: Wed, 17 Mar 2021 10:56:22 +0100 +Subject: s390x: modularize virtio-gpu-ccw + +Git-commit: adcf33a504de29feb720736051dc32889314c9e6 +References: bsc#1181103 + +Since the virtio-gpu-ccw device depends on the hw-display-virtio-gpu +module, which provides the type virtio-gpu-device, packaging the +hw-display-virtio-gpu module as a separate package that may or may not +be installed along with the qemu package leads to problems. Namely if +the hw-display-virtio-gpu is absent, qemu continues to advertise +virtio-gpu-ccw, but it aborts not only when one attempts using +virtio-gpu-ccw, but also when libvirtd's capability probing tries +to instantiate the type to introspect it. + +Let us thus introduce a module named hw-s390x-virtio-gpu-ccw that +is going to provide the virtio-gpu-ccw device. The hw-s390x prefix +was chosen because it is not a portable device. + +With virtio-gpu-ccw built as a module, the correct way to package a +modularized qemu is to require that hw-display-virtio-gpu must be +installed whenever the module hw-s390x-virtio-gpu-ccw. + +Signed-off-by: Halil Pasic +Signed-off-by: Gerd Hoffmann +Reviewed-by: Halil Pasic +Tested-by: Halil Pasic +Message-Id: <20210317095622.2839895-4-kraxel@redhat.com> +Signed-off-by: Gerd Hoffmann +Signed-off-by: Bruce Rogers +--- + hw/s390x/meson.build | 8 +++++++- + hw/s390x/virtio-ccw-gpu.c | 4 +++- + util/module.c | 1 + + 3 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/hw/s390x/meson.build b/hw/s390x/meson.build +index e53b7a69930a27dd030994ab6a54..8662ad04db2c51a229cbf7108c55 100644 +--- a/hw/s390x/meson.build ++++ b/hw/s390x/meson.build +@@ -34,7 +34,6 @@ virtio_ss.add(files('virtio-ccw.c')) + virtio_ss.add(when: 'CONFIG_VIRTIO_BALLOON', if_true: files('virtio-ccw-balloon.c')) + virtio_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio-ccw-blk.c')) + virtio_ss.add(when: 'CONFIG_VIRTIO_CRYPTO', if_true: files('virtio-ccw-crypto.c')) +-virtio_ss.add(when: 'CONFIG_VIRTIO_GPU', if_true: files('virtio-ccw-gpu.c')) + virtio_ss.add(when: 'CONFIG_VIRTIO_INPUT', if_true: files('virtio-ccw-input.c')) + virtio_ss.add(when: 'CONFIG_VIRTIO_NET', if_true: files('virtio-ccw-net.c')) + virtio_ss.add(when: 'CONFIG_VIRTIO_RNG', if_true: files('virtio-ccw-rng.c')) +@@ -46,3 +45,10 @@ virtio_ss.add(when: 'CONFIG_VHOST_USER_FS', if_true: files('vhost-user-fs-ccw.c' + s390x_ss.add_all(when: 'CONFIG_VIRTIO_CCW', if_true: virtio_ss) + + hw_arch += {'s390x': s390x_ss} ++ ++hw_s390x_modules = {} ++virtio_gpu_ccw_ss = ss.source_set() ++virtio_gpu_ccw_ss.add(when: ['CONFIG_VIRTIO_GPU', 'CONFIG_VIRTIO_CCW'], ++ if_true: [files('virtio-ccw-gpu.c'), pixman]) ++hw_s390x_modules += {'virtio-gpu-ccw': virtio_gpu_ccw_ss} ++modules += {'hw-s390x': hw_s390x_modules} +diff --git a/hw/s390x/virtio-ccw-gpu.c b/hw/s390x/virtio-ccw-gpu.c +index c301e2586bde8aff7333ea029c02..75a9e4bb3908178d3aea335fd7a0 100644 +--- a/hw/s390x/virtio-ccw-gpu.c ++++ b/hw/s390x/virtio-ccw-gpu.c +@@ -62,7 +62,9 @@ static const TypeInfo virtio_ccw_gpu = { + + static void virtio_ccw_gpu_register(void) + { +- type_register_static(&virtio_ccw_gpu); ++ if (have_virtio_ccw) { ++ type_register_static(&virtio_ccw_gpu); ++ } + } + + type_init(virtio_ccw_gpu_register) +diff --git a/util/module.c b/util/module.c +index c65060c167df236d6e2163472708..cbe89fede628c3674e49194ee688 100644 +--- a/util/module.c ++++ b/util/module.c +@@ -304,6 +304,7 @@ static struct { + { "virtio-gpu-pci-base", "hw-", "display-virtio-gpu-pci" }, + { "virtio-gpu-pci", "hw-", "display-virtio-gpu-pci" }, + { "vhost-user-gpu-pci", "hw-", "display-virtio-gpu-pci" }, ++ { "virtio-gpu-ccw", "hw-", "s390x-virtio-gpu-ccw" }, + { "virtio-vga-base", "hw-", "display-virtio-vga" }, + { "virtio-vga", "hw-", "display-virtio-vga" }, + { "vhost-user-vga", "hw-", "display-virtio-vga" }, diff --git a/s390x-move-S390_ADAPTER_SUPPRESSIBLE.patch b/s390x-move-S390_ADAPTER_SUPPRESSIBLE.patch new file mode 100644 index 00000000..bdae99fc --- /dev/null +++ b/s390x-move-S390_ADAPTER_SUPPRESSIBLE.patch @@ -0,0 +1,96 @@ +From: Gerd Hoffmann +Date: Wed, 17 Mar 2021 10:56:20 +0100 +Subject: s390x: move S390_ADAPTER_SUPPRESSIBLE + +Git-commit: d4c603d7be2e4173252c5b55e62d30ddd26edaca +References: bsc#1181103 + +The definition S390_ADAPTER_SUPPRESSIBLE was moved to "cpu.h", per +suggestion of Thomas Huth. From interface design perspective, IMHO, not +a good thing as it belongs to the public interface of +css_register_io_adapters(). We did this because CONFIG_KVM requeires +NEED_CPU_H and Thomas, and other commenters did not like the +consequences of that. + +Moving the interrupt related declarations to s390_flic.h was suggested +by Cornelia Huck. + +Signed-off-by: Halil Pasic +Signed-off-by: Gerd Hoffmann +Reviewed-by: Halil Pasic +Tested-by: Halil Pasic +Message-Id: <20210317095622.2839895-2-kraxel@redhat.com> +Signed-off-by: Gerd Hoffmann +Signed-off-by: Bruce Rogers +--- + include/hw/s390x/css.h | 7 ------- + include/hw/s390x/s390_flic.h | 3 +++ + target/s390x/cpu.h | 9 ++++++--- + 3 files changed, 9 insertions(+), 10 deletions(-) + +diff --git a/include/hw/s390x/css.h b/include/hw/s390x/css.h +index 08c869ab0afc18f34fb28056ce29..7858666307a1baaf2586dce56c07 100644 +--- a/include/hw/s390x/css.h ++++ b/include/hw/s390x/css.h +@@ -12,7 +12,6 @@ + #ifndef CSS_H + #define CSS_H + +-#include "cpu.h" + #include "hw/s390x/adapter.h" + #include "hw/s390x/s390_flic.h" + #include "hw/s390x/ioinst.h" +@@ -233,12 +232,6 @@ uint32_t css_get_adapter_id(CssIoAdapterType type, uint8_t isc); + void css_register_io_adapters(CssIoAdapterType type, bool swap, bool maskable, + uint8_t flags, Error **errp); + +-#ifndef CONFIG_KVM +-#define S390_ADAPTER_SUPPRESSIBLE 0x01 +-#else +-#define S390_ADAPTER_SUPPRESSIBLE KVM_S390_ADAPTER_SUPPRESSIBLE +-#endif +- + #ifndef CONFIG_USER_ONLY + SubchDev *css_find_subch(uint8_t m, uint8_t cssid, uint8_t ssid, + uint16_t schid); +diff --git a/include/hw/s390x/s390_flic.h b/include/hw/s390x/s390_flic.h +index e91b15d2d6af5feb2e7e7284bfbd..3907a13d07664bad96d466b3d20a 100644 +--- a/include/hw/s390x/s390_flic.h ++++ b/include/hw/s390x/s390_flic.h +@@ -134,6 +134,9 @@ void s390_flic_init(void); + S390FLICState *s390_get_flic(void); + QEMUS390FLICState *s390_get_qemu_flic(S390FLICState *fs); + S390FLICStateClass *s390_get_flic_class(S390FLICState *fs); ++void s390_crw_mchk(void); ++void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, ++ uint32_t io_int_parm, uint32_t io_int_word); + bool ais_needed(void *opaque); + + #endif /* HW_S390_FLIC_H */ +diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h +index 60d434d5edd55c59cfe7e345967c..b434b905c0ae337c62ddcc9d7e34 100644 +--- a/target/s390x/cpu.h ++++ b/target/s390x/cpu.h +@@ -40,6 +40,12 @@ + + #define S390_MAX_CPUS 248 + ++#ifndef CONFIG_KVM ++#define S390_ADAPTER_SUPPRESSIBLE 0x01 ++#else ++#define S390_ADAPTER_SUPPRESSIBLE KVM_S390_ADAPTER_SUPPRESSIBLE ++#endif ++ + typedef struct PSW { + uint64_t mask; + uint64_t addr; +@@ -806,9 +812,6 @@ int cpu_s390x_signal_handler(int host_signum, void *pinfo, void *puc); + + + /* interrupt.c */ +-void s390_crw_mchk(void); +-void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, +- uint32_t io_int_parm, uint32_t io_int_word); + #define RA_IGNORED 0 + void s390_program_interrupt(CPUS390XState *env, uint32_t code, uintptr_t ra); + /* service interrupts are floating therefore we must not pass an cpustate */ diff --git a/sungem-switch-to-use-qemu_receive_packet.patch b/sungem-switch-to-use-qemu_receive_packet.patch new file mode 100644 index 00000000..72c747cb --- /dev/null +++ b/sungem-switch-to-use-qemu_receive_packet.patch @@ -0,0 +1,38 @@ +From: Jason Wang +Date: Wed, 24 Feb 2021 13:14:35 +0800 +Subject: sungem: switch to use qemu_receive_packet() for loopback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Git-commit: 8c92060d3c0248bd4d515719a35922cd2391b9b4 + +This patch switches to use qemu_receive_packet() which can detect +reentrancy and return early. + +This is intended to address CVE-2021-3416. + +Cc: Prasad J Pandit +Cc: qemu-stable@nongnu.org +Reviewed-by: Mark Cave-Ayland +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Alistair Francis +Signed-off-by: Jason Wang +Signed-off-by: Bruce Rogers +--- + hw/net/sungem.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/net/sungem.c b/hw/net/sungem.c +index 33c3722df6f7c052b1632115e602..3684a4d733b6ec8bea39b4487e18 100644 +--- a/hw/net/sungem.c ++++ b/hw/net/sungem.c +@@ -306,7 +306,7 @@ static void sungem_send_packet(SunGEMState *s, const uint8_t *buf, + NetClientState *nc = qemu_get_queue(s->nic); + + if (s->macregs[MAC_XIFCFG >> 2] & MAC_XIFCFG_LBCK) { +- nc->info->receive(nc, buf, size); ++ qemu_receive_packet(nc, buf, size); + } else { + qemu_send_packet(nc, buf, size); + } diff --git a/tools-virtiofsd-Replace-the-word-whiteli.patch b/tools-virtiofsd-Replace-the-word-whiteli.patch new file mode 100644 index 00000000..988c403c --- /dev/null +++ b/tools-virtiofsd-Replace-the-word-whiteli.patch @@ -0,0 +1,93 @@ +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Fri, 5 Feb 2021 18:18:11 +0100 +Subject: tools/virtiofsd: Replace the word 'whitelist' +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Git-commit: a65963efa3a8533e8c9fc62e899147612d913058 +References: bsc#1183373, CVE-2021-20263 + +Follow the inclusive terminology from the "Conscious Language in your +Open Source Projects" guidelines [*] and replace the words "whitelist" +appropriately. + +[*] https://github.com/conscious-lang/conscious-lang-docs/blob/main/faq.md + +Reviewed-by: Dr. David Alan Gilbert +Reviewed-by: Daniel P. Berrangé +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20210205171817.2108907-3-philmd@redhat.com> +Signed-off-by: Dr. David Alan Gilbert +Signed-off-by: Bruce Rogers +--- + tools/virtiofsd/passthrough_ll.c | 6 +++--- + tools/virtiofsd/passthrough_seccomp.c | 12 ++++++------ + 2 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c +index 03c5e0d13c35849ec90d32fa38a2..90f5281f10ab747098e57a3157c1 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -3195,7 +3195,7 @@ static void setup_mounts(const char *source) + } + + /* +- * Only keep whitelisted capabilities that are needed for file system operation ++ * Only keep capabilities in allowlist that are needed for file system operation + * The (possibly NULL) modcaps_in string passed in is free'd before exit. + */ + static void setup_capabilities(char *modcaps_in) +@@ -3205,8 +3205,8 @@ static void setup_capabilities(char *modcaps_in) + capng_restore_state(&cap.saved); + + /* +- * Whitelist file system-related capabilities that are needed for a file +- * server to act like root. Drop everything else like networking and ++ * Add to allowlist file system-related capabilities that are needed for a ++ * file server to act like root. Drop everything else like networking and + * sysadmin capabilities. + * + * Exclusions: +diff --git a/tools/virtiofsd/passthrough_seccomp.c b/tools/virtiofsd/passthrough_seccomp.c +index 11623f56f20ca6ceb850ecf2cb8d..c98d28da6c41106d12608cf4b576 100644 +--- a/tools/virtiofsd/passthrough_seccomp.c ++++ b/tools/virtiofsd/passthrough_seccomp.c +@@ -24,7 +24,7 @@ + #endif + #endif + +-static const int syscall_whitelist[] = { ++static const int syscall_allowlist[] = { + /* TODO ireg sem*() syscalls */ + SCMP_SYS(brk), + SCMP_SYS(capget), /* For CAP_FSETID */ +@@ -118,12 +118,12 @@ static const int syscall_whitelist[] = { + }; + + /* Syscalls used when --syslog is enabled */ +-static const int syscall_whitelist_syslog[] = { ++static const int syscall_allowlist_syslog[] = { + SCMP_SYS(send), + SCMP_SYS(sendto), + }; + +-static void add_whitelist(scmp_filter_ctx ctx, const int syscalls[], size_t len) ++static void add_allowlist(scmp_filter_ctx ctx, const int syscalls[], size_t len) + { + size_t i; + +@@ -154,10 +154,10 @@ void setup_seccomp(bool enable_syslog) + exit(1); + } + +- add_whitelist(ctx, syscall_whitelist, G_N_ELEMENTS(syscall_whitelist)); ++ add_allowlist(ctx, syscall_allowlist, G_N_ELEMENTS(syscall_allowlist)); + if (enable_syslog) { +- add_whitelist(ctx, syscall_whitelist_syslog, +- G_N_ELEMENTS(syscall_whitelist_syslog)); ++ add_allowlist(ctx, syscall_allowlist_syslog, ++ G_N_ELEMENTS(syscall_allowlist_syslog)); + } + + /* libvhost-user calls this for post-copy migration, we don't need it */ diff --git a/tx_pkt-switch-to-use-qemu_receive_packet.patch b/tx_pkt-switch-to-use-qemu_receive_packet.patch new file mode 100644 index 00000000..742ff612 --- /dev/null +++ b/tx_pkt-switch-to-use-qemu_receive_packet.patch @@ -0,0 +1,36 @@ +From: Jason Wang +Date: Wed, 24 Feb 2021 13:27:52 +0800 +Subject: tx_pkt: switch to use qemu_receive_packet_iov() for loopback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Git-commit: 8c552542b81e56ff532dd27ec6e5328954bdda73 + +This patch switches to use qemu_receive_receive_iov() which can detect +reentrancy and return early. + +This is intended to address CVE-2021-3416. + +Cc: Prasad J Pandit +Cc: qemu-stable@nongnu.org +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Jason Wang +Signed-off-by: Bruce Rogers +--- + hw/net/net_tx_pkt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c +index da262edc3e95e71f2aa8a52026f9..1f9aa59eca258a51c462be114888 100644 +--- a/hw/net/net_tx_pkt.c ++++ b/hw/net/net_tx_pkt.c +@@ -553,7 +553,7 @@ static inline void net_tx_pkt_sendv(struct NetTxPkt *pkt, + NetClientState *nc, const struct iovec *iov, int iov_cnt) + { + if (pkt->is_loopback) { +- nc->info->receive_iov(nc, iov, iov_cnt); ++ qemu_receive_packet_iov(nc, iov, iov_cnt); + } else { + qemu_sendv_packet(nc, iov, iov_cnt); + } diff --git a/update_git.sh b/update_git.sh index 1045dd13..67955528 100644 --- a/update_git.sh +++ b/update_git.sh @@ -151,12 +151,11 @@ initbundle() { # "{path/}{git_sha}.{bundle}", where {path/} isn't present for # the top (qemu) bundle (ie it's for submodules). -rm -rf $GIT_DIR -rm -rf $BUNDLE_DIR -mkdir -p $BUNDLE_DIR +find $GIT_DIR -mindepth 1 -delete +find $BUN_DIR -mindepth 1 -delete if [[ -e ${LOCAL_REPO_MAP[$i]}/.git/shallow ]]; then if [[ -e bundles.tar.xz ]]; then - tar --extract --xz -f bundles.tar.xz -C $BUNDLE_DIR . + tar --extract --xz -f bundles.tar.xz -C $BUN_DIR . else echo "ERROR: Superproject at ${LOCAL_REPO_MAP[$i]} is shallow (so we assume submodules aren't" echo "recursively checked out), and there is not an existing bundle-of-bundles file, so we cannot" @@ -170,7 +169,7 @@ else rm bundles.tar.xz fi if [[ -e bundles.tar.xz ]]; then - tar --extract --xz -f bundles.tar.xz -C $BUNDLE_DIR . + tar --extract --xz -f bundles.tar.xz -C $BUN_DIR . else SUBMODULE_COMMIT_IDS=($(git -C ${LOCAL_REPO_MAP[0]} submodule status --recursive| cut -c 2- | awk '{print $1}')) SUBMODULE_DIRS=($(git -C ${LOCAL_REPO_MAP[0]} submodule status --recursive| cut -c 2- |awk '{print $2}')) @@ -181,16 +180,23 @@ else exit fi for (( i=0; i <$SUBMODULE_COUNT; i++ )); do - mkdir -p $BUNDLE_DIR/${SUBMODULE_DIRS[$i]} - touch $BUNDLE_DIR/${SUBMODULE_DIRS[$i]}/${SUBMODULE_COMMIT_IDS[$i]}.id + mkdir -p $BUN_DIR/${SUBMODULE_DIRS[$i]} + touch $BUN_DIR/${SUBMODULE_DIRS[$i]}/${SUBMODULE_COMMIT_IDS[$i]}.id done if [ "$GIT_UPSTREAM_COMMIT_ISH" = "LATEST" ]; then GIT_UPSTREAM_COMMIT=$NEW_COMMIT_ISH_FULL else # TODO: make this smarter, or change something - works for tag, but not normal commit? GIT_UPSTREAM_COMMIT=$(git -C ${LOCAL_REPO_MAP[0]} show-ref -d $GIT_UPSTREAM_COMMIT_ISH|grep -F "^{}"|awk '{print $1}') + if [[ "$GIT_UPSTREAM_COMMIT" = "" ]]; then + GIT_UPSTREAM_COMMIT=$(git -C ${LOCAL_REPO_MAP[0]} show-ref -d $GIT_UPSTREAM_COMMIT_ISH||awk '{print $1}') + fi + if [[ "$GIT_UPSTREAM_COMMIT" = "" ]]; then + echo "ERROR: Failed to get commit id for $GIT_UPSTREAM_COMMIT_ISH" + exit + fi fi - touch $BUNDLE_DIR/$GIT_UPSTREAM_COMMIT.id + touch $BUN_DIR/$GIT_UPSTREAM_COMMIT.id fi fi @@ -198,7 +204,7 @@ fi for (( i=0; i <$REPO_COUNT; i++ )); do if [[ -e $(readlink -f ${LOCAL_REPO_MAP[$i]}) ]]; then SUBDIR=${PATCH_PATH_MAP[$i]} - GITREPO_COMMIT_ISH=($BUNDLE_DIR/$SUBDIR*.id) + GITREPO_COMMIT_ISH=($BUN_DIR/$SUBDIR*.id) if [[ $GITREPO_COMMIT_ISH =~ .*(.{40})[.]id ]]; then GITREPO_COMMIT_ISH=${BASH_REMATCH[1]} echo "Using $GITREPO_COMMIT_ISH" @@ -210,9 +216,9 @@ for (( i=0; i <$REPO_COUNT; i++ )); do if [[ $(git -C $GIT_DIR/$SUBDIR ls-remote --heads origin $GIT_BRANCH) ]]; then git -C $GIT_DIR/$SUBDIR fetch --update-shallow origin $GIT_BRANCH if [[ $(git -C $GIT_DIR/$SUBDIR rev-list $GITREPO_COMMIT_ISH..FETCH_HEAD) ]]; then - git -C $GIT_DIR/$SUBDIR bundle create $BUNDLE_DIR/$SUBDIR$GITREPO_COMMIT_ISH.bundle $GITREPO_COMMIT_ISH..FETCH_HEAD + git -C $GIT_DIR/$SUBDIR bundle create $BUN_DIR/$SUBDIR$GITREPO_COMMIT_ISH.bundle $GITREPO_COMMIT_ISH..FETCH_HEAD #TODO: post-process repo info to avoid un-needed diffs (eg git vs https) - git -C $(readlink -f ${LOCAL_REPO_MAP[$PATCH_RANGE_INDEX]}) remote get-url origin >$BUNDLE_DIR/$SUBDIR/repo + git -C $(readlink -f ${LOCAL_REPO_MAP[$PATCH_RANGE_INDEX]}) remote get-url origin >$BUN_DIR/$SUBDIR/repo fi fi fi @@ -226,18 +232,17 @@ tar --format gnu --xz \ --group=0 \ --mtime="@$(date -r qemu-$SOURCE_VERSION$VERSION_EXTRA.tar.xz +%s)" \ --create \ - -f bundles.tar.xz -C $BUNDLE_DIR . -rm -rf $BUNDLE_DIR -rm -rf $GIT_DIR + -f bundles.tar.xz -C $BUN_DIR . + find $BUN_DIR -mindepth 1 -delete + find $GIT_DIR -mindepth 1 -delete } #============================================================================== bundle2local() { -rm -rf $BUNDLE_DIR -mkdir -p $BUNDLE_DIR -tar xJf bundles.tar.xz -C $BUNDLE_DIR -ID_FILES=$(find $BUNDLE_DIR -printf "%P\n"|grep "id$") + find $BUN_DIR -mindepth 1 -delete +tar xJf bundles.tar.xz -C $BUN_DIR +ID_FILES=$(find $BUN_DIR -printf "%P\n"|grep "id$") for entry in ${ID_FILES[@]}; do if [[ $entry =~ ^(.*)[/]*([a-f0-9]{40})[.]id$ ]]; then @@ -261,8 +266,8 @@ for entry in ${ID_FILES[@]}; do LOCAL_REPO=$(readlink -f ${LOCAL_REPO_MAP[$PATCH_RANGE_INDEX]}) if [ -e $LOCAL_REPO ]; then git -C $LOCAL_REPO remote remove bundlerepo || true - if [ -e $BUNDLE_DIR/$SUBDIR/$GITREPO_COMMIT_ISH.bundle ]; then - git -C $LOCAL_REPO remote add bundlerepo $BUNDLE_DIR/$SUBDIR/$GITREPO_COMMIT_ISH.bundle + if [ -e $BUN_DIR/$SUBDIR/$GITREPO_COMMIT_ISH.bundle ]; then + git -C $LOCAL_REPO remote add bundlerepo $BUN_DIR/$SUBDIR/$GITREPO_COMMIT_ISH.bundle git -C $LOCAL_REPO fetch bundlerepo FETCH_HEAD git -C $LOCAL_REPO branch -f frombundle FETCH_HEAD git -C $LOCAL_REPO remote remove bundlerepo @@ -271,7 +276,7 @@ for entry in ${ID_FILES[@]}; do git -C $LOCAL_REPO branch -D frombundle || true fi else - if [ -e $BUNDLE_DIR/$SUBDIR/$GITREPO_COMMIT_ISH.bundle ]; then + if [ -e $BUN_DIR/$SUBDIR/$GITREPO_COMMIT_ISH.bundle ]; then # TODO: We should be able to handle this case with some more coding, but for now... echo "No local repo $LOCAL_REPO available to process git bundle!" if [ "$GIT_UPSTREAM_COMMIT_ISH" = "LATEST" ]; then @@ -283,13 +288,13 @@ for entry in ${ID_FILES[@]}; do fi fi done -rm -rf $BUNDLE_DIR +find $BUN_DIR -mindepth 1 -delete } #============================================================================== redo_tarball_and_rebase_patches() { -rm -rf $GIT_DIR + find $GIT_DIR -mindepth 1 -delete #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # CREATE TARBALL, USING FRESH REPO - WE COULD RELY MORE ON LOCAL IF WE WERE MORE CAREFUL @@ -298,7 +303,7 @@ rm -rf $GIT_DIR # TODO: WHAT IS THIS NEXT LINE EVEN DOING FOR US?? (OK, it's initing a repo, what do we rely on there?) # Here, the branch doesn't really matter, and we're not relying on a master branch - we're just making sure we are grabbing latest from upstream # (while using a clone of "something close" as a way to quickly get most objects available as quickly as possible) -git clone -ls ${LOCAL_REPO_MAP[0]} $GIT_DIR -b $GIT_BRANCH --single-branch &>/dev/null +git clone -ls ${LOCAL_REPO_MAP[0]} -b $GIT_BRANCH --single-branch $GIT_DIR &>/dev/null echo "Please wait..." (cd $GIT_DIR && git remote add upstream \ $UPSTREAM_GIT_REPO &>/dev/null) @@ -389,10 +394,9 @@ rm -f checkpatch.log rm -f checkthese rm -rf checkdir rm -rf savedir -rm -rf $GIT_DIR -rm -rf $CMP_DIR -rm -rf $BUNDLE_DIR -mkdir -p $BUNDLE_DIR +find $GIT_DIR -mindepth 1 -delete +find $CMP_DIR -mindepth 1 -delete +find $BUN_DIR -mindepth 1 -delete mkdir savedir #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -450,14 +454,14 @@ while IFS= read -r line; do fi echo "ERROR: Failure groking spec file for patches!" exit -done < qemu.spec +done < $PKG.spec #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # CONVERT BUNDLES INTO COMMITS AND FILL SPEC FILE #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -tar xJf bundles.tar.xz -C $BUNDLE_DIR -BUNDLE_FILES=$(find $BUNDLE_DIR -printf "%P\n"|grep "bundle$") +tar xJf bundles.tar.xz -C $BUN_DIR +BUNDLE_FILES=$(find $BUN_DIR -printf "%P\n"|grep "bundle$") for entry in ${BUNDLE_FILES[@]}; do if [[ $entry =~ ^(.*)[/]*([a-f0-9]{40})[.]bundle$ ]]; then @@ -482,7 +486,7 @@ for entry in ${BUNDLE_FILES[@]}; do # This tag reference, was added to resolve $GITREPO_COMMIT_ISH, which is tag as commit-id # Since origin may be shallow, we need to use the --update-shallow option git -C $GIT_DIR/$SUBDIR fetch --update-shallow origin $GIT_BRANCH - git -C $GIT_DIR/$SUBDIR remote add bundle $BUNDLE_DIR/$entry + git -C $GIT_DIR/$SUBDIR remote add bundle $BUN_DIR/$entry git -C $GIT_DIR/$SUBDIR fetch bundle FETCH_HEAD git -C $GIT_DIR/$SUBDIR format-patch -N --suffix= --no-renames -o $CMP_DIR -k --stat=72 \ --indent-heuristic --zero-commit --no-signature --full-index \ @@ -506,8 +510,8 @@ for entry in ${BUNDLE_FILES[@]}; do fi done -rm -rf $GIT_DIR -rm -rf $BUNDLE_DIR +find $GIT_DIR -mindepth 1 -delete +find $BUN_DIR -mindepth 1 -delete ( CHANGED_COUNT=0 @@ -645,7 +649,7 @@ rm -rf $BUNDLE_DIR SEABIOS_VERSION=${SEABIOS_VERSION:-$(tar JxfO qemu-$SOURCE_VERSION$VERSION_EXTRA.tar.xz \ qemu-$SOURCE_VERSION/roms/seabios/.version | cut -c5- | tr '-' '_')} - for package in qemu; do + for package in $PKG; do while IFS= read -r line; do if [ "$line" = "PATCH_FILES" ]; then # Here (and other places below) we try to get ONLY the numbered patches, but it's possible some ACTUAL patch name actually starts with multiple digits, but EXTREMELY unlikely @@ -697,7 +701,10 @@ rm -rf $BUNDLE_DIR elif [ "$line" = "INSERT_VERSIONING" ]; then echo "%define qemuver $QEMU_VERSION$VERSION_EXTRA" echo "%define srcver $SOURCE_VERSION$VERSION_EXTRA" - echo "%define sbver $SEABIOS_VERSION" + # For SLE11, where seabios isn't in the qemu tarball: + if [[ "$SEABIOS_VERSION" != "" ]]; then + echo "%define sbver $SEABIOS_VERSION" + fi elif [[ "$line" =~ ^Source: ]]; then echo "$line" if [ ${#QEMU_TARBALL_SIG[@]} -eq 1 ]; then @@ -748,7 +755,7 @@ rm -rf $BUNDLE_DIR echo " added: $ADDED_COUNT" ) -rm -rf $CMP_DIR +find $CMP_DIR -mindepth 1 -delete rm -rf checkdir osc service localrun format_spec_file || true @@ -756,8 +763,8 @@ osc service localrun format_spec_file || true # Be aware that when checking into build service you should use --noservice, since we've # already run this and --noservice will prevent the modification from happening at checkin # time. -sed -i 's/^# spec file for package qemu%{name_suffix}$/# spec file for package qemu/g' qemu.spec -sed -i 's/^# spec file for package qemu-linux-user$/# spec file for package qemu/g' qemu.spec +sed -i 's/^# spec file for package '$PKG'%{name_suffix}$/# spec file for package '$PKG'/g' $PKG.spec +sed -i 's/^# spec file for package '$PKG'-linux-user$/# spec file for package '$PKG'/g' $PKG.spec } #============================================================================== @@ -804,6 +811,15 @@ fi #============================================================================== +clean_up_temp_dirs() +{ +rm -rf $GIT_DIR +rm -rf $CMP_DIR +rm -rf $BUN_DIR +} + +#============================================================================== + if [[ ! -e $(readlink -f ${LOCAL_REPO_MAP[0]}) ]]; then echo "No local repo found at ${LOCAL_REPO_MAP[0]}" if [ "$GIT_UPSTREAM_COMMIT_ISH" = "LATEST" ]; then @@ -900,15 +916,6 @@ for (( i=0; i <$REPO_COUNT; i++ )); do fi fi fi - # The following is unfortunately needed due to an improper removal of roms/openhackware - # in the qemu v5.0.0 timeframe. After checking out a new $GIT_BRANCH, check for - # whether commit b2ce76a0730e48e60633a698cd876d55917ac9bc is in ancestry and - # if so, make sure that roms/openhackware is gone, so we have a clean local repo dir - if [[ "$i" = "0" ]]; then - if $(git -C ${LOCAL_REPO_MAP[$i]} merge-base --is-ancestor b2ce76a0730e48e60633a698cd876d55917ac9bc HEAD); then - (cd ${LOCAL_REPO_MAP[$i]} && rm -rf roms/openhackware/ >/dev/null) - fi - fi # This does additional setup now that we've possibly grabbed additional submodules if ! git -C ${LOCAL_REPO_MAP[$i]} submodule update --init --recursive &> /dev/null; then echo "Please clean up state of local repo ${LOCAL_REPO_MAP[$i]} before using script" @@ -922,6 +929,16 @@ for (( i=0; i <$REPO_COUNT; i++ )); do fi fi done + +# cleanup directories from any previous failed run: +rm -rf /dev/shm/qemu-???????-git-dir +rm -rf /dev/shm/qemu-???????-cmp-dir +rm -rf /dev/shm/qemu-???????-bun-dir +# Temporary directories used in this script +GIT_DIR=$(mktemp -d /dev/shm/qemu-XXXXXXX-git-dir) +CMP_DIR=$(mktemp -d /dev/shm/qemu-XXXXXXX-cmp-dir) +BUN_DIR=$(mktemp -d /dev/shm/qemu-XXXXXXX-bun-dir) + if [ "$GIT_UPSTREAM_COMMIT_ISH" = "LATEST" ]; then if [ "$1" = "continue" ]; then CONTINUE_AFTER_REBASE=1 @@ -931,7 +948,8 @@ if [ "$GIT_UPSTREAM_COMMIT_ISH" = "LATEST" ]; then else if [ "$1" ]; then echo "ERROR: unrecognized option '$1'. Script in LATEST mode only recognizes 'pause' and 'continue' options" - exit + clean_up_temp_dirs + exit fi fi fi @@ -945,7 +963,7 @@ if [ "$GIT_UPSTREAM_COMMIT_ISH" = "LATEST" ]; then setup_common_vars WRITE_LOG=0 echo "Processing LATEST upstream changes" - echo "(If SUCCESS is not printed upon completion, see /tmp/latest.log for issues)" + echo "(If SUCCESS is not printed upon completion, see ~/latest.log for issues)" if [[ $QEMU_TARBALL =~ $BASE_RE$EXTRA_RE$SUFFIX_RE ]]; then OLD_COMMIT_ISH=${BASH_REMATCH[3]} else @@ -963,9 +981,10 @@ if [ "$GIT_UPSTREAM_COMMIT_ISH" = "LATEST" ]; then echo "continue after rebase selected but tarball is out of date. Continuing not possible." echo "If desired, save your rebase work (eg, branch $GIT_BRANCH), because otherwise it will" echo "be lost. Then run script again without the continue option" + clean_up_temp_dirs exit fi - redo_tarball_and_rebase_patches &> /tmp/latest.log # This includes a bundle2local + redo_tarball_and_rebase_patches &> ~/latest.log # This includes a bundle2local if [[ "$REBASE_FAILS" ]]; then echo "ERROR! Rebase of the $GIT_BRANCH branch failed in the following local git repos:" echo $REBASE_FAILS @@ -973,6 +992,7 @@ if [ "$GIT_UPSTREAM_COMMIT_ISH" = "LATEST" ]; then if [[ "$PAUSE_BEFORE_BUNDLE_CREATION" = "1" ]]; then echo "Feel free to also do the work now occasioned by the selected 'pause' option" fi + clean_up_temp_dirs exit fi CONTINUE_AFTER_REBASE=1 @@ -981,14 +1001,15 @@ if [ "$GIT_UPSTREAM_COMMIT_ISH" = "LATEST" ]; then echo "As requested, pausing before re-creating bundle of bundles for additional patch or specfile work" echo "(using current 'ready to go' $GIT_BRANCH branch of local repos to produce patches.)" echo "When changes are complete, finish the workflow by passing 'continue' to script" + clean_up_temp_dirs exit fi if [ "$CONTINUE_AFTER_REBASE" = "1" ]; then - initbundle &>> /tmp/latest.log + initbundle &>> ~/latest.log fi - bundle2spec &>> /tmp/latest.log + bundle2spec &>> ~/latest.log echo "SUCCESS" - tail -9 /tmp/latest.log + tail -9 ~/latest.log else # not LATEST #NOTNEEDED? git -C ${LOCAL_REPO_MAP[0]} checkout $GIT_UPSTREAM_COMMIT_ISH --recurse-submodules -f &> /dev/null NEW_COMMIT_ISH= @@ -996,22 +1017,22 @@ else # not LATEST case $1 in initbundle ) echo "Updating the bundle using the $GIT_BRANCH branch of the local repos." - echo "(If SUCCESS is not printed upon completion, see /tmp/initbundle.log for issues)" - initbundle &> /tmp/initbundle.log + echo "(If SUCCESS is not printed upon completion, see ~/initbundle.log for issues)" + initbundle &> ~/initbundle.log echo "SUCCESS" ;; git2pkg ) echo "Updating the package using the $GIT_BRANCH branch of the local repos." - echo "(If SUCCESS is not printed upon completion, see /tmp/git2pkg.log for issues)" - initbundle &> /tmp/git2pkg.log - bundle2spec &>> /tmp/git2pkg.log + echo "(If SUCCESS is not printed upon completion, see ~/git2pkg.log for issues)" + initbundle &> ~/git2pkg.log + bundle2spec &>> ~/git2pkg.log echo "SUCCESS" - tail -9 /tmp/git2pkg.log + tail -9 ~/git2pkg.log ;; pkg2git ) echo "Exporting the package's git bundles to the local repo's frombundle branches..." - echo "(If SUCCESS is not printed upon completion, see /tmp/pkg2git.log for issues)" - bundle2local &> /tmp/pkg2git.log + echo "(If SUCCESS is not printed upon completion, see ~/pkg2git.log for issues)" + bundle2local &> ~/pkg2git.log echo "SUCCESS" echo "To modify package patches, use the frombundle branch as the basis for updating" echo "the $GIT_BRANCH branch with the new patch queue." @@ -1020,12 +1041,12 @@ else # not LATEST refresh ) echo "Updating the spec file and patches from the spec file template and the bundle" echo "of bundles (bundles.tar.xz)" - echo "(If SUCCESS is not printed upon completion, see /tmp/refresh.log for issues)" - bundle2spec &> /tmp/refresh.log + echo "(If SUCCESS is not printed upon completion, see ~/refresh.log for issues)" + bundle2spec &> ~/refresh.log echo "SUCCESS" - tail -9 /tmp/refresh.log + tail -9 ~/refresh.log ;; esac fi +clean_up_temp_dirs exit - diff --git a/viriofsd-Add-support-for-FUSE_HANDLE_KIL.patch b/viriofsd-Add-support-for-FUSE_HANDLE_KIL.patch new file mode 100644 index 00000000..6589f349 --- /dev/null +++ b/viriofsd-Add-support-for-FUSE_HANDLE_KIL.patch @@ -0,0 +1,335 @@ +From: Vivek Goyal +Date: Mon, 8 Feb 2021 17:40:24 -0500 +Subject: viriofsd: Add support for FUSE_HANDLE_KILLPRIV_V2 + +Git-commit: d64907acbf6e436099fd26fbb6312fd56f9fb29d +References: bsc#1183373, CVE-2021-20263 + +This patch adds basic support for FUSE_HANDLE_KILLPRIV_V2. virtiofsd +can enable/disable this by specifying option "-o killpriv_v2/no_killpriv_v2". +By default this is enabled as long as client supports it + +Enabling this option helps with performance in write path. Without this +option, currently every write is first preceeded with a getxattr() operation +to find out if security.capability is set. (Write is supposed to clear +security.capability). With this option enabled, server is signing up for +clearing security.capability on every WRITE and also clearing suid/sgid +subject to certain rules. This gets rid of extra getxattr() call for every +WRITE and improves performance. This is true when virtiofsd is run with +option -o xattr. + +What does enabling FUSE_HANDLE_KILLPRIV_V2 mean for file server implementation. +It needs to adhere to following rules. Thanks to Miklos for this summary. + +- clear "security.capability" on write, truncate and chown unconditionally +- clear suid/sgid in case of following. Note, sgid is cleared only if + group executable bit is set. + o setattr has FATTR_SIZE and FATTR_KILL_SUIDGID set. + o setattr has FATTR_UID or FATTR_GID + o open has O_TRUNC and FUSE_OPEN_KILL_SUIDGID + o create has O_TRUNC and FUSE_OPEN_KILL_SUIDGID flag set. + o write has FUSE_WRITE_KILL_SUIDGID + +>From Linux VFS client perspective, here are the requirements. + +- caps are always cleared on chown/write/truncate +- suid is always cleared on chown, while for truncate/write it is cleared + only if caller does not have CAP_FSETID. +- sgid is always cleared on chown, while for truncate/write it is cleared + only if caller does not have CAP_FSETID as well as file has group execute + permission. + +virtiofsd implementation has not changed much to adhere to above ruls. And +reason being that current assumption is that we are running on Linux +and on top of filesystems like ext4/xfs which already follow above rules. +On write, truncate, chown, seucurity.capability is cleared. And virtiofsd +drops CAP_FSETID if need be and that will lead to clearing of suid/sgid. + +But if virtiofsd is running on top a filesystem which breaks above assumptions, +then it will have to take extra actions to emulate above. That's a TODO +for later when need arises. + +Note: create normally is supposed to be called only when file does not + exist. So generally there should not be any question of clearing + setuid/setgid. But it is possible that after client checks that + file is not present, some other client creates file on server + and this race can trigger sending FUSE_CREATE. In that case, if + O_TRUNC is set, we should clear suid/sgid if FUSE_OPEN_KILL_SUIDGID + is also set. + +v3: + - Resolved conflicts due to lo_inode_open() changes. + - Moved capability code in lo_do_open() so that both lo_open() and + lo_create() can benefit from common code. + - Dropped changes to kernel headers as these are part of qemu already. + +Signed-off-by: Vivek Goyal +Acked-by: Stefan Hajnoczi +Reviewed-by: Dr. David Alan Gilbert +Message-Id: <20210208224024.43555-3-vgoyal@redhat.com> +Signed-off-by: Dr. David Alan Gilbert +Signed-off-by: Bruce Rogers +--- + tools/virtiofsd/fuse_common.h | 15 ++++++ + tools/virtiofsd/fuse_lowlevel.c | 11 ++++- + tools/virtiofsd/fuse_lowlevel.h | 1 + + tools/virtiofsd/passthrough_ll.c | 84 +++++++++++++++++++++++++++++--- + 4 files changed, 103 insertions(+), 8 deletions(-) + +diff --git a/tools/virtiofsd/fuse_common.h b/tools/virtiofsd/fuse_common.h +index 5aee5193eb29ea10de8e6ce46b63..6f4a1ff3a9227964ea98d547d110 100644 +--- a/tools/virtiofsd/fuse_common.h ++++ b/tools/virtiofsd/fuse_common.h +@@ -359,6 +359,21 @@ struct fuse_file_info { + */ + #define FUSE_CAP_SUBMOUNTS (1 << 27) + ++/** ++ * Indicates that the filesystem is responsible for clearing ++ * security.capability xattr and clearing setuid and setgid bits. Following ++ * are the rules. ++ * - clear "security.capability" on write, truncate and chown unconditionally ++ * - clear suid/sgid if following is true. Note, sgid is cleared only if ++ * group executable bit is set. ++ * o setattr has FATTR_SIZE and FATTR_KILL_SUIDGID set. ++ * o setattr has FATTR_UID or FATTR_GID ++ * o open has O_TRUNC and FUSE_OPEN_KILL_SUIDGID ++ * o create has O_TRUNC and FUSE_OPEN_KILL_SUIDGID flag set. ++ * o write has FUSE_WRITE_KILL_SUIDGID ++ */ ++#define FUSE_CAP_HANDLE_KILLPRIV_V2 (1 << 28) ++ + /** + * Ioctl flags + * +diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c +index c70fb16a9a5313160a4cc53faf86..65f01a3fe31de0864948230b2e47 100644 +--- a/tools/virtiofsd/fuse_lowlevel.c ++++ b/tools/virtiofsd/fuse_lowlevel.c +@@ -865,7 +865,7 @@ static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, + FUSE_SET_ATTR_GID | FUSE_SET_ATTR_SIZE | + FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME | + FUSE_SET_ATTR_ATIME_NOW | FUSE_SET_ATTR_MTIME_NOW | +- FUSE_SET_ATTR_CTIME; ++ FUSE_SET_ATTR_CTIME | FUSE_SET_ATTR_KILL_SUIDGID; + + req->se->op.setattr(req, nodeid, &stbuf, arg->valid, fi); + } else { +@@ -1079,6 +1079,7 @@ static void do_create(fuse_req_t req, fuse_ino_t nodeid, + + memset(&fi, 0, sizeof(fi)); + fi.flags = arg->flags; ++ fi.kill_priv = arg->open_flags & FUSE_OPEN_KILL_SUIDGID; + + req->ctx.umask = arg->umask; + +@@ -1102,6 +1103,7 @@ static void do_open(fuse_req_t req, fuse_ino_t nodeid, + + memset(&fi, 0, sizeof(fi)); + fi.flags = arg->flags; ++ fi.kill_priv = arg->open_flags & FUSE_OPEN_KILL_SUIDGID; + + if (req->se->op.open) { + req->se->op.open(req, nodeid, &fi); +@@ -1993,6 +1995,9 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, + if (arg->flags & FUSE_SUBMOUNTS) { + se->conn.capable |= FUSE_CAP_SUBMOUNTS; + } ++ if (arg->flags & FUSE_HANDLE_KILLPRIV_V2) { ++ se->conn.capable |= FUSE_CAP_HANDLE_KILLPRIV_V2; ++ } + #ifdef HAVE_SPLICE + #ifdef HAVE_VMSPLICE + se->conn.capable |= FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE; +@@ -2124,6 +2129,10 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, + outarg.congestion_threshold = se->conn.congestion_threshold; + outarg.time_gran = se->conn.time_gran; + ++ if (se->conn.want & FUSE_CAP_HANDLE_KILLPRIV_V2) { ++ outarg.flags |= FUSE_HANDLE_KILLPRIV_V2; ++ } ++ + fuse_log(FUSE_LOG_DEBUG, " INIT: %u.%u\n", outarg.major, outarg.minor); + fuse_log(FUSE_LOG_DEBUG, " flags=0x%08x\n", outarg.flags); + fuse_log(FUSE_LOG_DEBUG, " max_readahead=0x%08x\n", outarg.max_readahead); +diff --git a/tools/virtiofsd/fuse_lowlevel.h b/tools/virtiofsd/fuse_lowlevel.h +index 9c06240f9e61ea259241a3ec77e9..96d10defc8936b00e8410589a183 100644 +--- a/tools/virtiofsd/fuse_lowlevel.h ++++ b/tools/virtiofsd/fuse_lowlevel.h +@@ -146,6 +146,7 @@ struct fuse_forget_data { + #define FUSE_SET_ATTR_ATIME_NOW (1 << 7) + #define FUSE_SET_ATTR_MTIME_NOW (1 << 8) + #define FUSE_SET_ATTR_CTIME (1 << 10) ++#define FUSE_SET_ATTR_KILL_SUIDGID (1 << 11) + + /* + * Request methods and replies +diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c +index 200a1d26bd11bcde5729c4f33195..f330fb72b93f24331174f52bf6b9 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -180,6 +180,7 @@ struct lo_data { + + /* An O_PATH file descriptor to /proc/self/fd/ */ + int proc_self_fd; ++ int user_killpriv_v2, killpriv_v2; + }; + + static const struct fuse_opt lo_opts[] = { +@@ -210,6 +211,8 @@ static const struct fuse_opt lo_opts[] = { + { "allow_direct_io", offsetof(struct lo_data, allow_direct_io), 1 }, + { "no_allow_direct_io", offsetof(struct lo_data, allow_direct_io), 0 }, + { "announce_submounts", offsetof(struct lo_data, announce_submounts), 1 }, ++ { "killpriv_v2", offsetof(struct lo_data, user_killpriv_v2), 1 }, ++ { "no_killpriv_v2", offsetof(struct lo_data, user_killpriv_v2), 0 }, + FUSE_OPT_END + }; + static bool use_syslog = false; +@@ -642,6 +645,34 @@ static void lo_init(void *userdata, struct fuse_conn_info *conn) + "does not support it\n"); + lo->announce_submounts = false; + } ++ ++ if (lo->user_killpriv_v2 == 1) { ++ /* ++ * User explicitly asked for this option. Enable it unconditionally. ++ * If connection does not have this capability, it should fail ++ * in fuse_lowlevel.c ++ */ ++ fuse_log(FUSE_LOG_DEBUG, "lo_init: enabling killpriv_v2\n"); ++ conn->want |= FUSE_CAP_HANDLE_KILLPRIV_V2; ++ lo->killpriv_v2 = 1; ++ } else if (lo->user_killpriv_v2 == -1 && ++ conn->capable & FUSE_CAP_HANDLE_KILLPRIV_V2) { ++ /* ++ * User did not specify a value for killpriv_v2. By default enable it ++ * if connection offers this capability ++ */ ++ fuse_log(FUSE_LOG_DEBUG, "lo_init: enabling killpriv_v2\n"); ++ conn->want |= FUSE_CAP_HANDLE_KILLPRIV_V2; ++ lo->killpriv_v2 = 1; ++ } else { ++ /* ++ * Either user specified to disable killpriv_v2, or connection does ++ * not offer this capability. Disable killpriv_v2 in both the cases ++ */ ++ fuse_log(FUSE_LOG_DEBUG, "lo_init: disabling killpriv_v2\n"); ++ conn->want &= ~FUSE_CAP_HANDLE_KILLPRIV_V2; ++ lo->killpriv_v2 = 0; ++ } + } + + static void lo_getattr(fuse_req_t req, fuse_ino_t ino, +@@ -726,7 +757,10 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, + } + if (valid & FUSE_SET_ATTR_SIZE) { + int truncfd; ++ bool kill_suidgid; ++ bool cap_fsetid_dropped = false; + ++ kill_suidgid = lo->killpriv_v2 && (valid & FUSE_SET_ATTR_KILL_SUIDGID); + if (fi) { + truncfd = fd; + } else { +@@ -737,8 +771,25 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, + } + } + ++ if (kill_suidgid) { ++ res = drop_effective_cap("FSETID", &cap_fsetid_dropped); ++ if (res != 0) { ++ saverr = res; ++ if (!fi) { ++ close(truncfd); ++ } ++ goto out_err; ++ } ++ } ++ + res = ftruncate(truncfd, attr->st_size); + saverr = res == -1 ? errno : 0; ++ ++ if (cap_fsetid_dropped) { ++ if (gain_effective_cap("FSETID")) { ++ fuse_log(FUSE_LOG_ERR, "Failed to gain CAP_FSETID\n"); ++ } ++ } + if (!fi) { + close(truncfd); + } +@@ -1719,11 +1770,27 @@ static int lo_do_open(struct lo_data *lo, struct lo_inode *inode, + { + ssize_t fh; + int fd = existing_fd; ++ int err; ++ bool cap_fsetid_dropped = false; ++ bool kill_suidgid = lo->killpriv_v2 && fi->kill_priv; + + update_open_flags(lo->writeback, lo->allow_direct_io, fi); + + if (fd < 0) { ++ if (kill_suidgid) { ++ err = drop_effective_cap("FSETID", &cap_fsetid_dropped); ++ if (err) { ++ return err; ++ } ++ } ++ + fd = lo_inode_open(lo, inode, fi->flags); ++ ++ if (cap_fsetid_dropped) { ++ if (gain_effective_cap("FSETID")) { ++ fuse_log(FUSE_LOG_ERR, "Failed to gain CAP_FSETID\n"); ++ } ++ } + if (fd < 0) { + return -fd; + } +@@ -1757,8 +1824,8 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name, + int err; + struct lo_cred old = {}; + +- fuse_log(FUSE_LOG_DEBUG, "lo_create(parent=%" PRIu64 ", name=%s)\n", parent, +- name); ++ fuse_log(FUSE_LOG_DEBUG, "lo_create(parent=%" PRIu64 ", name=%s)" ++ " kill_priv=%d\n", parent, name, fi->kill_priv); + + if (!is_safe_path_component(name)) { + fuse_reply_err(req, EINVAL); +@@ -1981,8 +2048,8 @@ static void lo_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) + struct lo_inode *inode = lo_inode(req, ino); + int err; + +- fuse_log(FUSE_LOG_DEBUG, "lo_open(ino=%" PRIu64 ", flags=%d)\n", ino, +- fi->flags); ++ fuse_log(FUSE_LOG_DEBUG, "lo_open(ino=%" PRIu64 ", flags=%d, kill_priv=%d)" ++ "\n", ino, fi->flags, fi->kill_priv); + + if (!inode) { + fuse_reply_err(req, EBADF); +@@ -2112,12 +2179,14 @@ static void lo_write_buf(fuse_req_t req, fuse_ino_t ino, + out_buf.buf[0].pos = off; + + fuse_log(FUSE_LOG_DEBUG, +- "lo_write_buf(ino=%" PRIu64 ", size=%zd, off=%lu)\n", ino, +- out_buf.buf[0].size, (unsigned long)off); ++ "lo_write_buf(ino=%" PRIu64 ", size=%zd, off=%lu kill_priv=%d)\n", ++ ino, out_buf.buf[0].size, (unsigned long)off, fi->kill_priv); + + /* + * If kill_priv is set, drop CAP_FSETID which should lead to kernel +- * clearing setuid/setgid on file. ++ * clearing setuid/setgid on file. Note, for WRITE, we need to do ++ * this even if killpriv_v2 is not enabled. fuse direct write path ++ * relies on this. + */ + if (fi->kill_priv) { + res = drop_effective_cap("FSETID", &cap_fsetid_dropped); +@@ -3496,6 +3565,7 @@ int main(int argc, char *argv[]) + .posix_lock = 0, + .allow_direct_io = 0, + .proc_self_fd = -1, ++ .user_killpriv_v2 = -1, + }; + struct lo_map_elem *root_elem; + struct lo_map_elem *reserve_elem; diff --git a/virtiofs-drop-remapped-security.capabili.patch b/virtiofs-drop-remapped-security.capabili.patch new file mode 100644 index 00000000..400bce31 --- /dev/null +++ b/virtiofs-drop-remapped-security.capabili.patch @@ -0,0 +1,208 @@ +From: "Dr. David Alan Gilbert" +Date: Wed, 24 Feb 2021 19:56:25 +0000 +Subject: virtiofs: drop remapped security.capability xattr as needed + +Git-commit: e586edcb410543768ef009eaa22a2d9dd4a53846 +References: bsc#1183373, CVE-2021-20263 + +On Linux, the 'security.capability' xattr holds a set of +capabilities that can change when an executable is run, giving +a limited form of privilege escalation to those programs that +the writer of the file deemed worthy. + +Any write causes the 'security.capability' xattr to be dropped, +stopping anyone from gaining privilege by modifying a blessed +file. + +Fuse relies on the daemon to do this dropping, and in turn the +daemon relies on the host kernel to drop the xattr for it. However, +with the addition of -o xattrmap, the xattr that the guest +stores its capabilities in is now not the same as the one that +the host kernel automatically clears. + +Where the mapping changes 'security.capability', explicitly clear +the remapped name to preserve the same behaviour. + +This bug is assigned CVE-2021-20263. + +Signed-off-by: Dr. David Alan Gilbert +Reviewed-by: Vivek Goyal +Signed-off-by: Bruce Rogers +--- + docs/tools/virtiofsd.rst | 4 ++ + tools/virtiofsd/passthrough_ll.c | 77 +++++++++++++++++++++++++++++++- + 2 files changed, 80 insertions(+), 1 deletion(-) + +diff --git a/docs/tools/virtiofsd.rst b/docs/tools/virtiofsd.rst +index 866b7db3eed36302bc96bbef8184..00554c75bd75785689e08a16086d 100644 +--- a/docs/tools/virtiofsd.rst ++++ b/docs/tools/virtiofsd.rst +@@ -228,6 +228,10 @@ The 'map' type adds a number of separate rules to add **prepend** as a prefix + to the matched **key** (or all attributes if **key** is empty). + There may be at most one 'map' rule and it must be the last rule in the set. + ++Note: When the 'security.capability' xattr is remapped, the daemon has to do ++extra work to remove it during many operations, which the host kernel normally ++does itself. ++ + xattr-mapping Examples + ---------------------- + +diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c +index f330fb72b93f24331174f52bf6b9..c18475e94635ad189f54ed400aff 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -160,6 +160,7 @@ struct lo_data { + int posix_lock; + int xattr; + char *xattrmap; ++ char *xattr_security_capability; + char *source; + char *modcaps; + double timeout; +@@ -229,6 +230,8 @@ static __thread bool cap_loaded = 0; + + static struct lo_inode *lo_find(struct lo_data *lo, struct stat *st, + uint64_t mnt_id); ++static int xattr_map_client(const struct lo_data *lo, const char *client_name, ++ char **out_name); + + static int is_dot_or_dotdot(const char *name) + { +@@ -368,6 +371,37 @@ out: + return ret; + } + ++/* ++ * The host kernel normally drops security.capability xattr's on ++ * any write, however if we're remapping xattr names we need to drop ++ * whatever the clients security.capability is actually stored as. ++ */ ++static int drop_security_capability(const struct lo_data *lo, int fd) ++{ ++ if (!lo->xattr_security_capability) { ++ /* We didn't remap the name, let the host kernel do it */ ++ return 0; ++ } ++ if (!fremovexattr(fd, lo->xattr_security_capability)) { ++ /* All good */ ++ return 0; ++ } ++ ++ switch (errno) { ++ case ENODATA: ++ /* Attribute didn't exist, that's fine */ ++ return 0; ++ ++ case ENOTSUP: ++ /* FS didn't support attribute anyway, also fine */ ++ return 0; ++ ++ default: ++ /* Hmm other error */ ++ return errno; ++ } ++} ++ + static void lo_map_init(struct lo_map *map) + { + map->elems = NULL; +@@ -749,6 +783,11 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, + uid_t uid = (valid & FUSE_SET_ATTR_UID) ? attr->st_uid : (uid_t)-1; + gid_t gid = (valid & FUSE_SET_ATTR_GID) ? attr->st_gid : (gid_t)-1; + ++ saverr = drop_security_capability(lo, ifd); ++ if (saverr) { ++ goto out_err; ++ } ++ + res = fchownat(ifd, "", uid, gid, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW); + if (res == -1) { + saverr = errno; +@@ -771,6 +810,14 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, + } + } + ++ saverr = drop_security_capability(lo, truncfd); ++ if (saverr) { ++ if (!fi) { ++ close(truncfd); ++ } ++ goto out_err; ++ } ++ + if (kill_suidgid) { + res = drop_effective_cap("FSETID", &cap_fsetid_dropped); + if (res != 0) { +@@ -1794,6 +1841,13 @@ static int lo_do_open(struct lo_data *lo, struct lo_inode *inode, + if (fd < 0) { + return -fd; + } ++ if (fi->flags & (O_TRUNC)) { ++ int err = drop_security_capability(lo, fd); ++ if (err) { ++ close(fd); ++ return err; ++ } ++ } + } + + pthread_mutex_lock(&lo->mutex); +@@ -2182,6 +2236,12 @@ static void lo_write_buf(fuse_req_t req, fuse_ino_t ino, + "lo_write_buf(ino=%" PRIu64 ", size=%zd, off=%lu kill_priv=%d)\n", + ino, out_buf.buf[0].size, (unsigned long)off, fi->kill_priv); + ++ res = drop_security_capability(lo_data(req), out_buf.buf[0].fd); ++ if (res) { ++ fuse_reply_err(req, res); ++ return; ++ } ++ + /* + * If kill_priv is set, drop CAP_FSETID which should lead to kernel + * clearing setuid/setgid on file. Note, for WRITE, we need to do +@@ -2423,6 +2483,7 @@ static void parse_xattrmap(struct lo_data *lo) + { + const char *map = lo->xattrmap; + const char *tmp; ++ int ret; + + lo->xattr_map_nentries = 0; + while (*map) { +@@ -2453,7 +2514,7 @@ static void parse_xattrmap(struct lo_data *lo) + * the last entry. + */ + parse_xattrmap_map(lo, map, sep); +- return; ++ break; + } else { + fuse_log(FUSE_LOG_ERR, + "%s: Unexpected type;" +@@ -2522,6 +2583,19 @@ static void parse_xattrmap(struct lo_data *lo) + fuse_log(FUSE_LOG_ERR, "Empty xattr map\n"); + exit(1); + } ++ ++ ret = xattr_map_client(lo, "security.capability", ++ &lo->xattr_security_capability); ++ if (ret) { ++ fuse_log(FUSE_LOG_ERR, "Failed to map security.capability: %s\n", ++ strerror(ret)); ++ exit(1); ++ } ++ if (!strcmp(lo->xattr_security_capability, "security.capability")) { ++ /* 1-1 mapping, don't need to do anything */ ++ free(lo->xattr_security_capability); ++ lo->xattr_security_capability = NULL; ++ } + } + + /* +@@ -3550,6 +3624,7 @@ static void fuse_lo_data_cleanup(struct lo_data *lo) + + free(lo->xattrmap); + free_xattrmap(lo); ++ free(lo->xattr_security_capability); + free(lo->source); + } + diff --git a/virtiofsd-Save-error-code-early-at-the-f.patch b/virtiofsd-Save-error-code-early-at-the-f.patch new file mode 100644 index 00000000..c79e293d --- /dev/null +++ b/virtiofsd-Save-error-code-early-at-the-f.patch @@ -0,0 +1,87 @@ +From: Vivek Goyal +Date: Mon, 8 Feb 2021 17:40:23 -0500 +Subject: virtiofsd: Save error code early at the failure callsite + +Git-commit: 1e08f164e9fdc9528ad6990012301b9a04b0bc90 +References: bsc#1183373, CVE-2021-20263 + +Change error code handling slightly in lo_setattr(). Right now we seem +to jump to out_err and assume that "errno" is valid and use that to +send reply. + +But if caller has to do some other operations before jumping to out_err, +then it does the dance of first saving errno to saverr and the restore +errno before jumping to out_err. This makes it more confusing. + +I am about to make more changes where caller will have to do some +work after error before jumping to out_err. I found it easier to +change the convention a bit. That is caller saves error in "saverr" +before jumping to out_err. And out_err uses "saverr" to send error +back and does not rely on "errno" having actual error. + +v3: Resolved conflicts in lo_setattr() due to lo_inode_open() changes. + +Signed-off-by: Vivek Goyal +Reviewed-by: Dr. David Alan Gilbert +Message-Id: <20210208224024.43555-2-vgoyal@redhat.com> +Signed-off-by: Dr. David Alan Gilbert +Signed-off-by: Bruce Rogers +--- + tools/virtiofsd/passthrough_ll.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c +index 90f5281f10ab747098e57a3157c1..200a1d26bd11bcde5729c4f33195 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -710,6 +710,7 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, + res = fchmodat(lo->proc_self_fd, procname, attr->st_mode, 0); + } + if (res == -1) { ++ saverr = errno; + goto out_err; + } + } +@@ -719,6 +720,7 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, + + res = fchownat(ifd, "", uid, gid, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW); + if (res == -1) { ++ saverr = errno; + goto out_err; + } + } +@@ -730,16 +732,15 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, + } else { + truncfd = lo_inode_open(lo, inode, O_RDWR); + if (truncfd < 0) { +- errno = -truncfd; ++ saverr = -truncfd; + goto out_err; + } + } + + res = ftruncate(truncfd, attr->st_size); ++ saverr = res == -1 ? errno : 0; + if (!fi) { +- saverr = errno; + close(truncfd); +- errno = saverr; + } + if (res == -1) { + goto out_err; +@@ -772,6 +773,7 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, + res = utimensat(lo->proc_self_fd, procname, tv, 0); + } + if (res == -1) { ++ saverr = errno; + goto out_err; + } + } +@@ -780,7 +782,6 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, + return lo_getattr(req, ino, fi); + + out_err: +- saverr = errno; + lo_inode_put(lo, &inode); + fuse_reply_err(req, saverr); + } diff --git a/virtiofsd-extract-lo_do_open-from-lo_ope.patch b/virtiofsd-extract-lo_do_open-from-lo_ope.patch new file mode 100644 index 00000000..a02b15a8 --- /dev/null +++ b/virtiofsd-extract-lo_do_open-from-lo_ope.patch @@ -0,0 +1,145 @@ +From: Stefan Hajnoczi +Date: Thu, 4 Feb 2021 15:02:06 +0000 +Subject: virtiofsd: extract lo_do_open() from lo_open() + +Git-commit: 8afaaee976965b7fb90ec225a51d60f35c5f173c +References: bsc#1183373, CVE-2021-20263 + +Both lo_open() and lo_create() have similar code to open a file. Extract +a common lo_do_open() function from lo_open() that will be used by +lo_create() in a later commit. + +Since lo_do_open() does not otherwise need fuse_req_t req, convert +lo_add_fd_mapping() to use struct lo_data *lo instead. + +Signed-off-by: Stefan Hajnoczi +Message-Id: <20210204150208.367837-2-stefanha@redhat.com> +Reviewed-by: Greg Kurz +Signed-off-by: Dr. David Alan Gilbert +Signed-off-by: Bruce Rogers +--- + tools/virtiofsd/passthrough_ll.c | 73 ++++++++++++++++++++------------ + 1 file changed, 46 insertions(+), 27 deletions(-) + +diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c +index 97485b22b4114228e622a0b256d9..218e20e9d7901f22e26ef8dc56c2 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -471,17 +471,17 @@ static void lo_map_remove(struct lo_map *map, size_t key) + } + + /* Assumes lo->mutex is held */ +-static ssize_t lo_add_fd_mapping(fuse_req_t req, int fd) ++static ssize_t lo_add_fd_mapping(struct lo_data *lo, int fd) + { + struct lo_map_elem *elem; + +- elem = lo_map_alloc_elem(&lo_data(req)->fd_map); ++ elem = lo_map_alloc_elem(&lo->fd_map); + if (!elem) { + return -1; + } + + elem->fd = fd; +- return elem - lo_data(req)->fd_map.elems; ++ return elem - lo->fd_map.elems; + } + + /* Assumes lo->mutex is held */ +@@ -1661,6 +1661,38 @@ static void update_open_flags(int writeback, int allow_direct_io, + } + } + ++static int lo_do_open(struct lo_data *lo, struct lo_inode *inode, ++ struct fuse_file_info *fi) ++{ ++ char buf[64]; ++ ssize_t fh; ++ int fd; ++ ++ update_open_flags(lo->writeback, lo->allow_direct_io, fi); ++ ++ sprintf(buf, "%i", inode->fd); ++ fd = openat(lo->proc_self_fd, buf, fi->flags & ~O_NOFOLLOW); ++ if (fd == -1) { ++ return errno; ++ } ++ ++ pthread_mutex_lock(&lo->mutex); ++ fh = lo_add_fd_mapping(lo, fd); ++ pthread_mutex_unlock(&lo->mutex); ++ if (fh == -1) { ++ close(fd); ++ return ENOMEM; ++ } ++ ++ fi->fh = fh; ++ if (lo->cache == CACHE_NONE) { ++ fi->direct_io = 1; ++ } else if (lo->cache == CACHE_ALWAYS) { ++ fi->keep_cache = 1; ++ } ++ return 0; ++} ++ + static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode, struct fuse_file_info *fi) + { +@@ -1701,7 +1733,7 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name, + ssize_t fh; + + pthread_mutex_lock(&lo->mutex); +- fh = lo_add_fd_mapping(req, fd); ++ fh = lo_add_fd_mapping(lo, fd); + pthread_mutex_unlock(&lo->mutex); + if (fh == -1) { + close(fd); +@@ -1892,38 +1924,25 @@ static void lo_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync, + + static void lo_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) + { +- int fd; +- ssize_t fh; +- char buf[64]; + struct lo_data *lo = lo_data(req); ++ struct lo_inode *inode = lo_inode(req, ino); ++ int err; + + fuse_log(FUSE_LOG_DEBUG, "lo_open(ino=%" PRIu64 ", flags=%d)\n", ino, + fi->flags); + +- update_open_flags(lo->writeback, lo->allow_direct_io, fi); +- +- sprintf(buf, "%i", lo_fd(req, ino)); +- fd = openat(lo->proc_self_fd, buf, fi->flags & ~O_NOFOLLOW); +- if (fd == -1) { +- return (void)fuse_reply_err(req, errno); +- } +- +- pthread_mutex_lock(&lo->mutex); +- fh = lo_add_fd_mapping(req, fd); +- pthread_mutex_unlock(&lo->mutex); +- if (fh == -1) { +- close(fd); +- fuse_reply_err(req, ENOMEM); ++ if (!inode) { ++ fuse_reply_err(req, EBADF); + return; + } + +- fi->fh = fh; +- if (lo->cache == CACHE_NONE) { +- fi->direct_io = 1; +- } else if (lo->cache == CACHE_ALWAYS) { +- fi->keep_cache = 1; ++ err = lo_do_open(lo, inode, fi); ++ lo_inode_put(lo, &inode); ++ if (err) { ++ fuse_reply_err(req, err); ++ } else { ++ fuse_reply_open(req, fi); + } +- fuse_reply_open(req, fi); + } + + static void lo_release(fuse_req_t req, fuse_ino_t ino, diff --git a/virtiofsd-optionally-return-inode-pointe.patch b/virtiofsd-optionally-return-inode-pointe.patch new file mode 100644 index 00000000..d9ef4d2d --- /dev/null +++ b/virtiofsd-optionally-return-inode-pointe.patch @@ -0,0 +1,108 @@ +From: Stefan Hajnoczi +Date: Thu, 4 Feb 2021 15:02:07 +0000 +Subject: virtiofsd: optionally return inode pointer from lo_do_lookup() + +Git-commit: 22d2ece71e533310da31f2857ebc4a00d91968b3 +References: bsc#1183373, CVE-2021-20263 + +lo_do_lookup() finds an existing inode or allocates a new one. It +increments nlookup so that the inode stays alive until the client +releases it. + +Existing callers don't need the struct lo_inode so the function doesn't +return it. Extend the function to optionally return the inode. The next +commit will need it. + +Signed-off-by: Stefan Hajnoczi +Reviewed-by: Greg Kurz +Message-Id: <20210204150208.367837-3-stefanha@redhat.com> +Signed-off-by: Dr. David Alan Gilbert +Signed-off-by: Bruce Rogers +--- + tools/virtiofsd/passthrough_ll.c | 29 +++++++++++++++++++++-------- + 1 file changed, 21 insertions(+), 8 deletions(-) + +diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c +index 218e20e9d7901f22e26ef8dc56c2..2bd050b6202e41476dc1cdce811a 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -843,11 +843,13 @@ static int do_statx(struct lo_data *lo, int dirfd, const char *pathname, + } + + /* +- * Increments nlookup and caller must release refcount using +- * lo_inode_put(&parent). ++ * Increments nlookup on the inode on success. unref_inode_lolocked() must be ++ * called eventually to decrement nlookup again. If inodep is non-NULL, the ++ * inode pointer is stored and the caller must call lo_inode_put(). + */ + static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name, +- struct fuse_entry_param *e) ++ struct fuse_entry_param *e, ++ struct lo_inode **inodep) + { + int newfd; + int res; +@@ -857,6 +859,10 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name, + struct lo_inode *inode = NULL; + struct lo_inode *dir = lo_inode(req, parent); + ++ if (inodep) { ++ *inodep = NULL; ++ } ++ + /* + * name_to_handle_at() and open_by_handle_at() can reach here with fuse + * mount point in guest, but we don't have its inode info in the +@@ -924,7 +930,14 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name, + pthread_mutex_unlock(&lo->mutex); + } + e->ino = inode->fuse_ino; +- lo_inode_put(lo, &inode); ++ ++ /* Transfer ownership of inode pointer to caller or drop it */ ++ if (inodep) { ++ *inodep = inode; ++ } else { ++ lo_inode_put(lo, &inode); ++ } ++ + lo_inode_put(lo, &dir); + + fuse_log(FUSE_LOG_DEBUG, " %lli/%s -> %lli\n", (unsigned long long)parent, +@@ -959,7 +972,7 @@ static void lo_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) + return; + } + +- err = lo_do_lookup(req, parent, name, &e); ++ err = lo_do_lookup(req, parent, name, &e, NULL); + if (err) { + fuse_reply_err(req, err); + } else { +@@ -1067,7 +1080,7 @@ static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent, + goto out; + } + +- saverr = lo_do_lookup(req, parent, name, &e); ++ saverr = lo_do_lookup(req, parent, name, &e, NULL); + if (saverr) { + goto out; + } +@@ -1544,7 +1557,7 @@ static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, + + if (plus) { + if (!is_dot_or_dotdot(name)) { +- err = lo_do_lookup(req, ino, name, &e); ++ err = lo_do_lookup(req, ino, name, &e, NULL); + if (err) { + goto error; + } +@@ -1742,7 +1755,7 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name, + } + + fi->fh = fh; +- err = lo_do_lookup(req, parent, name, &e); ++ err = lo_do_lookup(req, parent, name, &e, NULL); + } + if (lo->cache == CACHE_NONE) { + fi->direct_io = 1; diff --git a/virtiofsd-prevent-opening-of-special-fil.patch b/virtiofsd-prevent-opening-of-special-fil.patch new file mode 100644 index 00000000..da714eee --- /dev/null +++ b/virtiofsd-prevent-opening-of-special-fil.patch @@ -0,0 +1,298 @@ +From: Stefan Hajnoczi +Date: Thu, 4 Feb 2021 15:02:08 +0000 +Subject: virtiofsd: prevent opening of special files (CVE-2020-35517) + +Git-commit: a3fdbbc7f271bff7d53d0501b29d910ece0b3789 +References: bsc#1183373, CVE-2021-20263 + +A well-behaved FUSE client does not attempt to open special files with +FUSE_OPEN because they are handled on the client side (e.g. device nodes +are handled by client-side device drivers). + +The check to prevent virtiofsd from opening special files is missing in +a few cases, most notably FUSE_OPEN. A malicious client can cause +virtiofsd to open a device node, potentially allowing the guest to +escape. This can be exploited by a modified guest device driver. It is +not exploitable from guest userspace since the guest kernel will handle +special files inside the guest instead of sending FUSE requests. + +This patch fixes this issue by introducing the lo_inode_open() function +to check the file type before opening it. This is a short-term solution +because it does not prevent a compromised virtiofsd process from opening +device nodes on the host. + +Restructure lo_create() to try O_CREAT | O_EXCL first. Note that O_CREAT +| O_EXCL does not follow symlinks, so O_NOFOLLOW masking is not +necessary here. If the file exists and the user did not specify O_EXCL, +open it via lo_do_open(). + +Reported-by: Alex Xu +Fixes: CVE-2020-35517 +Reviewed-by: Dr. David Alan Gilbert +Reviewed-by: Vivek Goyal +Reviewed-by: Greg Kurz +Signed-off-by: Stefan Hajnoczi +Message-Id: <20210204150208.367837-4-stefanha@redhat.com> +Signed-off-by: Dr. David Alan Gilbert +Signed-off-by: Bruce Rogers +--- + tools/virtiofsd/passthrough_ll.c | 144 ++++++++++++++++++++----------- + 1 file changed, 92 insertions(+), 52 deletions(-) + +diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c +index 2bd050b6202e41476dc1cdce811a..03c5e0d13c35849ec90d32fa38a2 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -567,6 +567,38 @@ static int lo_fd(fuse_req_t req, fuse_ino_t ino) + return fd; + } + ++/* ++ * Open a file descriptor for an inode. Returns -EBADF if the inode is not a ++ * regular file or a directory. ++ * ++ * Use this helper function instead of raw openat(2) to prevent security issues ++ * when a malicious client opens special files such as block device nodes. ++ * Symlink inodes are also rejected since symlinks must already have been ++ * traversed on the client side. ++ */ ++static int lo_inode_open(struct lo_data *lo, struct lo_inode *inode, ++ int open_flags) ++{ ++ g_autofree char *fd_str = g_strdup_printf("%d", inode->fd); ++ int fd; ++ ++ if (!S_ISREG(inode->filetype) && !S_ISDIR(inode->filetype)) { ++ return -EBADF; ++ } ++ ++ /* ++ * The file is a symlink so O_NOFOLLOW must be ignored. We checked earlier ++ * that the inode is not a special file but if an external process races ++ * with us then symlinks are traversed here. It is not possible to escape ++ * the shared directory since it is mounted as "/" though. ++ */ ++ fd = openat(lo->proc_self_fd, fd_str, open_flags & ~O_NOFOLLOW); ++ if (fd < 0) { ++ return -errno; ++ } ++ return fd; ++} ++ + static void lo_init(void *userdata, struct fuse_conn_info *conn) + { + struct lo_data *lo = (struct lo_data *)userdata; +@@ -696,9 +728,9 @@ static void lo_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, + if (fi) { + truncfd = fd; + } else { +- sprintf(procname, "%i", ifd); +- truncfd = openat(lo->proc_self_fd, procname, O_RDWR); ++ truncfd = lo_inode_open(lo, inode, O_RDWR); + if (truncfd < 0) { ++ errno = -truncfd; + goto out_err; + } + } +@@ -860,7 +892,7 @@ static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char *name, + struct lo_inode *dir = lo_inode(req, parent); + + if (inodep) { +- *inodep = NULL; ++ *inodep = NULL; /* in case there is an error */ + } + + /* +@@ -1674,19 +1706,26 @@ static void update_open_flags(int writeback, int allow_direct_io, + } + } + ++/* ++ * Open a regular file, set up an fd mapping, and fill out the struct ++ * fuse_file_info for it. If existing_fd is not negative, use that fd instead ++ * opening a new one. Takes ownership of existing_fd. ++ * ++ * Returns 0 on success or a positive errno. ++ */ + static int lo_do_open(struct lo_data *lo, struct lo_inode *inode, +- struct fuse_file_info *fi) ++ int existing_fd, struct fuse_file_info *fi) + { +- char buf[64]; + ssize_t fh; +- int fd; ++ int fd = existing_fd; + + update_open_flags(lo->writeback, lo->allow_direct_io, fi); + +- sprintf(buf, "%i", inode->fd); +- fd = openat(lo->proc_self_fd, buf, fi->flags & ~O_NOFOLLOW); +- if (fd == -1) { +- return errno; ++ if (fd < 0) { ++ fd = lo_inode_open(lo, inode, fi->flags); ++ if (fd < 0) { ++ return -fd; ++ } + } + + pthread_mutex_lock(&lo->mutex); +@@ -1709,9 +1748,10 @@ static int lo_do_open(struct lo_data *lo, struct lo_inode *inode, + static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode, struct fuse_file_info *fi) + { +- int fd; ++ int fd = -1; + struct lo_data *lo = lo_data(req); + struct lo_inode *parent_inode; ++ struct lo_inode *inode = NULL; + struct fuse_entry_param e; + int err; + struct lo_cred old = {}; +@@ -1737,36 +1777,38 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name, + + update_open_flags(lo->writeback, lo->allow_direct_io, fi); + +- fd = openat(parent_inode->fd, name, (fi->flags | O_CREAT) & ~O_NOFOLLOW, +- mode); ++ /* Try to create a new file but don't open existing files */ ++ fd = openat(parent_inode->fd, name, fi->flags | O_CREAT | O_EXCL, mode); + err = fd == -1 ? errno : 0; +- lo_restore_cred(&old); + +- if (!err) { +- ssize_t fh; ++ lo_restore_cred(&old); + +- pthread_mutex_lock(&lo->mutex); +- fh = lo_add_fd_mapping(lo, fd); +- pthread_mutex_unlock(&lo->mutex); +- if (fh == -1) { +- close(fd); +- err = ENOMEM; +- goto out; +- } ++ /* Ignore the error if file exists and O_EXCL was not given */ ++ if (err && (err != EEXIST || (fi->flags & O_EXCL))) { ++ goto out; ++ } + +- fi->fh = fh; +- err = lo_do_lookup(req, parent, name, &e, NULL); ++ err = lo_do_lookup(req, parent, name, &e, &inode); ++ if (err) { ++ goto out; + } +- if (lo->cache == CACHE_NONE) { +- fi->direct_io = 1; +- } else if (lo->cache == CACHE_ALWAYS) { +- fi->keep_cache = 1; ++ ++ err = lo_do_open(lo, inode, fd, fi); ++ fd = -1; /* lo_do_open() takes ownership of fd */ ++ if (err) { ++ /* Undo lo_do_lookup() nlookup ref */ ++ unref_inode_lolocked(lo, inode, 1); + } + + out: ++ lo_inode_put(lo, &inode); + lo_inode_put(lo, &parent_inode); + + if (err) { ++ if (fd >= 0) { ++ close(fd); ++ } ++ + fuse_reply_err(req, err); + } else { + fuse_reply_create(req, &e, fi); +@@ -1780,7 +1822,6 @@ static struct lo_inode_plock *lookup_create_plock_ctx(struct lo_data *lo, + pid_t pid, int *err) + { + struct lo_inode_plock *plock; +- char procname[64]; + int fd; + + plock = +@@ -1797,12 +1838,10 @@ static struct lo_inode_plock *lookup_create_plock_ctx(struct lo_data *lo, + } + + /* Open another instance of file which can be used for ofd locks. */ +- sprintf(procname, "%i", inode->fd); +- + /* TODO: What if file is not writable? */ +- fd = openat(lo->proc_self_fd, procname, O_RDWR); +- if (fd == -1) { +- *err = errno; ++ fd = lo_inode_open(lo, inode, O_RDWR); ++ if (fd < 0) { ++ *err = -fd; + free(plock); + return NULL; + } +@@ -1949,7 +1988,7 @@ static void lo_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) + return; + } + +- err = lo_do_open(lo, inode, fi); ++ err = lo_do_open(lo, inode, -1, fi); + lo_inode_put(lo, &inode); + if (err) { + fuse_reply_err(req, err); +@@ -2005,39 +2044,40 @@ static void lo_flush(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) + static void lo_fsync(fuse_req_t req, fuse_ino_t ino, int datasync, + struct fuse_file_info *fi) + { ++ struct lo_inode *inode = lo_inode(req, ino); ++ struct lo_data *lo = lo_data(req); + int res; + int fd; +- char *buf; + + fuse_log(FUSE_LOG_DEBUG, "lo_fsync(ino=%" PRIu64 ", fi=0x%p)\n", ino, + (void *)fi); + +- if (!fi) { +- struct lo_data *lo = lo_data(req); +- +- res = asprintf(&buf, "%i", lo_fd(req, ino)); +- if (res == -1) { +- return (void)fuse_reply_err(req, errno); +- } ++ if (!inode) { ++ fuse_reply_err(req, EBADF); ++ return; ++ } + +- fd = openat(lo->proc_self_fd, buf, O_RDWR); +- free(buf); +- if (fd == -1) { +- return (void)fuse_reply_err(req, errno); ++ if (!fi) { ++ fd = lo_inode_open(lo, inode, O_RDWR); ++ if (fd < 0) { ++ res = -fd; ++ goto out; + } + } else { + fd = lo_fi_fd(req, fi); + } + + if (datasync) { +- res = fdatasync(fd); ++ res = fdatasync(fd) == -1 ? errno : 0; + } else { +- res = fsync(fd); ++ res = fsync(fd) == -1 ? errno : 0; + } + if (!fi) { + close(fd); + } +- fuse_reply_err(req, res == -1 ? errno : 0); ++out: ++ lo_inode_put(lo, &inode); ++ fuse_reply_err(req, res); + } + + static void lo_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset, diff --git a/xen-add-block-resize-support-for-xen-dis.patch b/xen-add-block-resize-support-for-xen-dis.patch index 63e924d2..f16757b0 100644 --- a/xen-add-block-resize-support-for-xen-dis.patch +++ b/xen-add-block-resize-support-for-xen-dis.patch @@ -15,7 +15,7 @@ Signed-off-by: Bruce Rogers 1 file changed, 3 insertions(+) diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c -index 5f96036c98cc2eada06186ff181c..903633e028266d6c7e73239672b0 100644 +index f6b66a0428eaa37db4c1bbe7e2c4..4bfd55a854afdc2359f03610724d 100644 --- a/hw/block/xen-block.c +++ b/hw/block/xen-block.c @@ -270,6 +270,9 @@ static void xen_block_realize(XenDevice *xendev, Error **errp) diff --git a/xen-block-Fix-removal-of-backend-instanc.patch b/xen-block-Fix-removal-of-backend-instanc.patch new file mode 100644 index 00000000..4bfec74a --- /dev/null +++ b/xen-block-Fix-removal-of-backend-instanc.patch @@ -0,0 +1,49 @@ +From: Anthony PERARD +Date: Mon, 8 Mar 2021 14:32:32 +0000 +Subject: xen-block: Fix removal of backend instance via xenstore + +Git-commit: b807ca3fa0ca29ec015adcf4045e716337cd3635 + +Whenever a Xen block device is detach via xenstore, the image +associated with it remained open by the backend QEMU and an error is +logged: + qemu-system-i386: failed to destroy drive: Node xvdz-qcow2 is in use + +This happened since object_unparent() doesn't immediately frees the +object and thus keep a reference to the node we are trying to free. +The reference is hold by the "drive" property and the call +xen_block_drive_destroy() fails. + +In order to fix that, we call drain_call_rcu() to run the callback +setup by bus_remove_child() via object_unparent(). + +Fixes: 2d24a6466154 ("device-core: use RCU for list of children of a bus") + +Signed-off-by: Anthony PERARD +Reviewed-by: Paul Durrant +Message-Id: <20210308143232.83388-1-anthony.perard@citrix.com> +Signed-off-by: Bruce Rogers +--- + hw/block/xen-block.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c +index 20b23c699bc1cb4cd796bf352c45..b1a3fa9b6a91f7748ce54d77cad6 100644 +--- a/hw/block/xen-block.c ++++ b/hw/block/xen-block.c +@@ -978,6 +978,15 @@ static void xen_block_device_destroy(XenBackendInstance *backend, + + object_unparent(OBJECT(xendev)); + ++ /* ++ * Drain all pending RCU callbacks as object_unparent() frees `xendev' ++ * in a RCU callback. ++ * And due to the property "drive" still existing in `xendev', we ++ * can't destroy the XenBlockDrive associated with `xendev' with ++ * xen_block_drive_destroy() below. ++ */ ++ drain_call_rcu(); ++ + if (iothread) { + xen_block_iothread_destroy(iothread, errp); + if (*errp) { diff --git a/xen_disk-Add-suse-specific-flush-disable.patch b/xen_disk-Add-suse-specific-flush-disable.patch index 186e0e86..349a9870 100644 --- a/xen_disk-Add-suse-specific-flush-disable.patch +++ b/xen_disk-Add-suse-specific-flush-disable.patch @@ -18,7 +18,7 @@ Signed-off-by: Olaf Hering 1 file changed, 12 insertions(+) diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c -index 20b23c699bc1cb4cd796bf352c45..5f96036c98cc2eada06186ff181c 100644 +index b1a3fa9b6a91f7748ce54d77cad6..f6b66a0428eaa37db4c1bbe7e2c4 100644 --- a/hw/block/xen-block.c +++ b/hw/block/xen-block.c @@ -729,6 +729,8 @@ static XenBlockDrive *xen_block_drive_create(const char *id,