SHA256
1
0
forked from pool/qemu

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
This commit is contained in:
Bruce Rogers 2021-03-30 20:27:28 +00:00 committed by Git OBS Bridge
parent 0cf745d181
commit 86ffd40d11
47 changed files with 3259 additions and 415 deletions

View File

@ -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

View File

@ -14,7 +14,7 @@ Signed-off-by: Bruce Rogers <brogers@suse.com>
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,

View File

@ -2,7 +2,7 @@ From: Kevin Wolf <kwolf@redhat.com>
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

View File

@ -2,7 +2,7 @@ From: Kevin Wolf <kwolf@redhat.com>
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.

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5eea7b1721613d6f843d6e94469431d4382e88e106bff9ac121acfcab88df9fc
size 79240
oid sha256:b1d2867d10746cf923467f5bddfbf443f001f1363dba4c9c099fc395ac8c2e75
size 100056

View File

@ -0,0 +1,39 @@
From: Alexander Bulekov <alxndr@bu.edu>
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 <ppandit@redhat.com>
Cc: qemu-stable@nongnu.org
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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);

View File

@ -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

View File

@ -0,0 +1,36 @@
From: Jason Wang <jasowang@redhat.com>
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 <ppandit@redhat.com>
Cc: qemu-stable@nongnu.org
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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 */

View File

@ -0,0 +1,36 @@
From: Jason Wang <jasowang@redhat.com>
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 <ppandit@redhat.com>
Cc: qemu-stable@nongnu.org
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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);
}

View File

@ -0,0 +1,87 @@
From: Gavin Shan <gshan@redhat.com>
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 <drjones@redhat.com>
Signed-off-by: Gavin Shan <gshan@redhat.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Message-id: 20210318023801.18287-1-gshan@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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;
};

View File

@ -1,248 +0,0 @@
From: Halil Pasic <pasic@linux.ibm.com>
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 <pasic@linux.ibm.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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" },

View File

@ -0,0 +1,69 @@
From: Bin Meng <bin.meng@windriver.com>
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 <bin.meng@windriver.com>
Message-Id: <1613811493-58815-1-git-send-email-bmeng.cn@gmail.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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);
}
}

View File

@ -0,0 +1,35 @@
From: Bin Meng <bin.meng@windriver.com>
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 <bin.meng@windriver.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20210228050609.24779-1-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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"

View File

@ -0,0 +1,83 @@
From: Bin Meng <bin.meng@windriver.com>
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 <bin.meng@windriver.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20210216150225.27996-5-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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;

View File

@ -0,0 +1,71 @@
From: Bin Meng <bin.meng@windriver.com>
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 <bin.meng@windriver.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20210216150225.27996-6-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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;
+ }
}
}
}

View File

@ -0,0 +1,70 @@
From: Bin Meng <bmeng.cn@gmail.com>
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 <alxndr@bu.edu>
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 <alxndr@bu.edu>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Message-Id: <20210303122639.20004-4-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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) {

View File

@ -0,0 +1,87 @@
From: Bin Meng <bmeng.cn@gmail.com>
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 <alxndr@bu.edu>
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 <alistair.francis@wdc.com>
Tested-by: Alexander Bulekov <alxndr@bu.edu>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Message-Id: <20210303122639.20004-2-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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);
}

View File

@ -0,0 +1,105 @@
From: Bin Meng <bmeng.cn@gmail.com>
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 <alxndr@bu.edu>
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 <alxndr@bu.edu>
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Message-Id: <20210303122639.20004-3-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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;

View File

@ -0,0 +1,52 @@
From: Bin Meng <bmeng.cn@gmail.com>
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 <alxndr@bu.edu>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Message-Id: <20210303122639.20004-5-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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;

View File

@ -0,0 +1,95 @@
From: Bin Meng <bmeng.cn@gmail.com>
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 <alxndr@bu.edu>
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 <alxndr@bu.edu>
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Message-Id: <20210303122639.20004-6-bmeng.cn@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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;

View File

@ -2,7 +2,7 @@ From: Max Reitz <mreitz@redhat.com>
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:

View File

@ -0,0 +1,37 @@
From: Alexander Bulekov <alxndr@bu.edu>
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 <ppandit@redhat.com>
Cc: qemu-stable@nongnu.org
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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);
}

View File

@ -0,0 +1,137 @@
From: Paolo Bonzini <pbonzini@redhat.com>
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 <pbonzini@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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();

View File

@ -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);
}

View File

@ -0,0 +1,36 @@
From: Jason Wang <jasowang@redhat.com>
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 <ppandit@redhat.com>
Cc: qemu-stable@nongnu.org
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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);
}

View File

@ -0,0 +1,171 @@
From: Jason Wang <jasowang@redhat.com>
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 <ppandit@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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,

View File

@ -0,0 +1,38 @@
From: Alexander Bulekov <alxndr@bu.edu>
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 <ppandit@redhat.com>
Cc: qemu-stable@nongnu.org
Buglink: https://bugs.launchpad.net/qemu/+bug/1917085
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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) {

View File

@ -1,3 +1,61 @@
-------------------------------------------------------------------
Tue Mar 30 17:30:11 UTC 2021 - Bruce Rogers <brogers@suse.com>
- 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 <brogers@suse.com>
- 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 <brogers@suse.com>

230
qemu.spec
View File

@ -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

View File

@ -14,7 +14,7 @@ Signed-off-by: Bruce Rogers <brogers@suse.com>
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)

View File

@ -0,0 +1,39 @@
From: Alexander Bulekov <alxndr@bu.edu>
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 <ppandit@redhat.com>
Cc: qemu-stable@nongnu.org
Buglink: https://bugs.launchpad.net/qemu/+bug/1910826
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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);

View File

@ -0,0 +1,50 @@
From: Gerd Hoffmann <kraxel@redhat.com>
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 <kraxel@redhat.com>
Reviewed-by: Halil Pasic <pasic@linux.ibm.com>
Tested-by: Halil Pasic <pasic@linux.ibm.com>
Message-Id: <20210317095622.2839895-3-kraxel@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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;

View File

@ -0,0 +1,87 @@
From: Gerd Hoffmann <kraxel@redhat.com>
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 <pasic@linux.ibm.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Halil Pasic <pasic@linux.ibm.com>
Tested-by: Halil Pasic <pasic@linux.ibm.com>
Message-Id: <20210317095622.2839895-4-kraxel@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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" },

View File

@ -0,0 +1,96 @@
From: Gerd Hoffmann <kraxel@redhat.com>
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 <pasic@linux.ibm.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Halil Pasic <pasic@linux.ibm.com>
Tested-by: Halil Pasic <pasic@linux.ibm.com>
Message-Id: <20210317095622.2839895-2-kraxel@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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 */

View File

@ -0,0 +1,38 @@
From: Jason Wang <jasowang@redhat.com>
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 <ppandit@redhat.com>
Cc: qemu-stable@nongnu.org
Reviewed-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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);
}

View File

@ -0,0 +1,93 @@
From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <philmd@redhat.com>
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 <dgilbert@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20210205171817.2108907-3-philmd@redhat.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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 */

View File

@ -0,0 +1,36 @@
From: Jason Wang <jasowang@redhat.com>
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 <ppandit@redhat.com>
Cc: qemu-stable@nongnu.org
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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);
}

View File

@ -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

View File

@ -0,0 +1,335 @@
From: Vivek Goyal <vgoyal@redhat.com>
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 <vgoyal@redhat.com>
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Message-Id: <20210208224024.43555-3-vgoyal@redhat.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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;

View File

@ -0,0 +1,208 @@
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
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 <dgilbert@redhat.com>
Reviewed-by: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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);
}

View File

@ -0,0 +1,87 @@
From: Vivek Goyal <vgoyal@redhat.com>
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 <vgoyal@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Message-Id: <20210208224024.43555-2-vgoyal@redhat.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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);
}

View File

@ -0,0 +1,145 @@
From: Stefan Hajnoczi <stefanha@redhat.com>
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 <stefanha@redhat.com>
Message-Id: <20210204150208.367837-2-stefanha@redhat.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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,

View File

@ -0,0 +1,108 @@
From: Stefan Hajnoczi <stefanha@redhat.com>
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 <stefanha@redhat.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
Message-Id: <20210204150208.367837-3-stefanha@redhat.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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;

View File

@ -0,0 +1,298 @@
From: Stefan Hajnoczi <stefanha@redhat.com>
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 <alex@alxu.ca>
Fixes: CVE-2020-35517
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Reviewed-by: Vivek Goyal <vgoyal@redhat.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-Id: <20210204150208.367837-4-stefanha@redhat.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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,

View File

@ -15,7 +15,7 @@ Signed-off-by: Bruce Rogers <brogers@suse.com>
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)

View File

@ -0,0 +1,49 @@
From: Anthony PERARD <anthony.perard@citrix.com>
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 <anthony.perard@citrix.com>
Reviewed-by: Paul Durrant <paul@xen.org>
Message-Id: <20210308143232.83388-1-anthony.perard@citrix.com>
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
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) {

View File

@ -18,7 +18,7 @@ Signed-off-by: Olaf Hering <olaf@aepfle.de>
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,