From 6e7d01bb82101ac098abc8a67018d5985f068b2a Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Oct 05 2021 23:57:49 +0000 Subject: import qemu-kvm-4.2.0-58.module+el8.5.0+12272+74ace547 --- diff --git a/SOURCES/kvm-Add-mtod_check.patch b/SOURCES/kvm-Add-mtod_check.patch new file mode 100644 index 0000000..0b2e710 --- /dev/null +++ b/SOURCES/kvm-Add-mtod_check.patch @@ -0,0 +1,68 @@ +From 52bf635da30c75d0fdb0a3e7e7b9a2483ca033fc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Thu, 29 Jul 2021 04:55:59 -0400 +Subject: [PATCH 05/14] Add mtod_check() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Marc-André Lureau +Message-id: <20210708082537.1550263-2-marcandre.lureau@redhat.com> +Patchwork-id: 101819 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 1/8] Add mtod_check() +Bugzilla: 1970819 1970835 1970843 1970853 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Eric Blake +RH-Acked-by: Stefan Hajnoczi + +From: Marc-André Lureau + +Recent security issues demonstrate the lack of safety care when casting +a mbuf to a particular structure type. At least, it should check that +the buffer is large enough. The following patches will make use of this +function. + +Signed-off-by: Marc-André Lureau + +(cherry picked from commit 93e645e72a056ec0b2c16e0299fc5c6b94e4ca17) +Signed-off-by: Marc-André Lureau +Signed-off-by: Miroslav Rezanina +--- + slirp/src/mbuf.c | 11 +++++++++++ + slirp/src/mbuf.h | 1 + + 2 files changed, 12 insertions(+) + +diff --git a/slirp/src/mbuf.c b/slirp/src/mbuf.c +index 4fd62282a9..6d0653ed3d 100644 +--- a/slirp/src/mbuf.c ++++ b/slirp/src/mbuf.c +@@ -222,3 +222,14 @@ struct mbuf *dtom(Slirp *slirp, void *dat) + + return (struct mbuf *)0; + } ++ ++void *mtod_check(struct mbuf *m, size_t len) ++{ ++ if (m->m_len >= len) { ++ return m->m_data; ++ } ++ ++ DEBUG_ERROR("mtod failed"); ++ ++ return NULL; ++} +diff --git a/slirp/src/mbuf.h b/slirp/src/mbuf.h +index 546e7852c5..2015e3232f 100644 +--- a/slirp/src/mbuf.h ++++ b/slirp/src/mbuf.h +@@ -118,6 +118,7 @@ void m_inc(struct mbuf *, int); + void m_adj(struct mbuf *, int); + int m_copy(struct mbuf *, struct mbuf *, int, int); + struct mbuf *dtom(Slirp *, void *); ++void *mtod_check(struct mbuf *, size_t len); + + static inline void ifs_init(struct mbuf *ifm) + { +-- +2.27.0 + diff --git a/SOURCES/kvm-Compress-lines-for-immediate-return.patch b/SOURCES/kvm-Compress-lines-for-immediate-return.patch new file mode 100644 index 0000000..aed5149 --- /dev/null +++ b/SOURCES/kvm-Compress-lines-for-immediate-return.patch @@ -0,0 +1,242 @@ +From 5cf6dd33456c4e7e2a8849f458ce234fb5bb290c Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Fri, 25 Jun 2021 17:41:03 -0400 +Subject: [PATCH 3/4] Compress lines for immediate return +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Kevin Wolf +Message-id: <20210625174104.44313-2-kwolf@redhat.com> +Patchwork-id: 101777 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 1/2] Compress lines for immediate return +Bugzilla: 1970912 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth + +From: Simran Singhal + +Compress two lines into a single line if immediate return statement is found. + +It also remove variables progress, val, data, ret and sock +as they are no longer needed. + +Remove space between function "mixer_load" and '(' to fix the +checkpatch.pl error:- +ERROR: space prohibited between function name and open parenthesis '(' + +Done using following coccinelle script: +@@ +local idexpression ret; +expression e; +@@ + +-ret = ++return + e; +-return ret; + +Signed-off-by: Simran Singhal +Reviewed-by: Stefan Hajnoczi +Message-Id: <20200401165314.GA3213@simran-Inspiron-5558> +[lv: in handle_aiocb_write_zeroes_unmap() move "int ret" inside the #ifdef] +Signed-off-by: Laurent Vivier +(cherry picked from commit b3ac2b94cdc939a90d5a22338ae507689e2cfab0) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block/file-posix.c | 8 +++----- + block/nfs.c | 3 +-- + block/nvme.c | 4 +--- + block/vhdx.c | 3 +-- + hw/audio/ac97.c | 4 +--- + hw/audio/adlib.c | 5 +---- + hw/display/cirrus_vga.c | 4 +--- + migration/ram.c | 4 +--- + ui/gtk.c | 3 +-- + util/qemu-sockets.c | 5 +---- + 10 files changed, 12 insertions(+), 31 deletions(-) + +diff --git a/block/file-posix.c b/block/file-posix.c +index 371572f1b0..837edcf027 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -1626,13 +1626,12 @@ static int handle_aiocb_write_zeroes_unmap(void *opaque) + { + RawPosixAIOData *aiocb = opaque; + BDRVRawState *s G_GNUC_UNUSED = aiocb->bs->opaque; +- int ret; + + /* First try to write zeros and unmap at the same time */ + + #ifdef CONFIG_FALLOCATE_PUNCH_HOLE +- ret = do_fallocate(s->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, +- aiocb->aio_offset, aiocb->aio_nbytes); ++ int ret = do_fallocate(s->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, ++ aiocb->aio_offset, aiocb->aio_nbytes); + if (ret != -ENOTSUP) { + return ret; + } +@@ -1640,8 +1639,7 @@ static int handle_aiocb_write_zeroes_unmap(void *opaque) + + /* If we couldn't manage to unmap while guaranteed that the area reads as + * all-zero afterwards, just write zeroes without unmapping */ +- ret = handle_aiocb_write_zeroes(aiocb); +- return ret; ++ return handle_aiocb_write_zeroes(aiocb); + } + + #ifndef HAVE_COPY_FILE_RANGE +diff --git a/block/nfs.c b/block/nfs.c +index 2393fbfe6b..18c0a73694 100644 +--- a/block/nfs.c ++++ b/block/nfs.c +@@ -623,8 +623,7 @@ static int nfs_file_open(BlockDriverState *bs, QDict *options, int flags, + } + + bs->total_sectors = ret; +- ret = 0; +- return ret; ++ return 0; + } + + static QemuOptsList nfs_create_opts = { +diff --git a/block/nvme.c b/block/nvme.c +index 7b7c0cc5d6..eb2f54dd9d 100644 +--- a/block/nvme.c ++++ b/block/nvme.c +@@ -575,11 +575,9 @@ static bool nvme_poll_cb(void *opaque) + { + EventNotifier *e = opaque; + BDRVNVMeState *s = container_of(e, BDRVNVMeState, irq_notifier); +- bool progress = false; + + trace_nvme_poll_cb(s); +- progress = nvme_poll_queues(s); +- return progress; ++ return nvme_poll_queues(s); + } + + static int nvme_init(BlockDriverState *bs, const char *device, int namespace, +diff --git a/block/vhdx.c b/block/vhdx.c +index 21497f7318..a427e47f10 100644 +--- a/block/vhdx.c ++++ b/block/vhdx.c +@@ -411,8 +411,7 @@ int vhdx_update_headers(BlockDriverState *bs, BDRVVHDXState *s, + if (ret < 0) { + return ret; + } +- ret = vhdx_update_header(bs, s, generate_data_write_guid, log_guid); +- return ret; ++ return vhdx_update_header(bs, s, generate_data_write_guid, log_guid); + } + + /* opens the specified header block from the VHDX file header section */ +diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c +index a136b97f68..a2cfae52b3 100644 +--- a/hw/audio/ac97.c ++++ b/hw/audio/ac97.c +@@ -574,11 +574,9 @@ static uint32_t nam_readb (void *opaque, uint32_t addr) + static uint32_t nam_readw (void *opaque, uint32_t addr) + { + AC97LinkState *s = opaque; +- uint32_t val = ~0U; + uint32_t index = addr; + s->cas = 0; +- val = mixer_load (s, index); +- return val; ++ return mixer_load(s, index); + } + + static uint32_t nam_readl (void *opaque, uint32_t addr) +diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c +index cb4178d861..5779d09815 100644 +--- a/hw/audio/adlib.c ++++ b/hw/audio/adlib.c +@@ -120,13 +120,10 @@ static void adlib_write(void *opaque, uint32_t nport, uint32_t val) + static uint32_t adlib_read(void *opaque, uint32_t nport) + { + AdlibState *s = opaque; +- uint8_t data; + int a = nport & 3; + + adlib_kill_timers (s); +- data = OPLRead (s->opl, a); +- +- return data; ++ return OPLRead (s->opl, a); + } + + static void timer_handler (void *opaque, int c, double interval_Sec) +diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c +index 93afa26fda..a52d3094b9 100644 +--- a/hw/display/cirrus_vga.c ++++ b/hw/display/cirrus_vga.c +@@ -2411,12 +2411,10 @@ static uint64_t cirrus_linear_bitblt_read(void *opaque, + unsigned size) + { + CirrusVGAState *s = opaque; +- uint32_t ret; + + /* XXX handle bitblt */ + (void)s; +- ret = 0xff; +- return ret; ++ return 0xff; + } + + static void cirrus_linear_bitblt_write(void *opaque, +diff --git a/migration/ram.c b/migration/ram.c +index 5344c7d59e..92c506d13c 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -3101,9 +3101,7 @@ int ram_postcopy_send_discard_bitmap(MigrationState *ms) + } + trace_ram_postcopy_send_discard_bitmap(); + +- ret = postcopy_each_ram_send_discard(ms); +- +- return ret; ++ return postcopy_each_ram_send_discard(ms); + } + + /** +diff --git a/ui/gtk.c b/ui/gtk.c +index 692ccc7bbb..e032e3c36f 100644 +--- a/ui/gtk.c ++++ b/ui/gtk.c +@@ -1649,8 +1649,7 @@ static GSList *gd_vc_menu_init(GtkDisplayState *s, VirtualConsole *vc, + G_CALLBACK(gd_menu_switch_vc), s); + gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), vc->menu_item); + +- group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(vc->menu_item)); +- return group; ++ return gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(vc->menu_item)); + } + + #if defined(CONFIG_VTE) +diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c +index bcc06d0e01..86c48b9fa5 100644 +--- a/util/qemu-sockets.c ++++ b/util/qemu-sockets.c +@@ -765,15 +765,12 @@ static int vsock_connect_addr(const struct sockaddr_vm *svm, Error **errp) + static int vsock_connect_saddr(VsockSocketAddress *vaddr, Error **errp) + { + struct sockaddr_vm svm; +- int sock = -1; + + if (!vsock_parse_vaddr_to_sockaddr(vaddr, &svm, errp)) { + return -1; + } + +- sock = vsock_connect_addr(&svm, errp); +- +- return sock; ++ return vsock_connect_addr(&svm, errp); + } + + static int vsock_listen_saddr(VsockSocketAddress *vaddr, +-- +2.27.0 + diff --git a/SOURCES/kvm-Fix-DHCP-broken-in-libslirp-v4.6.0.patch b/SOURCES/kvm-Fix-DHCP-broken-in-libslirp-v4.6.0.patch new file mode 100644 index 0000000..2dd4457 --- /dev/null +++ b/SOURCES/kvm-Fix-DHCP-broken-in-libslirp-v4.6.0.patch @@ -0,0 +1,59 @@ +From d0c668aa0ad255c3598267816154874541ac2943 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Thu, 29 Jul 2021 04:56:42 -0400 +Subject: [PATCH 12/14] Fix "DHCP broken in libslirp v4.6.0" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Marc-André Lureau +Message-id: <20210708082537.1550263-9-marcandre.lureau@redhat.com> +Patchwork-id: 101824 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 8/8] Fix "DHCP broken in libslirp v4.6.0" +Bugzilla: 1970819 1970835 1970843 1970853 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Eric Blake +RH-Acked-by: Stefan Hajnoczi + +From: Akihiro Suda + +Fix issue 48 + +Signed-off-by: Akihiro Suda + +(cherry picked from commit c9f314f6e315a5518432761fea864196a290f799) +[ minor conflict fix due to indentation change ] +Signed-off-by: Marc-André Lureau +Signed-off-by: Miroslav Rezanina +--- + slirp/src/bootp.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/slirp/src/bootp.c b/slirp/src/bootp.c +index 5789187166..3e4af075f1 100644 +--- a/slirp/src/bootp.c ++++ b/slirp/src/bootp.c +@@ -354,14 +354,14 @@ static void bootp_reply(Slirp *slirp, + q += sizeof(nak_msg) - 1; + } + assert(q < end); +- *q = +-RFC1533_END +-; ++ *q = RFC1533_END; + +-daddr.sin_addr.s_addr = 0xffffffffu; ++ daddr.sin_addr.s_addr = 0xffffffffu; + +-m->m_len = sizeof(struct bootp_t) - sizeof(struct ip) - sizeof(struct udphdr); +-udp_output(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); ++ assert ((q - rbp->bp_vend + 1) <= DHCP_OPT_LEN); ++ ++ m->m_len = sizeof(struct bootp_t) + (q - rbp->bp_vend + 1) - sizeof(struct ip) - sizeof(struct udphdr); ++ udp_output(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); + } + + void bootp_input(struct mbuf *m) +-- +2.27.0 + diff --git a/SOURCES/kvm-acpi-accept-byte-and-word-access-to-core-ACPI-regist.patch b/SOURCES/kvm-acpi-accept-byte-and-word-access-to-core-ACPI-regist.patch new file mode 100644 index 0000000..1538d11 --- /dev/null +++ b/SOURCES/kvm-acpi-accept-byte-and-word-access-to-core-ACPI-regist.patch @@ -0,0 +1,82 @@ +From dcac680adb6b8624f14eda3e812521bddbe8ecea Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 21 Apr 2021 22:30:04 -0400 +Subject: [PATCH 5/7] acpi: accept byte and word access to core ACPI registers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +Message-id: <20210421223006.19650-5-jmaloy@redhat.com> +Patchwork-id: 101482 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH v2 4/6] acpi: accept byte and word access to core ACPI registers +Bugzilla: 1842478 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laszlo Ersek + +From: Michael Tokarev + +All ISA registers should be accessible as bytes, words or dwords +(if wide enough). Fix the access constraints for acpi-pm-evt, +acpi-pm-tmr & acpi-cnt registers. + +Fixes: 5d971f9e67 (memory: Revert "memory: accept mismatching sizes in memory_region_access_valid") +Fixes: afafe4bbe0 (apci: switch cnt to memory api) +Fixes: 77d58b1e47 (apci: switch timer to memory api) +Fixes: b5a7c024d2 (apci: switch evt to memory api) +Buglink: https://lore.kernel.org/xen-devel/20200630170913.123646-1-anthony.perard@citrix.com/T/ +Buglink: https://bugs.debian.org/964793 +BugLink: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=964247 +BugLink: https://bugs.launchpad.net/bugs/1886318 +Reported-By: Simon John +Signed-off-by: Michael Tokarev +Message-Id: <20200720160627.15491-1-mjt@msgid.tls.msk.ru> +Cc: qemu-stable@nongnu.org +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin + +(cherry picked from commit dba04c3488c4699f5afe96f66e448b1d447cf3fb) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + hw/acpi/core.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/hw/acpi/core.c b/hw/acpi/core.c +index 45cbed49ab..d85052c34a 100644 +--- a/hw/acpi/core.c ++++ b/hw/acpi/core.c +@@ -461,7 +461,8 @@ static void acpi_pm_evt_write(void *opaque, hwaddr addr, uint64_t val, + static const MemoryRegionOps acpi_pm_evt_ops = { + .read = acpi_pm_evt_read, + .write = acpi_pm_evt_write, +- .valid.min_access_size = 2, ++ .impl.min_access_size = 2, ++ .valid.min_access_size = 1, + .valid.max_access_size = 2, + .endianness = DEVICE_LITTLE_ENDIAN, + }; +@@ -530,7 +531,8 @@ static void acpi_pm_tmr_write(void *opaque, hwaddr addr, uint64_t val, + static const MemoryRegionOps acpi_pm_tmr_ops = { + .read = acpi_pm_tmr_read, + .write = acpi_pm_tmr_write, +- .valid.min_access_size = 4, ++ .impl.min_access_size = 4, ++ .valid.min_access_size = 1, + .valid.max_access_size = 4, + .endianness = DEVICE_LITTLE_ENDIAN, + }; +@@ -602,7 +604,8 @@ static void acpi_pm_cnt_write(void *opaque, hwaddr addr, uint64_t val, + static const MemoryRegionOps acpi_pm_cnt_ops = { + .read = acpi_pm_cnt_read, + .write = acpi_pm_cnt_write, +- .valid.min_access_size = 2, ++ .impl.min_access_size = 2, ++ .valid.min_access_size = 1, + .valid.max_access_size = 2, + .endianness = DEVICE_LITTLE_ENDIAN, + }; +-- +2.27.0 + diff --git a/SOURCES/kvm-aio-wait-delegate-polling-of-main-AioContext-if-BQL-.patch b/SOURCES/kvm-aio-wait-delegate-polling-of-main-AioContext-if-BQL-.patch new file mode 100644 index 0000000..a234140 --- /dev/null +++ b/SOURCES/kvm-aio-wait-delegate-polling-of-main-AioContext-if-BQL-.patch @@ -0,0 +1,132 @@ +From b474155fdc38f86f516c14ba9a6f934616d589ef Mon Sep 17 00:00:00 2001 +From: Andrew Jones +Date: Wed, 4 Aug 2021 03:27:22 -0400 +Subject: [PATCH 1/2] aio-wait: delegate polling of main AioContext if BQL not + held + +RH-Author: Andrew Jones +Message-id: <20210729134448.4995-2-drjones@redhat.com> +Patchwork-id: 101935 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH v2 1/2] aio-wait: delegate polling of main AioContext if BQL not held +Bugzilla: 1969848 +RH-Acked-by: Gavin Shan +RH-Acked-by: Auger Eric +RH-Acked-by: Stefan Hajnoczi + +From: Paolo Bonzini + +Any thread that is not a iothread returns NULL for qemu_get_current_aio_context(). +As a result, it would also return true for +in_aio_context_home_thread(qemu_get_aio_context()), causing +AIO_WAIT_WHILE to invoke aio_poll() directly. This is incorrect +if the BQL is not held, because aio_poll() does not expect to +run concurrently from multiple threads, and it can actually +happen when savevm writes to the vmstate file from the +migration thread. + +Therefore, restrict in_aio_context_home_thread to return true +for the main AioContext only if the BQL is held. + +The function is moved to aio-wait.h because it is mostly used +there and to avoid a circular reference between main-loop.h +and block/aio.h. + +Signed-off-by: Paolo Bonzini +Message-Id: <20200407140746.8041-5-pbonzini@redhat.com> +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 3c18a92dc4b55ca8cc37a755ed119f11c0f34099) +Signed-off-by: Andrew Jones +Signed-off-by: Miroslav Rezanina +--- + include/block/aio-wait.h | 22 ++++++++++++++++++++++ + include/block/aio.h | 29 ++++++++++------------------- + 2 files changed, 32 insertions(+), 19 deletions(-) + +diff --git a/include/block/aio-wait.h b/include/block/aio-wait.h +index afeeb18f95..716d2639df 100644 +--- a/include/block/aio-wait.h ++++ b/include/block/aio-wait.h +@@ -26,6 +26,7 @@ + #define QEMU_AIO_WAIT_H + + #include "block/aio.h" ++#include "qemu/main-loop.h" + + /** + * AioWait: +@@ -124,4 +125,25 @@ void aio_wait_kick(void); + */ + void aio_wait_bh_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque); + ++/** ++ * in_aio_context_home_thread: ++ * @ctx: the aio context ++ * ++ * Return whether we are running in the thread that normally runs @ctx. Note ++ * that acquiring/releasing ctx does not affect the outcome, each AioContext ++ * still only has one home thread that is responsible for running it. ++ */ ++static inline bool in_aio_context_home_thread(AioContext *ctx) ++{ ++ if (ctx == qemu_get_current_aio_context()) { ++ return true; ++ } ++ ++ if (ctx == qemu_get_aio_context()) { ++ return qemu_mutex_iothread_locked(); ++ } else { ++ return false; ++ } ++} ++ + #endif /* QEMU_AIO_WAIT_H */ +diff --git a/include/block/aio.h b/include/block/aio.h +index 6b0d52f732..9d28e247df 100644 +--- a/include/block/aio.h ++++ b/include/block/aio.h +@@ -60,12 +60,16 @@ struct AioContext { + QLIST_HEAD(, AioHandler) aio_handlers; + + /* Used to avoid unnecessary event_notifier_set calls in aio_notify; +- * accessed with atomic primitives. If this field is 0, everything +- * (file descriptors, bottom halves, timers) will be re-evaluated +- * before the next blocking poll(), thus the event_notifier_set call +- * can be skipped. If it is non-zero, you may need to wake up a +- * concurrent aio_poll or the glib main event loop, making +- * event_notifier_set necessary. ++ * only written from the AioContext home thread, or under the BQL in ++ * the case of the main AioContext. However, it is read from any ++ * thread so it is still accessed with atomic primitives. ++ * ++ * If this field is 0, everything (file descriptors, bottom halves, ++ * timers) will be re-evaluated before the next blocking poll() or ++ * io_uring wait; therefore, the event_notifier_set call can be ++ * skipped. If it is non-zero, you may need to wake up a concurrent ++ * aio_poll or the glib main event loop, making event_notifier_set ++ * necessary. + * + * Bit 0 is reserved for GSource usage of the AioContext, and is 1 + * between a call to aio_ctx_prepare and the next call to aio_ctx_check. +@@ -580,19 +584,6 @@ void aio_co_enter(AioContext *ctx, struct Coroutine *co); + */ + AioContext *qemu_get_current_aio_context(void); + +-/** +- * in_aio_context_home_thread: +- * @ctx: the aio context +- * +- * Return whether we are running in the thread that normally runs @ctx. Note +- * that acquiring/releasing ctx does not affect the outcome, each AioContext +- * still only has one home thread that is responsible for running it. +- */ +-static inline bool in_aio_context_home_thread(AioContext *ctx) +-{ +- return ctx == qemu_get_current_aio_context(); +-} +- + /** + * aio_context_setup: + * @ctx: the aio context +-- +2.27.0 + diff --git a/SOURCES/kvm-async-use-explicit-memory-barriers.patch b/SOURCES/kvm-async-use-explicit-memory-barriers.patch new file mode 100644 index 0000000..2bf7245 --- /dev/null +++ b/SOURCES/kvm-async-use-explicit-memory-barriers.patch @@ -0,0 +1,183 @@ +From 82a02aec3a8b3c2ac925d0b71ea4c35aa5d6463b Mon Sep 17 00:00:00 2001 +From: Andrew Jones +Date: Wed, 4 Aug 2021 03:27:24 -0400 +Subject: [PATCH 2/2] async: use explicit memory barriers + +RH-Author: Andrew Jones +Message-id: <20210729134448.4995-3-drjones@redhat.com> +Patchwork-id: 101937 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH v2 2/2] async: use explicit memory barriers +Bugzilla: 1969848 +RH-Acked-by: Gavin Shan +RH-Acked-by: Auger Eric +RH-Acked-by: Stefan Hajnoczi + +From: Paolo Bonzini + +When using C11 atomics, non-seqcst reads and writes do not participate +in the total order of seqcst operations. In util/async.c and util/aio-posix.c, +in particular, the pattern that we use + + write ctx->notify_me write bh->scheduled + read bh->scheduled read ctx->notify_me + if !bh->scheduled, sleep if ctx->notify_me, notify + +needs to use seqcst operations for both the write and the read. In +general this is something that we do not want, because there can be +many sources that are polled in addition to bottom halves. The +alternative is to place a seqcst memory barrier between the write +and the read. This also comes with a disadvantage, in that the +memory barrier is implicit on strongly-ordered architectures and +it wastes a few dozen clock cycles. + +Fortunately, ctx->notify_me is never written concurrently by two +threads, so we can assert that and relax the writes to ctx->notify_me. +The resulting solution works and performs well on both aarch64 and x86. + +Note that the atomic_set/atomic_read combination is not an atomic +read-modify-write, and therefore it is even weaker than C11 ATOMIC_RELAXED; +on x86, ATOMIC_RELAXED compiles to a locked operation. + +Analyzed-by: Ying Fang +Signed-off-by: Paolo Bonzini +Tested-by: Ying Fang +Message-Id: <20200407140746.8041-6-pbonzini@redhat.com> +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 5710a3e09f9b85801e5ce70797a4a511e5fc9e2c) +Signed-off-by: Andrew Jones +Signed-off-by: Miroslav Rezanina +--- + util/aio-posix.c | 16 ++++++++++++++-- + util/aio-win32.c | 17 ++++++++++++++--- + util/async.c | 16 ++++++++++++---- + 3 files changed, 40 insertions(+), 9 deletions(-) + +diff --git a/util/aio-posix.c b/util/aio-posix.c +index abc396d030..8cfb25650d 100644 +--- a/util/aio-posix.c ++++ b/util/aio-posix.c +@@ -624,6 +624,11 @@ bool aio_poll(AioContext *ctx, bool blocking) + int64_t timeout; + int64_t start = 0; + ++ /* ++ * There cannot be two concurrent aio_poll calls for the same AioContext (or ++ * an aio_poll concurrent with a GSource prepare/check/dispatch callback). ++ * We rely on this below to avoid slow locked accesses to ctx->notify_me. ++ */ + assert(in_aio_context_home_thread(ctx)); + + /* aio_notify can avoid the expensive event_notifier_set if +@@ -634,7 +639,13 @@ bool aio_poll(AioContext *ctx, bool blocking) + * so disable the optimization now. + */ + if (blocking) { +- atomic_add(&ctx->notify_me, 2); ++ atomic_set(&ctx->notify_me, atomic_read(&ctx->notify_me) + 2); ++ /* ++ * Write ctx->notify_me before computing the timeout ++ * (reading bottom half flags, etc.). Pairs with ++ * smp_mb in aio_notify(). ++ */ ++ smp_mb(); + } + + qemu_lockcnt_inc(&ctx->list_lock); +@@ -679,7 +690,8 @@ bool aio_poll(AioContext *ctx, bool blocking) + } + + if (blocking) { +- atomic_sub(&ctx->notify_me, 2); ++ /* Finish the poll before clearing the flag. */ ++ atomic_store_release(&ctx->notify_me, atomic_read(&ctx->notify_me) - 2); + aio_notify_accept(ctx); + } + +diff --git a/util/aio-win32.c b/util/aio-win32.c +index a23b9c364d..729d533faf 100644 +--- a/util/aio-win32.c ++++ b/util/aio-win32.c +@@ -321,6 +321,12 @@ bool aio_poll(AioContext *ctx, bool blocking) + int count; + int timeout; + ++ /* ++ * There cannot be two concurrent aio_poll calls for the same AioContext (or ++ * an aio_poll concurrent with a GSource prepare/check/dispatch callback). ++ * We rely on this below to avoid slow locked accesses to ctx->notify_me. ++ */ ++ assert(in_aio_context_home_thread(ctx)); + progress = false; + + /* aio_notify can avoid the expensive event_notifier_set if +@@ -331,7 +337,13 @@ bool aio_poll(AioContext *ctx, bool blocking) + * so disable the optimization now. + */ + if (blocking) { +- atomic_add(&ctx->notify_me, 2); ++ atomic_set(&ctx->notify_me, atomic_read(&ctx->notify_me) + 2); ++ /* ++ * Write ctx->notify_me before computing the timeout ++ * (reading bottom half flags, etc.). Pairs with ++ * smp_mb in aio_notify(). ++ */ ++ smp_mb(); + } + + qemu_lockcnt_inc(&ctx->list_lock); +@@ -364,8 +376,7 @@ bool aio_poll(AioContext *ctx, bool blocking) + ret = WaitForMultipleObjects(count, events, FALSE, timeout); + if (blocking) { + assert(first); +- assert(in_aio_context_home_thread(ctx)); +- atomic_sub(&ctx->notify_me, 2); ++ atomic_store_release(&ctx->notify_me, atomic_read(&ctx->notify_me) - 2); + aio_notify_accept(ctx); + } + +diff --git a/util/async.c b/util/async.c +index b1fa5319e5..c65c58bbc9 100644 +--- a/util/async.c ++++ b/util/async.c +@@ -220,7 +220,14 @@ aio_ctx_prepare(GSource *source, gint *timeout) + { + AioContext *ctx = (AioContext *) source; + +- atomic_or(&ctx->notify_me, 1); ++ atomic_set(&ctx->notify_me, atomic_read(&ctx->notify_me) | 1); ++ ++ /* ++ * Write ctx->notify_me before computing the timeout ++ * (reading bottom half flags, etc.). Pairs with ++ * smp_mb in aio_notify(). ++ */ ++ smp_mb(); + + /* We assume there is no timeout already supplied */ + *timeout = qemu_timeout_ns_to_ms(aio_compute_timeout(ctx)); +@@ -238,7 +245,8 @@ aio_ctx_check(GSource *source) + AioContext *ctx = (AioContext *) source; + QEMUBH *bh; + +- atomic_and(&ctx->notify_me, ~1); ++ /* Finish computing the timeout before clearing the flag. */ ++ atomic_store_release(&ctx->notify_me, atomic_read(&ctx->notify_me) & ~1); + aio_notify_accept(ctx); + + for (bh = ctx->first_bh; bh; bh = bh->next) { +@@ -343,10 +351,10 @@ LinuxAioState *aio_get_linux_aio(AioContext *ctx) + void aio_notify(AioContext *ctx) + { + /* Write e.g. bh->scheduled before reading ctx->notify_me. Pairs +- * with atomic_or in aio_ctx_prepare or atomic_add in aio_poll. ++ * with smp_mb in aio_ctx_prepare or aio_poll. + */ + smp_mb(); +- if (ctx->notify_me) { ++ if (atomic_read(&ctx->notify_me)) { + event_notifier_set(&ctx->notifier); + atomic_mb_set(&ctx->notified, true); + } +-- +2.27.0 + diff --git a/SOURCES/kvm-audio-audio_generic_get_buffer_in-should-honor-size.patch b/SOURCES/kvm-audio-audio_generic_get_buffer_in-should-honor-size.patch new file mode 100644 index 0000000..1a20688 --- /dev/null +++ b/SOURCES/kvm-audio-audio_generic_get_buffer_in-should-honor-size.patch @@ -0,0 +1,53 @@ +From 96c8fcafa7325cd0e8a23a743a55f0ad0aa9f79b Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Thu, 18 Mar 2021 09:13:42 -0400 +Subject: [PATCH 5/5] audio: audio_generic_get_buffer_in should honor *size +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Gerd Hoffmann +Message-id: <20210318091342.3232471-2-kraxel@redhat.com> +Patchwork-id: 101352 +O-Subject: [RHEL-8.4.0 qemu-kvm PATCH 1/1] audio: audio_generic_get_buffer_in should honor *size +Bugzilla: 1932823 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Danilo de Paula +RH-Acked-by: Philippe Mathieu-Daudé + +From: Volker Rümelin + +The function generic_get_buffer_in currently ignores the *size +parameter and may return a buffer larger than *size. + +As a result the variable samples in function +audio_pcm_hw_run_in may underflow. The while loop then most +likely will never termiate. + +Buglink: http://bugs.debian.org/948658 +Signed-off-by: Volker Rümelin +Message-Id: <20200123074943.6699-9-vr_qemu@t-online.de> +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 599eac4e5a41e828645594097daee39373acc3c0) +Signed-off-by: Danilo C. L. de Paula +--- + audio/audio.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/audio/audio.c b/audio/audio.c +index 56fae55047..39a62fc62a 100644 +--- a/audio/audio.c ++++ b/audio/audio.c +@@ -1402,7 +1402,8 @@ void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size) + } + assert(start >= 0 && start < hw->size_emul); + +- *size = MIN(hw->pending_emul, hw->size_emul - start); ++ *size = MIN(*size, hw->pending_emul); ++ *size = MIN(*size, hw->size_emul - start); + return hw->buf_emul + start; + } + +-- +2.27.0 + diff --git a/SOURCES/kvm-block-file-posix-Fix-problem-with-fallocate-PUNCH_HO.patch b/SOURCES/kvm-block-file-posix-Fix-problem-with-fallocate-PUNCH_HO.patch new file mode 100644 index 0000000..60b1b0a --- /dev/null +++ b/SOURCES/kvm-block-file-posix-Fix-problem-with-fallocate-PUNCH_HO.patch @@ -0,0 +1,76 @@ +From 8c339c3535728179acc94deb5b922aebcfac9ab6 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Thu, 3 Jun 2021 16:13:34 -0400 +Subject: [PATCH 2/4] block/file-posix: Fix problem with fallocate(PUNCH_HOLE) + on GPFS + +RH-Author: Thomas Huth +Message-id: <20210603161334.607005-2-thuth@redhat.com> +Patchwork-id: 101673 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 1/1] block/file-posix: Fix problem with fallocate(PUNCH_HOLE) on GPFS +Bugzilla: 1944861 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Max Reitz +RH-Acked-by: Cornelia Huck +RH-Acked-by: Laszlo Ersek + +A customer reported that running + + qemu-img convert -t none -O qcow2 -f qcow2 input.qcow2 output.qcow2 + +fails for them with the following error message when the images are +stored on a GPFS file system : + + qemu-img: error while writing sector 0: Invalid argument + +After analyzing the strace output, it seems like the problem is in +handle_aiocb_write_zeroes(): The call to fallocate(FALLOC_FL_PUNCH_HOLE) +returns EINVAL, which can apparently happen if the file system has +a different idea of the granularity of the operation. It's arguably +a bug in GPFS, since the PUNCH_HOLE mode should not result in EINVAL +according to the man-page of fallocate(), but the file system is out +there in production and so we have to deal with it. In commit 294682cc3a +("block: workaround for unaligned byte range in fallocate()") we also +already applied the a work-around for the same problem to the earlier +fallocate(FALLOC_FL_ZERO_RANGE) call, so do it now similar with the +PUNCH_HOLE call. But instead of silently catching and returning +-ENOTSUP (which causes the caller to fall back to writing zeroes), +let's rather inform the user once about the buggy file system and +try the other fallback instead. + +Signed-off-by: Thomas Huth +Message-Id: <20210527172020.847617-2-thuth@redhat.com> +Signed-off-by: Kevin Wolf +(cherry picked from commit 73ebf29729d1a40feaa9f8ab8951b6ee6dbfbede) +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1944861 +Signed-off-by: Thomas Huth +Signed-off-by: Danilo C. L. de Paula +--- + block/file-posix.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/block/file-posix.c b/block/file-posix.c +index 62a463229f..371572f1b0 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -1587,6 +1587,17 @@ static int handle_aiocb_write_zeroes(void *opaque) + return ret; + } + s->has_fallocate = false; ++ } else if (ret == -EINVAL) { ++ /* ++ * Some file systems like older versions of GPFS do not like un- ++ * aligned byte ranges, and return EINVAL in such a case, though ++ * they should not do it according to the man-page of fallocate(). ++ * Warn about the bad filesystem and try the final fallback instead. ++ */ ++ warn_report_once("Your file system is misbehaving: " ++ "fallocate(FALLOC_FL_PUNCH_HOLE) returned EINVAL. " ++ "Please report this bug to your file sytem " ++ "vendor."); + } else if (ret != -ENOTSUP) { + return ret; + } else { +-- +2.27.0 + diff --git a/SOURCES/kvm-bootp-check-bootp_input-buffer-size.patch b/SOURCES/kvm-bootp-check-bootp_input-buffer-size.patch new file mode 100644 index 0000000..3362cb0 --- /dev/null +++ b/SOURCES/kvm-bootp-check-bootp_input-buffer-size.patch @@ -0,0 +1,52 @@ +From a66ab346bf74ebf3ed8fca0dc2e2febfe70069e8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Thu, 29 Jul 2021 04:56:28 -0400 +Subject: [PATCH 07/14] bootp: check bootp_input buffer size +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Marc-André Lureau +Message-id: <20210708082537.1550263-4-marcandre.lureau@redhat.com> +Patchwork-id: 101820 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 3/8] bootp: check bootp_input buffer size +Bugzilla: 1970819 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Eric Blake +RH-Acked-by: Stefan Hajnoczi + +From: Marc-André Lureau + +Fixes: CVE-2021-3592 +Fixes: https://gitlab.freedesktop.org/slirp/libslirp/-/issues/44 + +Signed-off-by: Marc-André Lureau + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1970819 + +(cherry picked from commit 2eca0838eee1da96204545e22cdaed860d9d7c6c) +Signed-off-by: Marc-André Lureau +Signed-off-by: Miroslav Rezanina +--- + slirp/src/bootp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/slirp/src/bootp.c b/slirp/src/bootp.c +index 5754327138..5789187166 100644 +--- a/slirp/src/bootp.c ++++ b/slirp/src/bootp.c +@@ -366,9 +366,9 @@ udp_output(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); + + void bootp_input(struct mbuf *m) + { +- struct bootp_t *bp = mtod(m, struct bootp_t *); ++ struct bootp_t *bp = mtod_check(m, sizeof(struct bootp_t)); + +- if (bp->bp_op == BOOTP_REQUEST) { ++ if (bp && bp->bp_op == BOOTP_REQUEST) { + bootp_reply(m->slirp, bp, m_end(m)); + } + } +-- +2.27.0 + diff --git a/SOURCES/kvm-bootp-limit-vendor-specific-area-to-input-packet-mem.patch b/SOURCES/kvm-bootp-limit-vendor-specific-area-to-input-packet-mem.patch new file mode 100644 index 0000000..bbf9b03 --- /dev/null +++ b/SOURCES/kvm-bootp-limit-vendor-specific-area-to-input-packet-mem.patch @@ -0,0 +1,175 @@ +From 8198ae7c21a4d37f7e365058f973867c41d44d21 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Thu, 29 Jul 2021 04:56:25 -0400 +Subject: [PATCH 06/14] bootp: limit vendor-specific area to input packet + memory buffer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Marc-André Lureau +Message-id: <20210708082537.1550263-3-marcandre.lureau@redhat.com> +Patchwork-id: 101821 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 2/8] bootp: limit vendor-specific area to input packet memory buffer +Bugzilla: 1970819 1970835 1970843 1970853 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Eric Blake +RH-Acked-by: Stefan Hajnoczi + +From: Marc-André Lureau + +sizeof(bootp_t) currently holds DHCP_OPT_LEN. Remove this optional field +from the structure, to help with the following patch checking for +minimal header size. Modify the bootp_reply() function to take the +buffer boundaries and avoiding potential buffer overflow. + +Related to CVE-2021-3592. + +https://gitlab.freedesktop.org/slirp/libslirp/-/issues/44 + +Signed-off-by: Marc-André Lureau + +(cherry picked from commit f13cad45b25d92760bb0ad67bec0300a4d7d5275) +Signed-off-by: Marc-André Lureau +Signed-off-by: Miroslav Rezanina +--- + slirp/src/bootp.c | 26 +++++++++++++++----------- + slirp/src/bootp.h | 2 +- + slirp/src/mbuf.c | 5 +++++ + slirp/src/mbuf.h | 1 + + 4 files changed, 22 insertions(+), 12 deletions(-) + +diff --git a/slirp/src/bootp.c b/slirp/src/bootp.c +index 3f9ce2553e..5754327138 100644 +--- a/slirp/src/bootp.c ++++ b/slirp/src/bootp.c +@@ -92,21 +92,22 @@ found: + return bc; + } + +-static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type, ++static void dhcp_decode(const struct bootp_t *bp, ++ const uint8_t *bp_end, ++ int *pmsg_type, + struct in_addr *preq_addr) + { +- const uint8_t *p, *p_end; ++ const uint8_t *p; + int len, tag; + + *pmsg_type = 0; + preq_addr->s_addr = htonl(0L); + + p = bp->bp_vend; +- p_end = p + DHCP_OPT_LEN; + if (memcmp(p, rfc1533_cookie, 4) != 0) + return; + p += 4; +- while (p < p_end) { ++ while (p < bp_end) { + tag = p[0]; + if (tag == RFC1533_PAD) { + p++; +@@ -114,10 +115,10 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type, + break; + } else { + p++; +- if (p >= p_end) ++ if (p >= bp_end) + break; + len = *p++; +- if (p + len > p_end) { ++ if (p + len > bp_end) { + break; + } + DPRINTF("dhcp: tag=%d len=%d\n", tag, len); +@@ -144,7 +145,9 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type, + } + } + +-static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) ++static void bootp_reply(Slirp *slirp, ++ const struct bootp_t *bp, ++ const uint8_t *bp_end) + { + BOOTPClient *bc = NULL; + struct mbuf *m; +@@ -157,7 +160,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) + uint8_t client_ethaddr[ETH_ALEN]; + + /* extract exact DHCP msg type */ +- dhcp_decode(bp, &dhcp_msg_type, &preq_addr); ++ dhcp_decode(bp, bp_end, &dhcp_msg_type, &preq_addr); + DPRINTF("bootp packet op=%d msgtype=%d", bp->bp_op, dhcp_msg_type); + if (preq_addr.s_addr != htonl(0L)) + DPRINTF(" req_addr=%08" PRIx32 "\n", ntohl(preq_addr.s_addr)); +@@ -179,9 +182,10 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) + return; + } + m->m_data += IF_MAXLINKHDR; ++ m_inc(m, sizeof(struct bootp_t) + DHCP_OPT_LEN); + rbp = (struct bootp_t *)m->m_data; + m->m_data += sizeof(struct udpiphdr); +- memset(rbp, 0, sizeof(struct bootp_t)); ++ memset(rbp, 0, sizeof(struct bootp_t) + DHCP_OPT_LEN); + + if (dhcp_msg_type == DHCPDISCOVER) { + if (preq_addr.s_addr != htonl(0L)) { +@@ -235,7 +239,7 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp) + rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */ + + q = rbp->bp_vend; +- end = (uint8_t *)&rbp[1]; ++ end = rbp->bp_vend + DHCP_OPT_LEN; + memcpy(q, rfc1533_cookie, 4); + q += 4; + +@@ -365,6 +369,6 @@ void bootp_input(struct mbuf *m) + struct bootp_t *bp = mtod(m, struct bootp_t *); + + if (bp->bp_op == BOOTP_REQUEST) { +- bootp_reply(m->slirp, bp); ++ bootp_reply(m->slirp, bp, m_end(m)); + } + } +diff --git a/slirp/src/bootp.h b/slirp/src/bootp.h +index 03ece9bf28..0d20a944a8 100644 +--- a/slirp/src/bootp.h ++++ b/slirp/src/bootp.h +@@ -114,7 +114,7 @@ struct bootp_t { + uint8_t bp_hwaddr[16]; + uint8_t bp_sname[64]; + uint8_t bp_file[128]; +- uint8_t bp_vend[DHCP_OPT_LEN]; ++ uint8_t bp_vend[]; + }; + + typedef struct { +diff --git a/slirp/src/mbuf.c b/slirp/src/mbuf.c +index 6d0653ed3d..7db07c088e 100644 +--- a/slirp/src/mbuf.c ++++ b/slirp/src/mbuf.c +@@ -233,3 +233,8 @@ void *mtod_check(struct mbuf *m, size_t len) + + return NULL; + } ++ ++void *m_end(struct mbuf *m) ++{ ++ return m->m_data + m->m_len; ++} +diff --git a/slirp/src/mbuf.h b/slirp/src/mbuf.h +index 2015e3232f..a9752a36e0 100644 +--- a/slirp/src/mbuf.h ++++ b/slirp/src/mbuf.h +@@ -119,6 +119,7 @@ void m_adj(struct mbuf *, int); + int m_copy(struct mbuf *, struct mbuf *, int, int); + struct mbuf *dtom(Slirp *, void *); + void *mtod_check(struct mbuf *, size_t len); ++void *m_end(struct mbuf *); + + static inline void ifs_init(struct mbuf *ifm) + { +-- +2.27.0 + diff --git a/SOURCES/kvm-cadence_gem-switch-to-use-qemu_receive_packet-for-lo.patch b/SOURCES/kvm-cadence_gem-switch-to-use-qemu_receive_packet-for-lo.patch new file mode 100644 index 0000000..32d5377 --- /dev/null +++ b/SOURCES/kvm-cadence_gem-switch-to-use-qemu_receive_packet-for-lo.patch @@ -0,0 +1,60 @@ +From 6f1ebcfdb92d12ef2caae0b63a3a380265cba1fa Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 29 Jun 2021 03:42:46 -0400 +Subject: [PATCH 8/9] 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 + +RH-Author: Jon Maloy +Message-id: <20210629034247.3286477-9-jmaloy@redhat.com> +Patchwork-id: 101793 +O-Subject: [RHEL-8.4.0.z qemu-kvm PATCH v2 8/9] cadence_gem: switch to use qemu_receive_packet() for loopback +Bugzilla: 1932917 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth + +From: Alexander Bulekov + +This patch switches to use qemu_receive_packet() which can detect +reentrancy and return early. + +This is intended to address CVE-2021-3416. + +Cc: Prasad J Pandit +Cc: qemu-stable@nongnu.org +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Alexander Bulekov +Signed-off-by: Jason Wang + +(cherry picked from commit e73adfbeec9d4e008630c814759052ed945c3fed) +Conflict: upstream commit 24d62fd5028e ("net: cadence_gem: Move tx/rx +packet buffert to CadenceGEMState") is missing in this version, so +we stick to using the original stack variable tx_packet in the calls. + +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + 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 b8be73dc55..be7c91123b 100644 +--- a/hw/net/cadence_gem.c ++++ b/hw/net/cadence_gem.c +@@ -1225,8 +1225,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), tx_packet, +- total_bytes); ++ qemu_receive_packet(qemu_get_queue(s->nic), tx_packet, ++ total_bytes); + } else { + qemu_send_packet(qemu_get_queue(s->nic), tx_packet, + total_bytes); +-- +2.27.0 + diff --git a/SOURCES/kvm-dp8393x-switch-to-use-qemu_receive_packet-for-loopba.patch b/SOURCES/kvm-dp8393x-switch-to-use-qemu_receive_packet-for-loopba.patch new file mode 100644 index 0000000..77e99eb --- /dev/null +++ b/SOURCES/kvm-dp8393x-switch-to-use-qemu_receive_packet-for-loopba.patch @@ -0,0 +1,53 @@ +From a6f0bef82cdd84844a06dac1e6d279d95824d827 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 29 Jun 2021 03:42:41 -0400 +Subject: [PATCH 3/9] 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 + +RH-Author: Jon Maloy +Message-id: <20210629034247.3286477-4-jmaloy@redhat.com> +Patchwork-id: 101789 +O-Subject: [RHEL-8.4.0.z qemu-kvm PATCH v2 3/9] dp8393x: switch to use qemu_receive_packet() for loopback packet +Bugzilla: 1932917 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth + +From: Jason Wang + +This patch switches to use qemu_receive_packet() which can detect +reentrancy and return early. + +This is intended to address CVE-2021-3416. + +Cc: Prasad J Pandit +Cc: qemu-stable@nongnu.org +Reviewed-by: Philippe Mathieu-Daudé + +(cherry picked from commit 331d2ac9ea307c990dc86e6493e8f0c48d14bb33) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + 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 3d991af163..6d55b5de64 100644 +--- a/hw/net/dp8393x.c ++++ b/hw/net/dp8393x.c +@@ -482,7 +482,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 */ +-- +2.27.0 + diff --git a/SOURCES/kvm-e1000-fail-early-for-evil-descriptor.patch b/SOURCES/kvm-e1000-fail-early-for-evil-descriptor.patch new file mode 100644 index 0000000..e599b7c --- /dev/null +++ b/SOURCES/kvm-e1000-fail-early-for-evil-descriptor.patch @@ -0,0 +1,65 @@ +From 7bd3000cf22a91e6bc6afc1e7adbf0ae1b731104 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 13 Apr 2021 22:45:17 -0400 +Subject: [PATCH 2/5] e1000: fail early for evil descriptor + +RH-Author: Jon Maloy +Message-id: <20210413224517.3841507-2-jmaloy@redhat.com> +Patchwork-id: 101473 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 1/1] e1000: fail early for evil descriptor +Bugzilla: 1930092 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Stefan Hajnoczi + +From: Jason Wang + +During procss_tx_desc(), driver can try to chain data descriptor with +legacy descriptor, when will lead underflow for the following +calculation in process_tx_desc() for bytes: + + if (tp->size + bytes > msh) + bytes = msh - tp->size; + +This will lead a infinite loop. So check and fail early if tp->size if +greater or equal to msh. + +Reported-by: Alexander Bulekov +Reported-by: Cheolwoo Myung +Reported-by: Ruhr-University Bochum +Cc: Prasad J Pandit +Cc: qemu-stable@nongnu.org +Signed-off-by: Jason Wang + +(cherry picked from commit 3de46e6fc489c52c9431a8a832ad8170a7569bd8) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + hw/net/e1000.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/hw/net/e1000.c b/hw/net/e1000.c +index fc73fdd6fa..fe56bccd52 100644 +--- a/hw/net/e1000.c ++++ b/hw/net/e1000.c +@@ -671,6 +671,9 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp) + msh = tp->tso_props.hdr_len + tp->tso_props.mss; + do { + bytes = split_size; ++ if (tp->size >= msh) { ++ goto eop; ++ } + if (tp->size + bytes > msh) + bytes = msh - tp->size; + +@@ -696,6 +699,7 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp) + tp->size += split_size; + } + ++eop: + if (!(txd_lower & E1000_TXD_CMD_EOP)) + return; + if (!(tp->cptse && tp->size < tp->tso_props.hdr_len)) { +-- +2.27.0 + diff --git a/SOURCES/kvm-e1000-switch-to-use-qemu_receive_packet-for-loopback.patch b/SOURCES/kvm-e1000-switch-to-use-qemu_receive_packet-for-loopback.patch new file mode 100644 index 0000000..05ff372 --- /dev/null +++ b/SOURCES/kvm-e1000-switch-to-use-qemu_receive_packet-for-loopback.patch @@ -0,0 +1,52 @@ +From 128b97f6049144af3c1a41ceb8e8583419edcd69 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 29 Jun 2021 03:42:40 -0400 +Subject: [PATCH 2/9] e1000: switch to use qemu_receive_packet() for loopback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +Message-id: <20210629034247.3286477-3-jmaloy@redhat.com> +Patchwork-id: 101784 +O-Subject: [RHEL-8.4.0.z qemu-kvm PATCH v2 2/9] e1000: switch to use qemu_receive_packet() for loopback +Bugzilla: 1932917 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth + +From: Jason Wang + +This patch switches to use qemu_receive_packet() which can detect +reentrancy and return early. + +This is intended to address CVE-2021-3416. + +Cc: Prasad J Pandit +Cc: qemu-stable@nongnu.org +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Jason Wang + +(cherry picked from commit 1caff0340f49c93d535c6558a5138d20d475315c) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + 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 fe56bccd52..8680b7d46b 100644 +--- a/hw/net/e1000.c ++++ b/hw/net/e1000.c +@@ -547,7 +547,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); + } +-- +2.27.0 + diff --git a/SOURCES/kvm-file-posix-Handle-EINVAL-fallocate-return-value.patch b/SOURCES/kvm-file-posix-Handle-EINVAL-fallocate-return-value.patch new file mode 100644 index 0000000..ac7b859 --- /dev/null +++ b/SOURCES/kvm-file-posix-Handle-EINVAL-fallocate-return-value.patch @@ -0,0 +1,59 @@ +From 94d99b13b48e922861570f043490efc966b3b445 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Fri, 25 Jun 2021 17:41:04 -0400 +Subject: [PATCH 4/4] file-posix: Handle `EINVAL` fallocate return value +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Kevin Wolf +Message-id: <20210625174104.44313-3-kwolf@redhat.com> +Patchwork-id: 101778 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 2/2] file-posix: Handle `EINVAL` fallocate return value +Bugzilla: 1970912 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth + +From: Antoine Damhet + +The `detect-zeroes=unmap` option may issue unaligned +`FALLOC_FL_PUNCH_HOLE` requests, raw block devices can (and will) return +`EINVAL`, qemu should then write the zeroes to the blockdev instead of +issuing an `IO_ERROR`. + +The problem can be reprodced like this: + +$ qemu-io -c 'write -P 0 42 1234' --image-opts driver=host_device,filename=/dev/loop0,detect-zeroes=unmap +write failed: Invalid argument + +Signed-off-by: Antoine Damhet +Message-Id: <20200717135603.51180-1-antoine.damhet@blade-group.com> +Signed-off-by: Kevin Wolf +(cherry picked from commit bae127d4dcf6158c5042e2eee9582430839a9967) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block/file-posix.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/block/file-posix.c b/block/file-posix.c +index 837edcf027..6cd19e6c9a 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -1632,7 +1632,11 @@ static int handle_aiocb_write_zeroes_unmap(void *opaque) + #ifdef CONFIG_FALLOCATE_PUNCH_HOLE + int ret = do_fallocate(s->fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, + aiocb->aio_offset, aiocb->aio_nbytes); +- if (ret != -ENOTSUP) { ++ switch (ret) { ++ case -ENOTSUP: ++ case -EINVAL: ++ break; ++ default: + return ret; + } + #endif +-- +2.27.0 + diff --git a/SOURCES/kvm-file-posix-Mitigate-file-fragmentation-with-extent-s.patch b/SOURCES/kvm-file-posix-Mitigate-file-fragmentation-with-extent-s.patch new file mode 100644 index 0000000..e8639f3 --- /dev/null +++ b/SOURCES/kvm-file-posix-Mitigate-file-fragmentation-with-extent-s.patch @@ -0,0 +1,466 @@ +From 7ee01b5ccb7fc660dafaf3fdb1578649d17fbddf Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 26 May 2021 09:05:52 -0400 +Subject: [PATCH 1/4] file-posix: Mitigate file fragmentation with extent size + hints + +RH-Author: Kevin Wolf +Message-id: <20210526090552.155820-2-kwolf@redhat.com> +Patchwork-id: 101638 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 1/1] file-posix: Mitigate file fragmentation with extent size hints +Bugzilla: 1877163 +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz + +Especially when O_DIRECT is used with image files so that the page cache +indirection can't cause a merge of allocating requests, the file will +fragment on the file system layer, with a potentially very small +fragment size (this depends on the requests the guest sent). + +On Linux, fragmentation can be reduced by setting an extent size hint +when creating the file (at least on XFS, it can't be set any more after +the first extent has been allocated), basically giving raw files a +"cluster size" for allocation. + +This adds a create option to set the extent size hint, and changes the +default from not setting a hint to setting it to 1 MB. The main reason +why qcow2 defaults to smaller cluster sizes is that COW becomes more +expensive, which is not an issue with raw files, so we can choose a +larger size. The tradeoff here is only potentially wasted disk space. + +For qcow2 (or other image formats) over file-posix, the advantage should +even be greater because they grow sequentially without leaving holes, so +there won't be wasted space. Setting even larger extent size hints for +such images may make sense. This can be done with the new option, but +let's keep the default conservative for now. + +The effect is very visible with a test that intentionally creates a +badly fragmented file with qemu-img bench (the time difference while +creating the file is already remarkable) and then looks at the number of +extents and the time a simple "qemu-img map" takes. + +Without an extent size hint: + + $ ./qemu-img create -f raw -o extent_size_hint=0 ~/tmp/test.raw 10G + Formatting '/home/kwolf/tmp/test.raw', fmt=raw size=10737418240 extent_size_hint=0 + $ ./qemu-img bench -f raw -t none -n -w ~/tmp/test.raw -c 1000000 -S 8192 -o 0 + Sending 1000000 write requests, 4096 bytes each, 64 in parallel (starting at offset 0, step size 8192) + Run completed in 25.848 seconds. + $ ./qemu-img bench -f raw -t none -n -w ~/tmp/test.raw -c 1000000 -S 8192 -o 4096 + Sending 1000000 write requests, 4096 bytes each, 64 in parallel (starting at offset 4096, step size 8192) + Run completed in 19.616 seconds. + $ filefrag ~/tmp/test.raw + /home/kwolf/tmp/test.raw: 2000000 extents found + $ time ./qemu-img map ~/tmp/test.raw + Offset Length Mapped to File + 0 0x1e8480000 0 /home/kwolf/tmp/test.raw + + real 0m1,279s + user 0m0,043s + sys 0m1,226s + +With the new default extent size hint of 1 MB: + + $ ./qemu-img create -f raw -o extent_size_hint=1M ~/tmp/test.raw 10G + Formatting '/home/kwolf/tmp/test.raw', fmt=raw size=10737418240 extent_size_hint=1048576 + $ ./qemu-img bench -f raw -t none -n -w ~/tmp/test.raw -c 1000000 -S 8192 -o 0 + Sending 1000000 write requests, 4096 bytes each, 64 in parallel (starting at offset 0, step size 8192) + Run completed in 11.833 seconds. + $ ./qemu-img bench -f raw -t none -n -w ~/tmp/test.raw -c 1000000 -S 8192 -o 4096 + Sending 1000000 write requests, 4096 bytes each, 64 in parallel (starting at offset 4096, step size 8192) + Run completed in 10.155 seconds. + $ filefrag ~/tmp/test.raw + /home/kwolf/tmp/test.raw: 178 extents found + $ time ./qemu-img map ~/tmp/test.raw + Offset Length Mapped to File + 0 0x1e8480000 0 /home/kwolf/tmp/test.raw + + real 0m0,061s + user 0m0,040s + sys 0m0,014s + +Signed-off-by: Kevin Wolf +Message-Id: <20200707142329.48303-1-kwolf@redhat.com> +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit ffa244c84a1a30dff69ecc80b0137a2b6d428ecb) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block/file-posix.c | 44 ++++++++++++++++++++++++++++++++ + include/block/block_int.h | 1 + + qapi/block-core.json | 11 +++++--- + tests/qemu-iotests/082.out | 16 ++++++++++++ + tests/qemu-iotests/106 | 7 +++-- + tests/qemu-iotests/175 | 6 ++--- + tests/qemu-iotests/243 | 6 ++--- + tests/qemu-iotests/common.filter | 1 + + 8 files changed, 80 insertions(+), 12 deletions(-) + +diff --git a/block/file-posix.c b/block/file-posix.c +index 2d834fbdf6..62a463229f 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -30,6 +30,7 @@ + #include "block/block_int.h" + #include "qemu/module.h" + #include "qemu/option.h" ++#include "qemu/units.h" + #include "trace.h" + #include "block/thread-pool.h" + #include "qemu/iov.h" +@@ -2289,6 +2290,14 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp) + if (!file_opts->has_preallocation) { + file_opts->preallocation = PREALLOC_MODE_OFF; + } ++ if (!file_opts->has_extent_size_hint) { ++ file_opts->extent_size_hint = 1 * MiB; ++ } ++ if (file_opts->extent_size_hint > UINT32_MAX) { ++ result = -EINVAL; ++ error_setg(errp, "Extent size hint is too large"); ++ goto out; ++ } + + /* Create file */ + fd = qemu_open(file_opts->filename, O_RDWR | O_CREAT | O_BINARY, 0644); +@@ -2346,6 +2355,27 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp) + } + #endif + } ++#ifdef FS_IOC_FSSETXATTR ++ /* ++ * Try to set the extent size hint. Failure is not fatal, and a warning is ++ * only printed if the option was explicitly specified. ++ */ ++ { ++ struct fsxattr attr; ++ result = ioctl(fd, FS_IOC_FSGETXATTR, &attr); ++ if (result == 0) { ++ attr.fsx_xflags |= FS_XFLAG_EXTSIZE; ++ attr.fsx_extsize = file_opts->extent_size_hint; ++ result = ioctl(fd, FS_IOC_FSSETXATTR, &attr); ++ } ++ if (result < 0 && file_opts->has_extent_size_hint && ++ file_opts->extent_size_hint) ++ { ++ warn_report("Failed to set extent size hint: %s", ++ strerror(errno)); ++ } ++ } ++#endif + + /* Resize and potentially preallocate the file to the desired + * final size */ +@@ -2381,6 +2411,8 @@ static int coroutine_fn raw_co_create_opts(BlockDriver *drv, + { + BlockdevCreateOptions options; + int64_t total_size = 0; ++ int64_t extent_size_hint = 0; ++ bool has_extent_size_hint = false; + bool nocow = false; + PreallocMode prealloc; + char *buf = NULL; +@@ -2392,6 +2424,11 @@ static int coroutine_fn raw_co_create_opts(BlockDriver *drv, + /* Read out options */ + total_size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), + BDRV_SECTOR_SIZE); ++ if (qemu_opt_get(opts, BLOCK_OPT_EXTENT_SIZE_HINT)) { ++ has_extent_size_hint = true; ++ extent_size_hint = ++ qemu_opt_get_size_del(opts, BLOCK_OPT_EXTENT_SIZE_HINT, -1); ++ } + nocow = qemu_opt_get_bool(opts, BLOCK_OPT_NOCOW, false); + buf = qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC); + prealloc = qapi_enum_parse(&PreallocMode_lookup, buf, +@@ -2411,6 +2448,8 @@ static int coroutine_fn raw_co_create_opts(BlockDriver *drv, + .preallocation = prealloc, + .has_nocow = true, + .nocow = nocow, ++ .has_extent_size_hint = has_extent_size_hint, ++ .extent_size_hint = extent_size_hint, + }, + }; + return raw_co_create(&options, errp); +@@ -2902,6 +2941,11 @@ static QemuOptsList raw_create_opts = { + #endif + ", full)" + }, ++ { ++ .name = BLOCK_OPT_EXTENT_SIZE_HINT, ++ .type = QEMU_OPT_SIZE, ++ .help = "Extent size hint for the image file, 0 to disable" ++ }, + { /* end of list */ } + } + }; +diff --git a/include/block/block_int.h b/include/block/block_int.h +index 41f13ecbed..4b23da2eb0 100644 +--- a/include/block/block_int.h ++++ b/include/block/block_int.h +@@ -53,6 +53,7 @@ + #define BLOCK_OPT_ADAPTER_TYPE "adapter_type" + #define BLOCK_OPT_REDUNDANCY "redundancy" + #define BLOCK_OPT_NOCOW "nocow" ++#define BLOCK_OPT_EXTENT_SIZE_HINT "extent_size_hint" + #define BLOCK_OPT_OBJECT_SIZE "object_size" + #define BLOCK_OPT_REFCOUNT_BITS "refcount_bits" + #define BLOCK_OPT_DATA_FILE "data_file" +diff --git a/qapi/block-core.json b/qapi/block-core.json +index 289320902d..c7aa919fa3 100644 +--- a/qapi/block-core.json ++++ b/qapi/block-core.json +@@ -4272,14 +4272,17 @@ + # falloc (if defined CONFIG_POSIX_FALLOCATE), + # full (if defined CONFIG_POSIX)) + # @nocow Turn off copy-on-write (valid only on btrfs; default: off) ++# @extent-size-hint: Extent size hint to add to the image file; 0 for not ++# adding an extent size hint (default: 1 MB, since 5.1) + # + # Since: 2.12 + ## + { 'struct': 'BlockdevCreateOptionsFile', +- 'data': { 'filename': 'str', +- 'size': 'size', +- '*preallocation': 'PreallocMode', +- '*nocow': 'bool' } } ++ 'data': { 'filename': 'str', ++ 'size': 'size', ++ '*preallocation': 'PreallocMode', ++ '*nocow': 'bool', ++ '*extent-size-hint': 'size'} } + + ## + # @BlockdevCreateOptionsGluster: +diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out +index 9d4ed4dc9d..7a87946fa2 100644 +--- a/tests/qemu-iotests/082.out ++++ b/tests/qemu-iotests/082.out +@@ -59,6 +59,7 @@ Supported options: + encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm + encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase + encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) ++ extent_size_hint= - Extent size hint for the image file, 0 to disable + lazy_refcounts= - Postpone refcount updates + nocow= - Turn off copy-on-write (valid only on btrfs) + preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) +@@ -82,6 +83,7 @@ Supported options: + encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm + encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase + encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) ++ extent_size_hint= - Extent size hint for the image file, 0 to disable + lazy_refcounts= - Postpone refcount updates + nocow= - Turn off copy-on-write (valid only on btrfs) + preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) +@@ -105,6 +107,7 @@ Supported options: + encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm + encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase + encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) ++ extent_size_hint= - Extent size hint for the image file, 0 to disable + lazy_refcounts= - Postpone refcount updates + nocow= - Turn off copy-on-write (valid only on btrfs) + preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) +@@ -128,6 +131,7 @@ Supported options: + encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm + encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase + encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) ++ extent_size_hint= - Extent size hint for the image file, 0 to disable + lazy_refcounts= - Postpone refcount updates + nocow= - Turn off copy-on-write (valid only on btrfs) + preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) +@@ -151,6 +155,7 @@ Supported options: + encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm + encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase + encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) ++ extent_size_hint= - Extent size hint for the image file, 0 to disable + lazy_refcounts= - Postpone refcount updates + nocow= - Turn off copy-on-write (valid only on btrfs) + preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) +@@ -174,6 +179,7 @@ Supported options: + encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm + encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase + encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) ++ extent_size_hint= - Extent size hint for the image file, 0 to disable + lazy_refcounts= - Postpone refcount updates + nocow= - Turn off copy-on-write (valid only on btrfs) + preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) +@@ -197,6 +203,7 @@ Supported options: + encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm + encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase + encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) ++ extent_size_hint= - Extent size hint for the image file, 0 to disable + lazy_refcounts= - Postpone refcount updates + nocow= - Turn off copy-on-write (valid only on btrfs) + preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) +@@ -220,6 +227,7 @@ Supported options: + encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm + encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase + encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) ++ extent_size_hint= - Extent size hint for the image file, 0 to disable + lazy_refcounts= - Postpone refcount updates + nocow= - Turn off copy-on-write (valid only on btrfs) + preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) +@@ -339,6 +347,7 @@ Supported options: + encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm + encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase + encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) ++ extent_size_hint= - Extent size hint for the image file, 0 to disable + lazy_refcounts= - Postpone refcount updates + nocow= - Turn off copy-on-write (valid only on btrfs) + preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) +@@ -362,6 +371,7 @@ Supported options: + encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm + encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase + encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) ++ extent_size_hint= - Extent size hint for the image file, 0 to disable + lazy_refcounts= - Postpone refcount updates + nocow= - Turn off copy-on-write (valid only on btrfs) + preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) +@@ -385,6 +395,7 @@ Supported options: + encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm + encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase + encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) ++ extent_size_hint= - Extent size hint for the image file, 0 to disable + lazy_refcounts= - Postpone refcount updates + nocow= - Turn off copy-on-write (valid only on btrfs) + preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) +@@ -408,6 +419,7 @@ Supported options: + encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm + encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase + encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) ++ extent_size_hint= - Extent size hint for the image file, 0 to disable + lazy_refcounts= - Postpone refcount updates + nocow= - Turn off copy-on-write (valid only on btrfs) + preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) +@@ -431,6 +443,7 @@ Supported options: + encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm + encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase + encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) ++ extent_size_hint= - Extent size hint for the image file, 0 to disable + lazy_refcounts= - Postpone refcount updates + nocow= - Turn off copy-on-write (valid only on btrfs) + preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) +@@ -454,6 +467,7 @@ Supported options: + encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm + encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase + encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) ++ extent_size_hint= - Extent size hint for the image file, 0 to disable + lazy_refcounts= - Postpone refcount updates + nocow= - Turn off copy-on-write (valid only on btrfs) + preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) +@@ -477,6 +491,7 @@ Supported options: + encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm + encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase + encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) ++ extent_size_hint= - Extent size hint for the image file, 0 to disable + lazy_refcounts= - Postpone refcount updates + nocow= - Turn off copy-on-write (valid only on btrfs) + preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) +@@ -500,6 +515,7 @@ Supported options: + encrypt.ivgen-hash-alg= - Name of IV generator hash algorithm + encrypt.key-secret= - ID of secret providing qcow AES key or LUKS passphrase + encryption= - Encrypt the image with format 'aes'. (Deprecated in favor of encrypt.format=aes) ++ extent_size_hint= - Extent size hint for the image file, 0 to disable + lazy_refcounts= - Postpone refcount updates + nocow= - Turn off copy-on-write (valid only on btrfs) + preallocation= - Preallocation mode (allowed values: off, metadata, falloc, full) +diff --git a/tests/qemu-iotests/106 b/tests/qemu-iotests/106 +index ac47eaa0f5..ee6f51d08b 100755 +--- a/tests/qemu-iotests/106 ++++ b/tests/qemu-iotests/106 +@@ -51,7 +51,10 @@ for create_mode in off falloc full; do + echo + echo "--- create_mode=$create_mode growth_mode=$growth_mode ---" + +- IMGOPTS="preallocation=$create_mode" _make_test_img ${CREATION_SIZE}K ++ # Our calculation below assumes kilobytes as unit for the actual size. ++ # Disable the extent size hint because it would give us a result in ++ # megabytes. ++ IMGOPTS="preallocation=$create_mode,extent_size_hint=0" _make_test_img ${CREATION_SIZE}K + $QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K + + expected_size=0 +@@ -98,7 +101,7 @@ for growth_mode in falloc full; do + # plain int. We should use the correct type for the result, and + # this tests we do. + +- _make_test_img 2G ++ _make_test_img -o "extent_size_hint=0" 2G + $QEMU_IMG resize -f "$IMGFMT" --preallocation=$growth_mode "$TEST_IMG" +${GROWTH_SIZE}K + + actual_size=$($QEMU_IMG info -f "$IMGFMT" "$TEST_IMG" | grep 'disk size') +diff --git a/tests/qemu-iotests/175 b/tests/qemu-iotests/175 +index 55db2803ed..8a8494aeb6 100755 +--- a/tests/qemu-iotests/175 ++++ b/tests/qemu-iotests/175 +@@ -89,20 +89,20 @@ min_blocks=$(stat -c '%b' "$TEST_DIR/empty") + + echo + echo "== creating image with default preallocation ==" +-_make_test_img $size | _filter_imgfmt ++_make_test_img -o extent_size_hint=0 $size | _filter_imgfmt + stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size + + for mode in off full falloc; do + echo + echo "== creating image with preallocation $mode ==" +- IMGOPTS=preallocation=$mode _make_test_img $size | _filter_imgfmt ++ IMGOPTS="preallocation=$mode,extent_size_hint=0" _make_test_img $size | _filter_imgfmt + stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size + done + + for new_size in 4096 1048576; do + echo + echo "== resize empty image with block_resize ==" +- _make_test_img 0 | _filter_imgfmt ++ _make_test_img -o extent_size_hint=0 0 | _filter_imgfmt + _block_resize $TEST_IMG $new_size >/dev/null + stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $new_size + done +diff --git a/tests/qemu-iotests/243 b/tests/qemu-iotests/243 +index e563761307..104c7256c4 100755 +--- a/tests/qemu-iotests/243 ++++ b/tests/qemu-iotests/243 +@@ -47,7 +47,7 @@ for mode in off metadata falloc full; do + echo "=== preallocation=$mode ===" + echo + +- IMGOPTS="preallocation=$mode" _make_test_img 64M ++ IMGOPTS="preallocation=$mode,extent_size_hint=0" _make_test_img 64M + + printf "File size: " + du -b $TEST_IMG | cut -f1 +@@ -64,7 +64,7 @@ for mode in off metadata falloc full; do + echo "=== External data file: preallocation=$mode ===" + echo + +- IMGOPTS="data_file=$TEST_IMG.data,preallocation=$mode" _make_test_img 64M ++ IMGOPTS="data_file=$TEST_IMG.data,preallocation=$mode,extent_size_hint=0" _make_test_img 64M + + echo -n "qcow2 file size: " + du -b $TEST_IMG | cut -f1 +@@ -75,7 +75,7 @@ for mode in off metadata falloc full; do + echo -n "qcow2 disk usage: " + [ $(du -B1 $TEST_IMG | cut -f1) -lt 1048576 ] && echo "low" || echo "high" + echo -n "data disk usage: " +- [ $(du -B1 $TEST_IMG.data | cut -f1) -lt 1048576 ] && echo "low" || echo "high" ++ [ $(du -B1 $TEST_IMG.data | cut -f1) -lt 2097152 ] && echo "low" || echo "high" + + done + +diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter +index c8e8663665..f29c1d3238 100644 +--- a/tests/qemu-iotests/common.filter ++++ b/tests/qemu-iotests/common.filter +@@ -146,6 +146,7 @@ _filter_img_create() + -e "s# refcount_bits=[0-9]\\+##g" \ + -e "s# key-secret=[a-zA-Z0-9]\\+##g" \ + -e "s# iter-time=[0-9]\\+##g" \ ++ -e "s# extent_size_hint=[0-9]\\+##g" \ + -e "s# force_size=\\(on\\|off\\)##g" + } + +-- +2.27.0 + diff --git a/SOURCES/kvm-glib-compat-add-g_unix_get_passwd_entry_qemu.patch b/SOURCES/kvm-glib-compat-add-g_unix_get_passwd_entry_qemu.patch new file mode 100644 index 0000000..551b2eb --- /dev/null +++ b/SOURCES/kvm-glib-compat-add-g_unix_get_passwd_entry_qemu.patch @@ -0,0 +1,89 @@ +From 15331267d11713906361ddd767c3e04ae46d9a83 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Thu, 29 Jul 2021 04:55:50 -0400 +Subject: [PATCH 01/14] glib-compat: add g_unix_get_passwd_entry_qemu() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Marc-André Lureau +Message-id: <20210609100615.2501448-2-marcandre.lureau@redhat.com> +Patchwork-id: 101687 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 1/4] glib-compat: add g_unix_get_passwd_entry_qemu() +Bugzilla: 1967716 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Michal Privoznik + +From: Marc-André Lureau + +The glib function was introduced in 2.64. It's a safer version of +getpwnam, and also simpler to use than getpwnam_r. + +Currently, it's only use by the next patch in qemu-ga, which doesn't +(well well...) need the thread safety guarantees. Since the fallback +version is still unsafe, I would rather keep the _qemu postfix, to make +sure it's not being misused by mistake. When/if necessary, we can +implement a safer fallback and drop the _qemu suffix. + +Signed-off-by: Marc-André Lureau +Reviewed-by: Michal Privoznik +*fix checkpatch warnings about newlines before/after block comments +Signed-off-by: Michael Roth + +(cherry picked from commit 6d593ab451c490b0ca941c6a519894231634751e) +Signed-off-by: Marc-André Lureau +Signed-off-by: Miroslav Rezanina +--- + include/glib-compat.h | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +diff --git a/include/glib-compat.h b/include/glib-compat.h +index 0b0ec76299..695a96f7ea 100644 +--- a/include/glib-compat.h ++++ b/include/glib-compat.h +@@ -30,6 +30,11 @@ + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + + #include ++#if defined(G_OS_UNIX) ++#include ++#include ++#include ++#endif + + /* + * Note that because of the GLIB_VERSION_MAX_ALLOWED constant above, allowing +@@ -72,6 +77,29 @@ + gint g_poll_fixed(GPollFD *fds, guint nfds, gint timeout); + #endif + ++#if defined(G_OS_UNIX) ++/* ++ * Note: The fallback implementation is not MT-safe, and it returns a copy of ++ * the libc passwd (must be g_free() after use) but not the content. Because of ++ * these important differences the caller must be aware of, it's not #define for ++ * GLib API substitution. ++ */ ++static inline struct passwd * ++g_unix_get_passwd_entry_qemu(const gchar *user_name, GError **error) ++{ ++#if GLIB_CHECK_VERSION(2, 64, 0) ++ return g_unix_get_passwd_entry(user_name, error); ++#else ++ struct passwd *p = getpwnam(user_name); ++ if (!p) { ++ g_set_error_literal(error, G_UNIX_ERROR, 0, g_strerror(errno)); ++ return NULL; ++ } ++ return (struct passwd *)g_memdup(p, sizeof(*p)); ++#endif ++} ++#endif /* G_OS_UNIX */ ++ + #pragma GCC diagnostic pop + + #endif +-- +2.27.0 + diff --git a/SOURCES/kvm-hw-intc-arm_gic-Fix-interrupt-ID-in-GICD_SGIR-regist.patch b/SOURCES/kvm-hw-intc-arm_gic-Fix-interrupt-ID-in-GICD_SGIR-regist.patch new file mode 100644 index 0000000..650555c --- /dev/null +++ b/SOURCES/kvm-hw-intc-arm_gic-Fix-interrupt-ID-in-GICD_SGIR-regist.patch @@ -0,0 +1,80 @@ +From dad4f9beaa3fd1eec1e0dd46c3d5cd2f444c0f48 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 13 Apr 2021 20:05:51 -0400 +Subject: [PATCH 1/7] hw/intc/arm_gic: Fix interrupt ID in GICD_SGIR register +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +Message-id: <20210413200551.3825495-2-jmaloy@redhat.com> +Patchwork-id: 101471 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 1/1] hw/intc/arm_gic: Fix interrupt ID in GICD_SGIR register +Bugzilla: 1925430 +RH-Acked-by: Andrew Jones +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Philippe Mathieu-Daudé + +From: Philippe Mathieu-Daudé + +Per the ARM Generic Interrupt Controller Architecture specification +(document "ARM IHI 0048B.b (ID072613)"), the SGIINTID field is 4 bit, +not 10: + + - 4.3 Distributor register descriptions + - 4.3.15 Software Generated Interrupt Register, GICD_SG + + - Table 4-21 GICD_SGIR bit assignments + + The Interrupt ID of the SGI to forward to the specified CPU + interfaces. The value of this field is the Interrupt ID, in + the range 0-15, for example a value of 0b0011 specifies + Interrupt ID 3. + +Correct the irq mask to fix an undefined behavior (which eventually +lead to a heap-buffer-overflow, see [Buglink]): + + $ echo 'writel 0x8000f00 0xff4affb0' | qemu-system-aarch64 -M virt,accel=qtest -qtest stdio + [I 1612088147.116987] OPENED + [R +0.278293] writel 0x8000f00 0xff4affb0 + ../hw/intc/arm_gic.c:1498:13: runtime error: index 944 out of bounds for type 'uint8_t [16][8]' + SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../hw/intc/arm_gic.c:1498:13 + +This fixes a security issue when running with KVM on Arm with +kernel-irqchip=off. (The default is kernel-irqchip=on, which is +unaffected, and which is also the correct choice for performance.) + +Cc: qemu-stable@nongnu.org +Fixes: CVE-2021-20221 +Fixes: 9ee6e8bb853 ("ARMv7 support.") +Buglink: https://bugs.launchpad.net/qemu/+bug/1913916 +Buglink: https://bugs.launchpad.net/qemu/+bug/1913917 +Reported-by: Alexander Bulekov +Signed-off-by: Philippe Mathieu-Daudé +Message-id: 20210131103401.217160-1-f4bug@amsat.org +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell + +(cherry picked from commit edfe2eb4360cde4ed5d95bda7777edcb3510f76a) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + hw/intc/arm_gic.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c +index 1d7da7baa2..df355f4d11 100644 +--- a/hw/intc/arm_gic.c ++++ b/hw/intc/arm_gic.c +@@ -1455,7 +1455,7 @@ static void gic_dist_writel(void *opaque, hwaddr offset, + int target_cpu; + + cpu = gic_get_current_cpu(s); +- irq = value & 0x3ff; ++ irq = value & 0xf; + switch ((value >> 24) & 3) { + case 0: + mask = (value >> 16) & ALL_CPU_MASK; +-- +2.27.0 + diff --git a/SOURCES/kvm-i386-Add-the-support-for-AMD-EPYC-3rd-generation-pro.patch b/SOURCES/kvm-i386-Add-the-support-for-AMD-EPYC-3rd-generation-pro.patch new file mode 100644 index 0000000..5c335f8 --- /dev/null +++ b/SOURCES/kvm-i386-Add-the-support-for-AMD-EPYC-3rd-generation-pro.patch @@ -0,0 +1,213 @@ +From 4daa8dca77edec191dfe0ae4a0a9fc70f8f63607 Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Wed, 24 Feb 2021 11:30:37 -0500 +Subject: [PATCH 4/4] i386: Add the support for AMD EPYC 3rd generation + processors + +RH-Author: Dr. David Alan Gilbert +Message-id: <20210224113037.15599-5-dgilbert@redhat.com> +Patchwork-id: 101202 +O-Subject: [RHEL-8.4.0 qemu-kvm PATCH 4/4] i386: Add the support for AMD EPYC 3rd generation processors +Bugzilla: 1790620 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: Peter Xu + +From: Babu Moger + +Adds the support for AMD 3rd generation processors. The model +display for the new processor will be EPYC-Milan. + +Adds the following new feature bits on top of the feature bits from +the first and second generation EPYC models. + +pcid : Process context identifiers support +ibrs : Indirect Branch Restricted Speculation +ssbd : Speculative Store Bypass Disable +erms : Enhanced REP MOVSB/STOSB support +fsrm : Fast Short REP MOVSB support +invpcid : Invalidate processor context ID +pku : Protection keys support +svme-addr-chk : SVM instructions address check for #GP handling + +Depends on the following kernel commits: +14c2bf81fcd2 ("KVM: SVM: Fix #GP handling for doubly-nested virtualization") +3b9c723ed7cf ("KVM: SVM: Add support for SVM instruction address check change") +4aa2691dcbd3 ("8ce1c461188799d863398dd2865d KVM: x86: Factor out x86 instruction emulation with decoding") +4407a797e941 ("KVM: SVM: Enable INVPCID feature on AMD") +9715092f8d7e ("KVM: X86: Move handling of INVPCID types to x86") +3f3393b3ce38 ("KVM: X86: Rename and move the function vmx_handle_memory_failure to x86.c") +830bd71f2c06 ("KVM: SVM: Remove set_cr_intercept, clr_cr_intercept and is_cr_intercept") +4c44e8d6c193 ("KVM: SVM: Add new intercept word in vmcb_control_area") +c62e2e94b9d4 ("KVM: SVM: Modify 64 bit intercept field to two 32 bit vectors") +9780d51dc2af ("KVM: SVM: Modify intercept_exceptions to generic intercepts") +30abaa88382c ("KVM: SVM: Change intercept_dr to generic intercepts") +03bfeeb988a9 ("KVM: SVM: Change intercept_cr to generic intercepts") +c45ad7229d13 ("KVM: SVM: Introduce vmcb_(set_intercept/clr_intercept/_is_intercept)") +a90c1ed9f11d ("(pcid) KVM: nSVM: Remove unused field") +fa44b82eb831 ("KVM: x86: Move MPK feature detection to common code") +38f3e775e9c2 ("x86/Kconfig: Update config and kernel doc for MPK feature on AMD") +37486135d3a7 ("KVM: x86: Fix pkru save/restore when guest CR4.PKE=0, move it to x86.c") + +Signed-off-by: Babu Moger +Message-Id: <161290460478.11352.8933244555799318236.stgit@bmoger-ubuntu> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 623972ceae091b31331ae4a1dc94fe5cbb891937) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 107 +++++++++++++++++++++++++++++++++++++++++++++- + target/i386/cpu.h | 4 ++ + 2 files changed, 110 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 7227c803c3..d5b0d4b7f0 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1133,7 +1133,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + "clzero", NULL, "xsaveerptr", NULL, + NULL, NULL, NULL, NULL, + NULL, "wbnoinvd", NULL, NULL, +- "ibpb", NULL, NULL, "amd-stibp", ++ "ibpb", NULL, "ibrs", "amd-stibp", + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + "amd-ssbd", "virt-ssbd", "amd-no-ssb", NULL, +@@ -1853,6 +1853,56 @@ static CPUCaches epyc_rome_cache_info = { + }, + }; + ++static CPUCaches epyc_milan_cache_info = { ++ .l1d_cache = &(CPUCacheInfo) { ++ .type = DATA_CACHE, ++ .level = 1, ++ .size = 32 * KiB, ++ .line_size = 64, ++ .associativity = 8, ++ .partitions = 1, ++ .sets = 64, ++ .lines_per_tag = 1, ++ .self_init = 1, ++ .no_invd_sharing = true, ++ }, ++ .l1i_cache = &(CPUCacheInfo) { ++ .type = INSTRUCTION_CACHE, ++ .level = 1, ++ .size = 32 * KiB, ++ .line_size = 64, ++ .associativity = 8, ++ .partitions = 1, ++ .sets = 64, ++ .lines_per_tag = 1, ++ .self_init = 1, ++ .no_invd_sharing = true, ++ }, ++ .l2_cache = &(CPUCacheInfo) { ++ .type = UNIFIED_CACHE, ++ .level = 2, ++ .size = 512 * KiB, ++ .line_size = 64, ++ .associativity = 8, ++ .partitions = 1, ++ .sets = 1024, ++ .lines_per_tag = 1, ++ }, ++ .l3_cache = &(CPUCacheInfo) { ++ .type = UNIFIED_CACHE, ++ .level = 3, ++ .size = 32 * MiB, ++ .line_size = 64, ++ .associativity = 16, ++ .partitions = 1, ++ .sets = 32768, ++ .lines_per_tag = 1, ++ .self_init = true, ++ .inclusive = true, ++ .complex_indexing = true, ++ }, ++}; ++ + /* The following VMX features are not supported by KVM and are left out in the + * CPU definitions: + * +@@ -4124,6 +4174,61 @@ static X86CPUDefinition builtin_x86_defs[] = { + .model_id = "AMD EPYC-Rome Processor", + .cache_info = &epyc_rome_cache_info, + }, ++ { ++ .name = "EPYC-Milan", ++ .level = 0xd, ++ .vendor = CPUID_VENDOR_AMD, ++ .family = 25, ++ .model = 1, ++ .stepping = 1, ++ .features[FEAT_1_EDX] = ++ CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | CPUID_CLFLUSH | ++ CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | CPUID_PGE | ++ CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | CPUID_MCE | ++ CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | CPUID_DE | ++ CPUID_VME | CPUID_FP87, ++ .features[FEAT_1_ECX] = ++ CPUID_EXT_RDRAND | CPUID_EXT_F16C | CPUID_EXT_AVX | ++ CPUID_EXT_XSAVE | CPUID_EXT_AES | CPUID_EXT_POPCNT | ++ CPUID_EXT_MOVBE | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 | ++ CPUID_EXT_CX16 | CPUID_EXT_FMA | CPUID_EXT_SSSE3 | ++ CPUID_EXT_MONITOR | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 | ++ CPUID_EXT_PCID, ++ .features[FEAT_8000_0001_EDX] = ++ CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_PDPE1GB | ++ CPUID_EXT2_FFXSR | CPUID_EXT2_MMXEXT | CPUID_EXT2_NX | ++ CPUID_EXT2_SYSCALL, ++ .features[FEAT_8000_0001_ECX] = ++ CPUID_EXT3_OSVW | CPUID_EXT3_3DNOWPREFETCH | ++ CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | ++ CPUID_EXT3_CR8LEG | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM | ++ CPUID_EXT3_TOPOEXT | CPUID_EXT3_PERFCORE, ++ .features[FEAT_8000_0008_EBX] = ++ CPUID_8000_0008_EBX_CLZERO | CPUID_8000_0008_EBX_XSAVEERPTR | ++ CPUID_8000_0008_EBX_WBNOINVD | CPUID_8000_0008_EBX_IBPB | ++ CPUID_8000_0008_EBX_IBRS | CPUID_8000_0008_EBX_STIBP | ++ CPUID_8000_0008_EBX_AMD_SSBD, ++ .features[FEAT_7_0_EBX] = ++ CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_AVX2 | ++ CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_RDSEED | ++ CPUID_7_0_EBX_ADX | CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLFLUSHOPT | ++ CPUID_7_0_EBX_SHA_NI | CPUID_7_0_EBX_CLWB | CPUID_7_0_EBX_ERMS | ++ CPUID_7_0_EBX_INVPCID, ++ .features[FEAT_7_0_ECX] = ++ CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_RDPID | CPUID_7_0_ECX_PKU, ++ .features[FEAT_7_0_EDX] = ++ CPUID_7_0_EDX_FSRM, ++ .features[FEAT_XSAVE] = ++ CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC | ++ CPUID_XSAVE_XGETBV1 | CPUID_XSAVE_XSAVES, ++ .features[FEAT_6_EAX] = ++ CPUID_6_EAX_ARAT, ++ .features[FEAT_SVM] = ++ CPUID_SVM_NPT | CPUID_SVM_NRIPSAVE | CPUID_SVM_SVME_ADDR_CHK, ++ .xlevel = 0x8000001E, ++ .model_id = "AMD EPYC-Milan Processor", ++ .cache_info = &epyc_milan_cache_info, ++ }, + }; + + /* KVM-specific features that are automatically added/removed +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index e1b67910c2..7a3aa40201 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -800,8 +800,12 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_8000_0008_EBX_WBNOINVD (1U << 9) + /* Indirect Branch Prediction Barrier */ + #define CPUID_8000_0008_EBX_IBPB (1U << 12) ++/* Indirect Branch Restricted Speculation */ ++#define CPUID_8000_0008_EBX_IBRS (1U << 14) + /* Single Thread Indirect Branch Predictors */ + #define CPUID_8000_0008_EBX_STIBP (1U << 15) ++/* Speculative Store Bypass Disable */ ++#define CPUID_8000_0008_EBX_AMD_SSBD (1U << 24) + + #define CPUID_XSAVE_XSAVEOPT (1U << 0) + #define CPUID_XSAVE_XSAVEC (1U << 1) +-- +2.27.0 + diff --git a/SOURCES/kvm-ide-atapi-check-logical-block-address-and-read-size-.patch b/SOURCES/kvm-ide-atapi-check-logical-block-address-and-read-size-.patch new file mode 100644 index 0000000..706bd8b --- /dev/null +++ b/SOURCES/kvm-ide-atapi-check-logical-block-address-and-read-size-.patch @@ -0,0 +1,120 @@ +From 0453588f95294ed5ce912cb8b810a322bf9d91e0 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Thu, 25 Feb 2021 19:43:02 -0500 +Subject: [PATCH] ide: atapi: check logical block address and read size + (CVE-2020-29443) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +Message-id: <20210225194302.3137699-2-jmaloy@redhat.com> +Patchwork-id: 101208 +O-Subject: [RHEL-8.4.0 qemu-kvm PATCH v2 1/1] ide: atapi: check logical block address and read size (CVE-2020-29443) +Bugzilla: 1917451 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Danilo de Paula +RH-Acked-by: Paolo Bonzini + +From: Prasad J Pandit + +While processing ATAPI cmd_read/cmd_read_cd commands, +Logical Block Address (LBA) maybe invalid OR closer to the last block, +leading to an OOB access issues. Add range check to avoid it. + +Fixes: CVE-2020-29443 +Reported-by: Wenxiang Qian +Suggested-by: Paolo Bonzini +Reviewed-by: Paolo Bonzini +Signed-off-by: Prasad J Pandit +Message-Id: <20210118115130.457044-1-ppandit@redhat.com> +Signed-off-by: Paolo Bonzini + +(cherry picked from commit b8d7f1bc59276fec85e4d09f1567613a3e14d31e) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + hw/ide/atapi.c | 30 ++++++++++++++++++++++++------ + 1 file changed, 24 insertions(+), 6 deletions(-) + +diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c +index 17a9d635d8..d064935c8d 100644 +--- a/hw/ide/atapi.c ++++ b/hw/ide/atapi.c +@@ -320,6 +320,8 @@ static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size) + static void ide_atapi_cmd_read_pio(IDEState *s, int lba, int nb_sectors, + int sector_size) + { ++ assert(0 <= lba && lba < (s->nb_sectors >> 2)); ++ + s->lba = lba; + s->packet_transfer_size = nb_sectors * sector_size; + s->elementary_transfer_size = 0; +@@ -418,6 +420,8 @@ eot: + static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors, + int sector_size) + { ++ assert(0 <= lba && lba < (s->nb_sectors >> 2)); ++ + s->lba = lba; + s->packet_transfer_size = nb_sectors * sector_size; + s->io_buffer_size = 0; +@@ -971,35 +975,49 @@ static void cmd_prevent_allow_medium_removal(IDEState *s, uint8_t* buf) + + static void cmd_read(IDEState *s, uint8_t* buf) + { +- int nb_sectors, lba; ++ unsigned int nb_sectors, lba; ++ ++ /* Total logical sectors of ATAPI_SECTOR_SIZE(=2048) bytes */ ++ uint64_t total_sectors = s->nb_sectors >> 2; + + if (buf[0] == GPCMD_READ_10) { + nb_sectors = lduw_be_p(buf + 7); + } else { + nb_sectors = ldl_be_p(buf + 6); + } +- +- lba = ldl_be_p(buf + 2); + if (nb_sectors == 0) { + ide_atapi_cmd_ok(s); + return; + } + ++ lba = ldl_be_p(buf + 2); ++ if (lba >= total_sectors || lba + nb_sectors - 1 >= total_sectors) { ++ ide_atapi_cmd_error(s, ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR); ++ return; ++ } ++ + ide_atapi_cmd_read(s, lba, nb_sectors, 2048); + } + + static void cmd_read_cd(IDEState *s, uint8_t* buf) + { +- int nb_sectors, lba, transfer_request; ++ unsigned int nb_sectors, lba, transfer_request; + +- nb_sectors = (buf[6] << 16) | (buf[7] << 8) | buf[8]; +- lba = ldl_be_p(buf + 2); ++ /* Total logical sectors of ATAPI_SECTOR_SIZE(=2048) bytes */ ++ uint64_t total_sectors = s->nb_sectors >> 2; + ++ nb_sectors = (buf[6] << 16) | (buf[7] << 8) | buf[8]; + if (nb_sectors == 0) { + ide_atapi_cmd_ok(s); + return; + } + ++ lba = ldl_be_p(buf + 2); ++ if (lba >= total_sectors || lba + nb_sectors - 1 >= total_sectors) { ++ ide_atapi_cmd_error(s, ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR); ++ return; ++ } ++ + transfer_request = buf[9] & 0xf8; + if (transfer_request == 0x00) { + /* nothing */ +-- +2.27.0 + diff --git a/SOURCES/kvm-lan9118-switch-to-use-qemu_receive_packet-for-loopba.patch b/SOURCES/kvm-lan9118-switch-to-use-qemu_receive_packet-for-loopba.patch new file mode 100644 index 0000000..902af6c --- /dev/null +++ b/SOURCES/kvm-lan9118-switch-to-use-qemu_receive_packet-for-loopba.patch @@ -0,0 +1,53 @@ +From e2cafb929acb74377754cb688419575b139b922a Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 29 Jun 2021 03:42:47 -0400 +Subject: [PATCH 9/9] lan9118: switch to use qemu_receive_packet() for loopback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +Message-id: <20210629034247.3286477-10-jmaloy@redhat.com> +Patchwork-id: 101790 +O-Subject: [RHEL-8.4.0.z qemu-kvm PATCH v2 9/9] lan9118: switch to use qemu_receive_packet() for loopback +Bugzilla: 1932917 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth + +From: Alexander Bulekov + +This patch switches to use qemu_receive_packet() which can detect +reentrancy and return early. + +This is intended to address CVE-2021-3416. + +Cc: Prasad J Pandit +Cc: qemu-stable@nongnu.org +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Jason Wang + +(cherry picked from commit 37cee01784ff0df13e5209517e1b3594a5e792d1) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + 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 ed551f2178..7bb4633f0f 100644 +--- a/hw/net/lan9118.c ++++ b/hw/net/lan9118.c +@@ -667,7 +667,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); + } +-- +2.27.0 + diff --git a/SOURCES/kvm-libqos-pci-pc-use-32-bit-write-for-EJ-register.patch b/SOURCES/kvm-libqos-pci-pc-use-32-bit-write-for-EJ-register.patch new file mode 100644 index 0000000..71a2eac --- /dev/null +++ b/SOURCES/kvm-libqos-pci-pc-use-32-bit-write-for-EJ-register.patch @@ -0,0 +1,47 @@ +From 2687e0348e3e4d377b4f5356e46948dc2b371b6d Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 21 Apr 2021 22:30:02 -0400 +Subject: [PATCH 3/7] libqos: pci-pc: use 32-bit write for EJ register +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +Message-id: <20210421223006.19650-3-jmaloy@redhat.com> +Patchwork-id: 101484 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH v2 2/6] libqos: pci-pc: use 32-bit write for EJ register +Bugzilla: 1842478 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laszlo Ersek + +From: Paolo Bonzini + +The memory region ops have min_access_size == 4 so obey it. + +Tested-by: Thomas Huth +Signed-off-by: Paolo Bonzini + +(cherry picked from commit 4b7c06837ae0b1ff56473202a42e7e386f53d6db) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + tests/libqos/pci-pc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c +index 0bc591d1da..3bb2eb3ba8 100644 +--- a/tests/libqos/pci-pc.c ++++ b/tests/libqos/pci-pc.c +@@ -186,7 +186,7 @@ void qpci_unplug_acpi_device_test(QTestState *qts, const char *id, uint8_t slot) + g_assert(!qdict_haskey(response, "error")); + qobject_unref(response); + +- qtest_outb(qts, ACPI_PCIHP_ADDR + PCI_EJ_BASE, 1 << slot); ++ qtest_outl(qts, ACPI_PCIHP_ADDR + PCI_EJ_BASE, 1 << slot); + + qtest_qmp_eventwait(qts, "DEVICE_DELETED"); + } +-- +2.27.0 + diff --git a/SOURCES/kvm-libqos-usb-hcd-ehci-use-32-bit-write-for-config-regi.patch b/SOURCES/kvm-libqos-usb-hcd-ehci-use-32-bit-write-for-config-regi.patch new file mode 100644 index 0000000..424a60c --- /dev/null +++ b/SOURCES/kvm-libqos-usb-hcd-ehci-use-32-bit-write-for-config-regi.patch @@ -0,0 +1,48 @@ +From 6320b4e76965b1cf64da4307f4d313fe6b2aa971 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 21 Apr 2021 22:30:01 -0400 +Subject: [PATCH 2/7] libqos: usb-hcd-ehci: use 32-bit write for config + register +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +Message-id: <20210421223006.19650-2-jmaloy@redhat.com> +Patchwork-id: 101478 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH v2 1/6] libqos: usb-hcd-ehci: use 32-bit write for config register +Bugzilla: 1842478 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laszlo Ersek + +From: Paolo Bonzini + +The memory region ops have min_access_size == 4 so obey it. + +Tested-by: Thomas Huth +Signed-off-by: Paolo Bonzini + +(cherry picked from commit 89ed83d8b23c11d250c290593cad3ca839d5b053) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + tests/usb-hcd-ehci-test.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/usb-hcd-ehci-test.c b/tests/usb-hcd-ehci-test.c +index 5251d539e9..c51e8bb223 100644 +--- a/tests/usb-hcd-ehci-test.c ++++ b/tests/usb-hcd-ehci-test.c +@@ -96,7 +96,7 @@ static void pci_ehci_port_1(void) + static void pci_ehci_config(void) + { + /* hands over all ports from companion uhci to ehci */ +- qpci_io_writew(ehci1.dev, ehci1.bar, 0x60, 1); ++ qpci_io_writel(ehci1.dev, ehci1.bar, 0x60, 1); + } + + static void pci_uhci_port_2(void) +-- +2.27.0 + diff --git a/SOURCES/kvm-linux-headers-Add-VFIO_CCW_REQ_IRQ_INDEX.patch b/SOURCES/kvm-linux-headers-Add-VFIO_CCW_REQ_IRQ_INDEX.patch new file mode 100644 index 0000000..d9c81cf --- /dev/null +++ b/SOURCES/kvm-linux-headers-Add-VFIO_CCW_REQ_IRQ_INDEX.patch @@ -0,0 +1,43 @@ +From f844ca939adb619cce8426e104b0039a7eba70a6 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Tue, 11 May 2021 11:24:04 -0400 +Subject: [PATCH 1/5] linux-headers: Add VFIO_CCW_REQ_IRQ_INDEX + +RH-Author: Thomas Huth +Message-id: <20210511112405.297037-2-thuth@redhat.com> +Patchwork-id: 101537 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 1/2] linux-headers: Add VFIO_CCW_REQ_IRQ_INDEX +Bugzilla: 1940450 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1940450 +Upstream-status: N/A + +This is based on upstream commit b3c818a47f ("Update linux headers to +5.11-rc2"), but has been reduced to the single hunk that is required +for the next patch (there were too many unrelated conflicts in the other +files for doing full backport of the original upstream commit). + +Signed-off-by: Thomas Huth +Signed-off-by: Danilo C. L. de Paula +--- + linux-headers/linux/vfio.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h +index f660bd7bac..9c8810bef4 100644 +--- a/linux-headers/linux/vfio.h ++++ b/linux-headers/linux/vfio.h +@@ -580,6 +580,7 @@ enum { + enum { + VFIO_CCW_IO_IRQ_INDEX, + VFIO_CCW_CRW_IRQ_INDEX, ++ VFIO_CCW_REQ_IRQ_INDEX, + VFIO_CCW_NUM_IRQS + }; + +-- +2.27.0 + diff --git a/SOURCES/kvm-memory-Revert-memory-accept-mismatching-sizes-in-mem.patch b/SOURCES/kvm-memory-Revert-memory-accept-mismatching-sizes-in-mem.patch new file mode 100644 index 0000000..f81c86f --- /dev/null +++ b/SOURCES/kvm-memory-Revert-memory-accept-mismatching-sizes-in-mem.patch @@ -0,0 +1,104 @@ +From 13f4ebe4708f4f4dc20d710e475a42d520459860 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 21 Apr 2021 22:30:03 -0400 +Subject: [PATCH 4/7] memory: Revert "memory: accept mismatching sizes in + memory_region_access_valid" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +Message-id: <20210421223006.19650-4-jmaloy@redhat.com> +Patchwork-id: 101480 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH v2 3/6] memory: Revert "memory: accept mismatching sizes in memory_region_access_valid" +Bugzilla: 1842478 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laszlo Ersek + +From: "Michael S. Tsirkin" + +Memory API documentation documents valid .min_access_size and .max_access_size +fields and explains that any access outside these boundaries is blocked. + +This is what devices seem to assume. + +However this is not what the implementation does: it simply +ignores the boundaries unless there's an "accepts" callback. + +Naturally, this breaks a bunch of devices. + +Revert to the documented behaviour. + +Devices that want to allow any access can just drop the valid field, +or add the impl field to have accesses converted to appropriate +length. + +Cc: qemu-stable@nongnu.org +Reviewed-by: Richard Henderson +Fixes: CVE-2020-13754 +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1842363 +Fixes: a014ed07bd5a ("memory: accept mismatching sizes in memory_region_access_valid") +Signed-off-by: Michael S. Tsirkin +Message-Id: <20200610134731.1514409-1-mst@redhat.com> +Signed-off-by: Paolo Bonzini + +(cherry picked from commit 5d971f9e672507210e77d020d89e0e89165c8fc9) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + memory.c | 29 +++++++++-------------------- + 1 file changed, 9 insertions(+), 20 deletions(-) + +diff --git a/memory.c b/memory.c +index 5a4a80842d..0cfcb72a5a 100644 +--- a/memory.c ++++ b/memory.c +@@ -1351,35 +1351,24 @@ bool memory_region_access_valid(MemoryRegion *mr, + bool is_write, + MemTxAttrs attrs) + { +- int access_size_min, access_size_max; +- int access_size, i; +- +- if (!mr->ops->valid.unaligned && (addr & (size - 1))) { ++ if (mr->ops->valid.accepts ++ && !mr->ops->valid.accepts(mr->opaque, addr, size, is_write, attrs)) { + return false; + } + +- if (!mr->ops->valid.accepts) { +- return true; +- } +- +- access_size_min = mr->ops->valid.min_access_size; +- if (!mr->ops->valid.min_access_size) { +- access_size_min = 1; ++ if (!mr->ops->valid.unaligned && (addr & (size - 1))) { ++ return false; + } + +- access_size_max = mr->ops->valid.max_access_size; ++ /* Treat zero as compatibility all valid */ + if (!mr->ops->valid.max_access_size) { +- access_size_max = 4; ++ return true; + } + +- access_size = MAX(MIN(size, access_size_max), access_size_min); +- for (i = 0; i < size; i += access_size) { +- if (!mr->ops->valid.accepts(mr->opaque, addr + i, access_size, +- is_write, attrs)) { +- return false; +- } ++ if (size > mr->ops->valid.max_access_size ++ || size < mr->ops->valid.min_access_size) { ++ return false; + } +- + return true; + } + +-- +2.27.0 + diff --git a/SOURCES/kvm-net-check-if-the-file-descriptor-is-valid-before-usi.patch b/SOURCES/kvm-net-check-if-the-file-descriptor-is-valid-before-usi.patch new file mode 100644 index 0000000..654a64f --- /dev/null +++ b/SOURCES/kvm-net-check-if-the-file-descriptor-is-valid-before-usi.patch @@ -0,0 +1,301 @@ +From 512c7e92808dff66779f7421f1c17a081f18d7e6 Mon Sep 17 00:00:00 2001 +From: Laurent Vivier +Date: Thu, 29 Jul 2021 04:56:46 -0400 +Subject: [PATCH 13/14] net: check if the file descriptor is valid before using + it +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Laurent Vivier +Message-id: <20210726102337.6359-2-lvivier@redhat.com> +Patchwork-id: 101924 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 1/2] net: check if the file descriptor is valid before using it +Bugzilla: 1982134 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Philippe Mathieu-Daudé + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1982134 +BRANCH: rhel-8.5.0 +UPSTREAM: Merged +BREW: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=38380653 + +qemu_set_nonblock() checks that the file descriptor can be used and, if +not, crashes QEMU. An assert() is used for that. The use of assert() is +used to detect programming error and the coredump will allow to debug +the problem. + +But in the case of the tap device, this assert() can be triggered by +a misconfiguration by the user. At startup, it's not a real problem, but it +can also happen during the hot-plug of a new device, and here it's a +problem because we can crash a perfectly healthy system. + +For instance: + # ip link add link virbr0 name macvtap0 type macvtap mode bridge + # ip link set macvtap0 up + # TAP=/dev/tap$(ip -o link show macvtap0 | cut -d: -f1) + # qemu-system-x86_64 -machine q35 -device pcie-root-port,id=pcie-root-port-0 -monitor stdio 9<> $TAP + (qemu) netdev_add type=tap,id=hostnet0,vhost=on,fd=9 + (qemu) device_add driver=virtio-net-pci,netdev=hostnet0,id=net0,bus=pcie-root-port-0 + (qemu) device_del net0 + (qemu) netdev_del hostnet0 + (qemu) netdev_add type=tap,id=hostnet1,vhost=on,fd=9 + qemu-system-x86_64: .../util/oslib-posix.c:247: qemu_set_nonblock: Assertion `f != -1' failed. + Aborted (core dumped) + +To avoid that, add a function, qemu_try_set_nonblock(), that allows to report the +problem without crashing. + +In the same way, we also update the function for vhostfd in net_init_tap_one() and +for fd in net_init_socket() (both descriptors are provided by the user and can +be wrong). + +Signed-off-by: Laurent Vivier +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Jason Wang +(cherry picked from commit 894022e616016fe81745753f14adfbd680a1c7ee) +Signed-off-by: Laurent Vivier +Signed-off-by: Miroslav Rezanina +--- + include/qemu/sockets.h | 1 + + net/socket.c | 9 +++++-- + net/tap.c | 25 +++++++++++++++--- + util/oslib-posix.c | 26 +++++++++++++------ + util/oslib-win32.c | 57 ++++++++++++++++++++++++------------------ + 5 files changed, 79 insertions(+), 39 deletions(-) + +diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h +index 57cd049d6e..7d1f813576 100644 +--- a/include/qemu/sockets.h ++++ b/include/qemu/sockets.h +@@ -18,6 +18,7 @@ int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen); + int socket_set_cork(int fd, int v); + int socket_set_nodelay(int fd); + void qemu_set_block(int fd); ++int qemu_try_set_nonblock(int fd); + void qemu_set_nonblock(int fd); + int socket_set_fast_reuse(int fd); + +diff --git a/net/socket.c b/net/socket.c +index c92354049b..2d21fddd9c 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -725,13 +725,18 @@ int net_init_socket(const Netdev *netdev, const char *name, + } + + if (sock->has_fd) { +- int fd; ++ int fd, ret; + + fd = monitor_fd_param(cur_mon, sock->fd, errp); + if (fd == -1) { + return -1; + } +- qemu_set_nonblock(fd); ++ ret = qemu_try_set_nonblock(fd); ++ if (ret < 0) { ++ error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", ++ name, fd); ++ return -1; ++ } + if (!net_socket_fd_init(peer, "socket", name, fd, 1, sock->mcast, + errp)) { + return -1; +diff --git a/net/tap.c b/net/tap.c +index 6207f61f84..41a20102fd 100644 +--- a/net/tap.c ++++ b/net/tap.c +@@ -689,6 +689,8 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, + } + + if (vhostfdname) { ++ int ret; ++ + vhostfd = monitor_fd_param(cur_mon, vhostfdname, &err); + if (vhostfd == -1) { + if (tap->has_vhostforce && tap->vhostforce) { +@@ -698,7 +700,12 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, + } + return; + } +- qemu_set_nonblock(vhostfd); ++ ret = qemu_try_set_nonblock(vhostfd); ++ if (ret < 0) { ++ error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", ++ name, fd); ++ return; ++ } + } else { + vhostfd = open("/dev/vhost-net", O_RDWR); + if (vhostfd < 0) { +@@ -766,6 +773,7 @@ int net_init_tap(const Netdev *netdev, const char *name, + Error *err = NULL; + const char *vhostfdname; + char ifname[128]; ++ int ret = 0; + + assert(netdev->type == NET_CLIENT_DRIVER_TAP); + tap = &netdev->u.tap; +@@ -795,7 +803,12 @@ int net_init_tap(const Netdev *netdev, const char *name, + return -1; + } + +- qemu_set_nonblock(fd); ++ ret = qemu_try_set_nonblock(fd); ++ if (ret < 0) { ++ error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", ++ name, fd); ++ return -1; ++ } + + vnet_hdr = tap_probe_vnet_hdr(fd); + +@@ -810,7 +823,6 @@ int net_init_tap(const Netdev *netdev, const char *name, + char **fds; + char **vhost_fds; + int nfds = 0, nvhosts = 0; +- int ret = 0; + + if (tap->has_ifname || tap->has_script || tap->has_downscript || + tap->has_vnet_hdr || tap->has_helper || tap->has_queues || +@@ -843,7 +855,12 @@ int net_init_tap(const Netdev *netdev, const char *name, + goto free_fail; + } + +- qemu_set_nonblock(fd); ++ ret = qemu_try_set_nonblock(fd); ++ if (ret < 0) { ++ error_setg_errno(errp, -ret, "%s: Can't use file descriptor %d", ++ name, fd); ++ goto free_fail; ++ } + + if (i == 0) { + vnet_hdr = tap_probe_vnet_hdr(fd); +diff --git a/util/oslib-posix.c b/util/oslib-posix.c +index 8f88e4dbe1..db70416dbb 100644 +--- a/util/oslib-posix.c ++++ b/util/oslib-posix.c +@@ -240,25 +240,35 @@ void qemu_set_block(int fd) + assert(f != -1); + } + +-void qemu_set_nonblock(int fd) ++int qemu_try_set_nonblock(int fd) + { + int f; + f = fcntl(fd, F_GETFL); +- assert(f != -1); +- f = fcntl(fd, F_SETFL, f | O_NONBLOCK); +-#ifdef __OpenBSD__ + if (f == -1) { ++ return -errno; ++ } ++ if (fcntl(fd, F_SETFL, f | O_NONBLOCK) == -1) { ++#ifdef __OpenBSD__ + /* + * Previous to OpenBSD 6.3, fcntl(F_SETFL) is not permitted on + * memory devices and sets errno to ENODEV. + * It's OK if we fail to set O_NONBLOCK on devices like /dev/null, + * because they will never block anyway. + */ +- assert(errno == ENODEV); +- } +-#else +- assert(f != -1); ++ if (errno == ENODEV) { ++ return 0; ++ } + #endif ++ return -errno; ++ } ++ return 0; ++} ++ ++void qemu_set_nonblock(int fd) ++{ ++ int f; ++ f = qemu_try_set_nonblock(fd); ++ assert(f == 0); + } + + int socket_set_fast_reuse(int fd) +diff --git a/util/oslib-win32.c b/util/oslib-win32.c +index 3b49d27297..7eedbe5859 100644 +--- a/util/oslib-win32.c ++++ b/util/oslib-win32.c +@@ -132,31 +132,6 @@ struct tm *localtime_r(const time_t *timep, struct tm *result) + } + #endif /* CONFIG_LOCALTIME_R */ + +-void qemu_set_block(int fd) +-{ +- unsigned long opt = 0; +- WSAEventSelect(fd, NULL, 0); +- ioctlsocket(fd, FIONBIO, &opt); +-} +- +-void qemu_set_nonblock(int fd) +-{ +- unsigned long opt = 1; +- ioctlsocket(fd, FIONBIO, &opt); +- qemu_fd_register(fd); +-} +- +-int socket_set_fast_reuse(int fd) +-{ +- /* Enabling the reuse of an endpoint that was used by a socket still in +- * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows +- * fast reuse is the default and SO_REUSEADDR does strange things. So we +- * don't have to do anything here. More info can be found at: +- * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */ +- return 0; +-} +- +- + static int socket_error(void) + { + switch (WSAGetLastError()) { +@@ -233,6 +208,38 @@ static int socket_error(void) + } + } + ++void qemu_set_block(int fd) ++{ ++ unsigned long opt = 0; ++ WSAEventSelect(fd, NULL, 0); ++ ioctlsocket(fd, FIONBIO, &opt); ++} ++ ++int qemu_try_set_nonblock(int fd) ++{ ++ unsigned long opt = 1; ++ if (ioctlsocket(fd, FIONBIO, &opt) != NO_ERROR) { ++ return -socket_error(); ++ } ++ qemu_fd_register(fd); ++ return 0; ++} ++ ++void qemu_set_nonblock(int fd) ++{ ++ (void)qemu_try_set_nonblock(fd); ++} ++ ++int socket_set_fast_reuse(int fd) ++{ ++ /* Enabling the reuse of an endpoint that was used by a socket still in ++ * TIME_WAIT state is usually performed by setting SO_REUSEADDR. On Windows ++ * fast reuse is the default and SO_REUSEADDR does strange things. So we ++ * don't have to do anything here. More info can be found at: ++ * http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx */ ++ return 0; ++} ++ + int inet_aton(const char *cp, struct in_addr *ia) + { + uint32_t addr = inet_addr(cp); +-- +2.27.0 + diff --git a/SOURCES/kvm-net-detect-errors-from-probing-vnet-hdr-flag-for-TAP.patch b/SOURCES/kvm-net-detect-errors-from-probing-vnet-hdr-flag-for-TAP.patch new file mode 100644 index 0000000..8718c71 --- /dev/null +++ b/SOURCES/kvm-net-detect-errors-from-probing-vnet-hdr-flag-for-TAP.patch @@ -0,0 +1,221 @@ +From 3475ea6598896edb689ca8ba6fb81781e2517b6f Mon Sep 17 00:00:00 2001 +From: Laurent Vivier +Date: Thu, 29 Jul 2021 04:56:49 -0400 +Subject: [PATCH 14/14] net: detect errors from probing vnet hdr flag for TAP + devices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Laurent Vivier +Message-id: <20210726102337.6359-3-lvivier@redhat.com> +Patchwork-id: 101923 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 2/2] net: detect errors from probing vnet hdr flag for TAP devices +Bugzilla: 1982134 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Philippe Mathieu-Daudé + +From: "Daniel P. Berrange" + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1982134 +BRANCH: rhel-8.5.0 +UPSTREAM: Merged +BREW: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=38380653 + +When QEMU sets up a tap based network device backend, it mostly ignores errors +reported from various ioctl() calls it makes, assuming the TAP file descriptor +is valid. This assumption can easily be violated when the user is passing in a +pre-opened file descriptor. At best, the ioctls may fail with a -EBADF, but if +the user passes in a bogus FD number that happens to clash with a FD number that +QEMU has opened internally for another reason, a wide variety of errnos may +result, as the TUNGETIFF ioctl number may map to a completely different command +on a different type of file. + +By ignoring all these errors, QEMU sets up a zombie network backend that will +never pass any data. Even worse, when QEMU shuts down, or that network backend +is hot-removed, it will close this bogus file descriptor, which could belong to +another QEMU device backend. + +There's no obvious guaranteed reliable way to detect that a FD genuinely is a +TAP device, as opposed to a UNIX socket, or pipe, or something else. Checking +the errno from probing vnet hdr flag though, does catch the big common cases. +ie calling TUNGETIFF will return EBADF for an invalid FD, and ENOTTY when FD is +a UNIX socket, or pipe which catches accidental collisions with FDs used for +stdio, or monitor socket. + +Previously the example below where bogus fd 9 collides with the FD used for the +chardev saw: + +$ ./x86_64-softmmu/qemu-system-x86_64 -netdev tap,id=hostnet0,fd=9 \ + -chardev socket,id=charchannel0,path=/tmp/qga,server,nowait \ + -monitor stdio -vnc :0 +qemu-system-x86_64: -netdev tap,id=hostnet0,fd=9: TUNGETIFF ioctl() failed: Inappropriate ioctl for device +TUNSETOFFLOAD ioctl() failed: Bad address +QEMU 2.9.1 monitor - type 'help' for more information +(qemu) Warning: netdev hostnet0 has no peer + +which gives a running QEMU with a zombie network backend. + +With this change applied we get an error message and QEMU immediately exits +before carrying on and making a bigger disaster: + +$ ./x86_64-softmmu/qemu-system-x86_64 -netdev tap,id=hostnet0,fd=9 \ + -chardev socket,id=charchannel0,path=/tmp/qga,server,nowait \ + -monitor stdio -vnc :0 +qemu-system-x86_64: -netdev tap,id=hostnet0,vhost=on,fd=9: Unable to query TUNGETIFF on FD 9: Inappropriate ioctl for device + +Reported-by: Dr. David Alan Gilbert +Signed-off-by: Daniel P. Berrange +Tested-by: Dr. David Alan Gilbert +Message-id: 20171027085548.3472-1-berrange@redhat.com +[lv: to simplify, don't check on EINVAL with TUNGETIFF as it exists since v2.6.27] +Signed-off-by: Laurent Vivier +Signed-off-by: Jason Wang +(cherry picked from commit e7b347d0bf640adb1c998d317eaf44d2d7cbd973) +Signed-off-by: Laurent Vivier +Signed-off-by: Miroslav Rezanina +--- + net/tap-bsd.c | 2 +- + net/tap-linux.c | 8 +++++--- + net/tap-solaris.c | 2 +- + net/tap-stub.c | 2 +- + net/tap.c | 25 ++++++++++++++++++++----- + net/tap_int.h | 2 +- + 6 files changed, 29 insertions(+), 12 deletions(-) + +diff --git a/net/tap-bsd.c b/net/tap-bsd.c +index a5c3707f80..77aaf674b1 100644 +--- a/net/tap-bsd.c ++++ b/net/tap-bsd.c +@@ -211,7 +211,7 @@ void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp) + { + } + +-int tap_probe_vnet_hdr(int fd) ++int tap_probe_vnet_hdr(int fd, Error **errp) + { + return 0; + } +diff --git a/net/tap-linux.c b/net/tap-linux.c +index e0dd442ee3..b0635e9e32 100644 +--- a/net/tap-linux.c ++++ b/net/tap-linux.c +@@ -147,13 +147,15 @@ void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp) + } + } + +-int tap_probe_vnet_hdr(int fd) ++int tap_probe_vnet_hdr(int fd, Error **errp) + { + struct ifreq ifr; + + if (ioctl(fd, TUNGETIFF, &ifr) != 0) { +- error_report("TUNGETIFF ioctl() failed: %s", strerror(errno)); +- return 0; ++ /* TUNGETIFF is available since kernel v2.6.27 */ ++ error_setg_errno(errp, errno, ++ "Unable to query TUNGETIFF on FD %d", fd); ++ return -1; + } + + return ifr.ifr_flags & IFF_VNET_HDR; +diff --git a/net/tap-solaris.c b/net/tap-solaris.c +index 4725d2314e..ae2ba68284 100644 +--- a/net/tap-solaris.c ++++ b/net/tap-solaris.c +@@ -206,7 +206,7 @@ void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp) + { + } + +-int tap_probe_vnet_hdr(int fd) ++int tap_probe_vnet_hdr(int fd, Error **errp) + { + return 0; + } +diff --git a/net/tap-stub.c b/net/tap-stub.c +index a9ab8f8293..de525a2e69 100644 +--- a/net/tap-stub.c ++++ b/net/tap-stub.c +@@ -37,7 +37,7 @@ void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp) + { + } + +-int tap_probe_vnet_hdr(int fd) ++int tap_probe_vnet_hdr(int fd, Error **errp) + { + return 0; + } +diff --git a/net/tap.c b/net/tap.c +index 41a20102fd..b37ccae00c 100644 +--- a/net/tap.c ++++ b/net/tap.c +@@ -597,7 +597,11 @@ int net_init_bridge(const Netdev *netdev, const char *name, + } + + qemu_set_nonblock(fd); +- vnet_hdr = tap_probe_vnet_hdr(fd); ++ vnet_hdr = tap_probe_vnet_hdr(fd, errp); ++ if (vnet_hdr < 0) { ++ close(fd); ++ return -1; ++ } + s = net_tap_fd_init(peer, "bridge", name, fd, vnet_hdr); + + snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s,br=%s", helper, +@@ -810,7 +814,11 @@ int net_init_tap(const Netdev *netdev, const char *name, + return -1; + } + +- vnet_hdr = tap_probe_vnet_hdr(fd); ++ vnet_hdr = tap_probe_vnet_hdr(fd, errp); ++ if (vnet_hdr < 0) { ++ close(fd); ++ return -1; ++ } + + net_init_tap_one(tap, peer, "tap", name, NULL, + script, downscript, +@@ -863,8 +871,11 @@ int net_init_tap(const Netdev *netdev, const char *name, + } + + if (i == 0) { +- vnet_hdr = tap_probe_vnet_hdr(fd); +- } else if (vnet_hdr != tap_probe_vnet_hdr(fd)) { ++ vnet_hdr = tap_probe_vnet_hdr(fd, errp); ++ if (vnet_hdr < 0) { ++ goto free_fail; ++ } ++ } else if (vnet_hdr != tap_probe_vnet_hdr(fd, NULL)) { + error_setg(errp, + "vnet_hdr not consistent across given tap fds"); + ret = -1; +@@ -909,7 +920,11 @@ free_fail: + } + + qemu_set_nonblock(fd); +- vnet_hdr = tap_probe_vnet_hdr(fd); ++ vnet_hdr = tap_probe_vnet_hdr(fd, errp); ++ if (vnet_hdr < 0) { ++ close(fd); ++ return -1; ++ } + + net_init_tap_one(tap, peer, "bridge", name, ifname, + script, downscript, vhostfdname, +diff --git a/net/tap_int.h b/net/tap_int.h +index e3194b23f4..225a49ea48 100644 +--- a/net/tap_int.h ++++ b/net/tap_int.h +@@ -34,7 +34,7 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, + ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen); + + void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp); +-int tap_probe_vnet_hdr(int fd); ++int tap_probe_vnet_hdr(int fd, Error **errp); + int tap_probe_vnet_hdr_len(int fd, int len); + int tap_probe_has_ufo(int fd); + void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo); +-- +2.27.0 + diff --git a/SOURCES/kvm-net-forbid-the-reentrant-RX.patch b/SOURCES/kvm-net-forbid-the-reentrant-RX.patch new file mode 100644 index 0000000..aaf57ed --- /dev/null +++ b/SOURCES/kvm-net-forbid-the-reentrant-RX.patch @@ -0,0 +1,50 @@ +From 1e01e2f96fd5e903394eab59365d5363394c8b18 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 13 Apr 2021 18:59:12 -0400 +Subject: [PATCH 3/5] net: forbid the reentrant RX + +RH-Author: Jon Maloy +Message-id: <20210413185912.3811035-2-jmaloy@redhat.com> +Patchwork-id: 101467 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 1/1] net: forbid the reentrant RX +Bugzilla: 1859175 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth +RH-Acked-by: Xiao Wang + +From: Jason Wang + +The memory API allows DMA into NIC's MMIO area. This means the NIC's +RX routine must be reentrant. Instead of auditing all the NIC, we can +simply detect the reentrancy and return early. The queue->delivering +is set and cleared by qemu_net_queue_deliver() for other queue helpers +to know whether the delivering in on going (NIC's receive is being +called). We can check it and return early in qemu_net_queue_flush() to +forbid reentrant RX. + +Signed-off-by: Jason Wang + +(cherry picked from commit 22dc8663d9fc7baa22100544c600b6285a63c7a3) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + net/queue.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/queue.c b/net/queue.c +index 61276ca4be..c679d79f4b 100644 +--- a/net/queue.c ++++ b/net/queue.c +@@ -250,6 +250,9 @@ void qemu_net_queue_purge(NetQueue *queue, NetClientState *from) + + bool qemu_net_queue_flush(NetQueue *queue) + { ++ if (queue->delivering) ++ return false; ++ + while (!QTAILQ_EMPTY(&queue->packets)) { + NetPacket *packet; + int ret; +-- +2.27.0 + diff --git a/SOURCES/kvm-net-introduce-qemu_receive_packet.patch b/SOURCES/kvm-net-introduce-qemu_receive_packet.patch new file mode 100644 index 0000000..8de8cae --- /dev/null +++ b/SOURCES/kvm-net-introduce-qemu_receive_packet.patch @@ -0,0 +1,187 @@ +From 89732bf03b26daaebbd3e6e031e79459ae3f77e1 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 29 Jun 2021 03:42:39 -0400 +Subject: [PATCH 1/9] net: introduce qemu_receive_packet() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +Message-id: <20210629034247.3286477-2-jmaloy@redhat.com> +Patchwork-id: 101785 +O-Subject: [RHEL-8.4.0.z qemu-kvm PATCH v2 1/9] net: introduce qemu_receive_packet() +Bugzilla: 1932917 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth + +From: Jason Wang + +Some NIC supports loopback mode and this is done by calling +nc->info->receive() directly which in fact suppresses the effort of +reentrancy check that is done in qemu_net_queue_send(). + +Unfortunately we can't use qemu_net_queue_send() here since for +loopback there's no sender as peer, so this patch introduce a +qemu_receive_packet() which is used for implementing loopback mode +for a NIC with this check. + +NIC that supports loopback mode will be converted to this helper. + +This is intended to address CVE-2021-3416. + +Cc: Prasad J Pandit +Reviewed-by: Philippe Mathieu-Daudé +Cc: qemu-stable@nongnu.org +Signed-off-by: Jason Wang + +(cherry picked from commit 705df5466c98f3efdd2b68d3b31dad86858acad7) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + 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 e175ba9677..1b32a8aaec 100644 +--- a/include/net/net.h ++++ b/include/net/net.h +@@ -142,12 +142,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 c0269bb1dc..9f2f289d77 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 84aa6d8d00..d0b651ca95 100644 +--- a/net/net.c ++++ b/net/net.c +@@ -516,6 +516,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(); +@@ -528,13 +539,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, +@@ -667,6 +672,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 c679d79f4b..5f0f9ffcaf 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, +-- +2.27.0 + diff --git a/SOURCES/kvm-net-remove-an-assert-call-in-eth_get_gso_type.patch b/SOURCES/kvm-net-remove-an-assert-call-in-eth_get_gso_type.patch new file mode 100644 index 0000000..b619e78 --- /dev/null +++ b/SOURCES/kvm-net-remove-an-assert-call-in-eth_get_gso_type.patch @@ -0,0 +1,59 @@ +From b7de63e72c479df42c324c058a487517210fa069 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 13 Apr 2021 19:21:50 -0400 +Subject: [PATCH 1/5] net: remove an assert call in eth_get_gso_type + +RH-Author: Jon Maloy +Message-id: <20210413192150.3817133-2-jmaloy@redhat.com> +Patchwork-id: 101469 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 1/1] net: remove an assert call in eth_get_gso_type +Bugzilla: 1892350 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Xiao Wang + +From: Prasad J Pandit + +eth_get_gso_type() routine returns segmentation offload type based on +L3 protocol type. It calls g_assert_not_reached if L3 protocol is +unknown, making the following return statement unreachable. Remove the +g_assert call, it maybe triggered by a guest user. + +Reported-by: Gaoning Pan +Signed-off-by: Prasad J Pandit +Signed-off-by: Jason Wang + +(cherry picked from commit 7564bf7701f00214cdc8a678a9f7df765244def1) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + net/eth.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/eth.c b/net/eth.c +index 0c1d413ee2..1e0821c5f8 100644 +--- a/net/eth.c ++++ b/net/eth.c +@@ -16,6 +16,7 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/log.h" + #include "net/eth.h" + #include "net/checksum.h" + #include "net/tap.h" +@@ -71,9 +72,8 @@ eth_get_gso_type(uint16_t l3_proto, uint8_t *l3_hdr, uint8_t l4proto) + return VIRTIO_NET_HDR_GSO_TCPV6 | ecn_state; + } + } +- +- /* Unsupported offload */ +- g_assert_not_reached(); ++ qemu_log_mask(LOG_UNIMP, "%s: probably not GSO frame, " ++ "unknown L3 protocol: 0x%04"PRIx16"\n", __func__, l3_proto); + + return VIRTIO_NET_HDR_GSO_NONE | ecn_state; + } +-- +2.27.0 + diff --git a/SOURCES/kvm-pc-bios-s390-ccw-break-loop-if-a-null-block-number-i.patch b/SOURCES/kvm-pc-bios-s390-ccw-break-loop-if-a-null-block-number-i.patch new file mode 100644 index 0000000..414cc13 --- /dev/null +++ b/SOURCES/kvm-pc-bios-s390-ccw-break-loop-if-a-null-block-number-i.patch @@ -0,0 +1,50 @@ +From 56ae2d8a1ee3a35e2eed4f4baa61f97184189b47 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Tue, 18 May 2021 13:51:24 -0400 +Subject: [PATCH 4/5] pc-bios/s390-ccw: break loop if a null block number is + reached +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20210518135125.191329-3-thuth@redhat.com> +Patchwork-id: 101549 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 2/3] pc-bios/s390-ccw: break loop if a null block number is reached +Bugzilla: 1942880 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck + +Break the loop if `cur_block_nr` is a null block number because this +means that the end of chunk is reached. In this case we will try to +boot the default entry. + +Fixes: ba831b25262a ("s390-ccw: read stage2 boot loader data to find menu") +Reviewed-by: Collin Walling +Signed-off-by: Marc Hartmayer +Message-Id: <20200924085926.21709-3-mhartmay@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 468184ec9024f4f7b55247f70ec57554e8a500d7) +Signed-off-by: Thomas Huth +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/bootmap.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c +index bb6e003270..624f524331 100644 +--- a/pc-bios/s390-ccw/bootmap.c ++++ b/pc-bios/s390-ccw/bootmap.c +@@ -192,7 +192,7 @@ static int eckd_get_boot_menu_index(block_number_t s1b_block_nr) + for (i = 0; i < STAGE2_BLK_CNT_MAX; i++) { + cur_block_nr = eckd_block_num(&s1b->seek[i].chs); + +- if (!cur_block_nr) { ++ if (!cur_block_nr || is_null_block_number(cur_block_nr)) { + break; + } + +-- +2.27.0 + diff --git a/SOURCES/kvm-pc-bios-s390-ccw-don-t-try-to-read-the-next-block-if.patch b/SOURCES/kvm-pc-bios-s390-ccw-don-t-try-to-read-the-next-block-if.patch new file mode 100644 index 0000000..2597118 --- /dev/null +++ b/SOURCES/kvm-pc-bios-s390-ccw-don-t-try-to-read-the-next-block-if.patch @@ -0,0 +1,48 @@ +From 52ba1903b2c8ce69e8cd1de2a78c2c63cc60383b Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Tue, 18 May 2021 13:51:25 -0400 +Subject: [PATCH 5/5] pc-bios/s390-ccw: don't try to read the next block if end + of chunk is reached +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20210518135125.191329-4-thuth@redhat.com> +Patchwork-id: 101550 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 3/3] pc-bios/s390-ccw: don't try to read the next block if end of chunk is reached +Bugzilla: 1942880 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck + +Don't read the block if a null block number is reached, because this means that +the end of chunk is reached. + +Reviewed-by: Collin Walling +Signed-off-by: Marc Hartmayer +Message-Id: <20210416074736.17409-1-mhartmay@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit a6625d38cce3901a7c1cba069f0abcf743a293f1) +Signed-off-by: Thomas Huth +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/bootmap.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c +index 624f524331..8458b15cb6 100644 +--- a/pc-bios/s390-ccw/bootmap.c ++++ b/pc-bios/s390-ccw/bootmap.c +@@ -212,7 +212,7 @@ static int eckd_get_boot_menu_index(block_number_t s1b_block_nr) + next_block_nr = eckd_block_num(&s1b->seek[i + 1].chs); + } + +- if (next_block_nr) { ++ if (next_block_nr && !is_null_block_number(next_block_nr)) { + read_block(next_block_nr, s2_next_blk, + "Cannot read stage2 boot loader"); + } +-- +2.27.0 + diff --git a/SOURCES/kvm-pc-bios-s390-ccw-fix-off-by-one-error.patch b/SOURCES/kvm-pc-bios-s390-ccw-fix-off-by-one-error.patch new file mode 100644 index 0000000..691bed4 --- /dev/null +++ b/SOURCES/kvm-pc-bios-s390-ccw-fix-off-by-one-error.patch @@ -0,0 +1,51 @@ +From 0e9bdb960045f98d70f765bbb585f1647e5fea08 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Tue, 18 May 2021 13:51:23 -0400 +Subject: [PATCH 3/5] pc-bios/s390-ccw: fix off-by-one error +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Thomas Huth +Message-id: <20210518135125.191329-2-thuth@redhat.com> +Patchwork-id: 101548 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 1/3] pc-bios/s390-ccw: fix off-by-one error +Bugzilla: 1942880 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck + +This error takes effect when the magic value "zIPL" is located at the +end of a block. For example if s2_cur_blk = 0x7fe18000 and the magic +value "zIPL" is located at 0x7fe18ffc - 0x7fe18fff. + +Fixes: ba831b25262a ("s390-ccw: read stage2 boot loader data to find menu") +Reviewed-by: Collin Walling +Signed-off-by: Marc Hartmayer +Message-Id: <20200924085926.21709-2-mhartmay@linux.ibm.com> +Reviewed-by: Thomas Huth +[thuth: Use "<= ... - 4" instead of "< ... - 3"] +Signed-off-by: Thomas Huth +(cherry picked from commit 5f97ba0c74ccace0a4014460de9751ff3c6f454a) +Signed-off-by: Thomas Huth +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/bootmap.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c +index e91ea719ff..bb6e003270 100644 +--- a/pc-bios/s390-ccw/bootmap.c ++++ b/pc-bios/s390-ccw/bootmap.c +@@ -163,7 +163,7 @@ static bool find_zipl_boot_menu_banner(int *offset) + int i; + + /* Menu banner starts with "zIPL" */ +- for (i = 0; i < virtio_get_block_size() - 4; i++) { ++ for (i = 0; i <= virtio_get_block_size() - 4; i++) { + if (magic_match(s2_cur_blk + i, ZIPL_MAGIC_EBCDIC)) { + *offset = i; + return true; +-- +2.27.0 + diff --git a/SOURCES/kvm-pcnet-switch-to-use-qemu_receive_packet-for-loopback.patch b/SOURCES/kvm-pcnet-switch-to-use-qemu_receive_packet-for-loopback.patch new file mode 100644 index 0000000..8c33334 --- /dev/null +++ b/SOURCES/kvm-pcnet-switch-to-use-qemu_receive_packet-for-loopback.patch @@ -0,0 +1,54 @@ +From b36a9259e085b4d32532d896e485889181b130ae Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 29 Jun 2021 03:42:45 -0400 +Subject: [PATCH 7/9] pcnet: switch to use qemu_receive_packet() for loopback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +Message-id: <20210629034247.3286477-8-jmaloy@redhat.com> +Patchwork-id: 101791 +O-Subject: [RHEL-8.4.0.z qemu-kvm PATCH v2 7/9] pcnet: switch to use qemu_receive_packet() for loopback +Bugzilla: 1932917 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth + +From: Alexander Bulekov + +This patch switches to use qemu_receive_packet() which can detect +reentrancy and return early. + +This is intended to address CVE-2021-3416. + +Cc: Prasad J Pandit +Cc: qemu-stable@nongnu.org +Buglink: https://bugs.launchpad.net/qemu/+bug/1917085 +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Jason Wang + +(cherry picked from commit 99ccfaa1edafd79f7a3a0ff7b58ae4da7c514928) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + 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 f3f18d8598..dcd3fc4948 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) { +-- +2.27.0 + diff --git a/SOURCES/kvm-qemu-img-convert-Don-t-pre-zero-images.patch b/SOURCES/kvm-qemu-img-convert-Don-t-pre-zero-images.patch new file mode 100644 index 0000000..28311f4 --- /dev/null +++ b/SOURCES/kvm-qemu-img-convert-Don-t-pre-zero-images.patch @@ -0,0 +1,73 @@ +From eea45924903f03dc6d8f20576be0a4a84d5acce4 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 10 Feb 2021 10:16:11 -0500 +Subject: [PATCH 4/5] qemu-img convert: Don't pre-zero images + +RH-Author: Kevin Wolf +Message-id: <20210210101611.137928-2-kwolf@redhat.com> +Patchwork-id: 101030 +O-Subject: [RHEL-8.4.0 qemu-kvm PATCH 1/1] qemu-img convert: Don't pre-zero images +Bugzilla: 1855250 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Max Reitz + +Since commit 5a37b60a61c, qemu-img create will pre-zero the target image +if it isn't already zero-initialised (most importantly, for host block +devices, but also iscsi etc.), so that writing explicit zeros wouldn't +be necessary later. + +This could speed up the operation significantly, in particular when the +source image file was only sparsely populated. However, it also means +that some block are written twice: Once when pre-zeroing them, and then +when they are overwritten with actual data. On a full image, the +pre-zeroing is wasted work because everything will be overwritten. + +In practice, write_zeroes typically turns out faster than writing +explicit zero buffers, but slow enough that first zeroing everything and +then overwriting parts can be a significant net loss. + +Meanwhile, qemu-img convert was rewritten in 690c7301600 and zero blocks +are now written to the target using bdrv_co_pwrite_zeroes() if the +target could be pre-zeroed. This way we already make use of the faster +write_zeroes operation, but avoid writing any blocks twice. + +Remove the pre-zeroing because these days this former optimisation has +actually turned into a pessimisation in the common case. + +Reported-by: Nir Soffer +Signed-off-by: Kevin Wolf +Message-Id: <20200622151203.35624-1-kwolf@redhat.com> +Tested-by: Nir Soffer +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit edafc70c0c8510862f2f213a3acf7067113bcd08) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + qemu-img.c | 9 --------- + 1 file changed, 9 deletions(-) + +diff --git a/qemu-img.c b/qemu-img.c +index a27ad70851..b10dc5129b 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -2029,15 +2029,6 @@ static int convert_do_copy(ImgConvertState *s) + s->has_zero_init = false; + } + +- if (!s->has_zero_init && !s->target_has_backing && +- bdrv_can_write_zeroes_with_unmap(blk_bs(s->target))) +- { +- ret = blk_make_zero(s->target, BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK); +- if (ret == 0) { +- s->has_zero_init = true; +- } +- } +- + /* Allocate buffer for copied data. For compressed images, only one cluster + * can be copied at a time. */ + if (s->compressed) { +-- +2.27.0 + diff --git a/SOURCES/kvm-qga-add-reset-argument-to-ssh-add-authorized-keys.patch b/SOURCES/kvm-qga-add-reset-argument-to-ssh-add-authorized-keys.patch new file mode 100644 index 0000000..dec7f7b --- /dev/null +++ b/SOURCES/kvm-qga-add-reset-argument-to-ssh-add-authorized-keys.patch @@ -0,0 +1,176 @@ +From 7f8888f2c53060c4536856859d5ea94d23ea9e45 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Thu, 29 Jul 2021 04:55:54 -0400 +Subject: [PATCH 03/14] qga: add *reset argument to ssh-add-authorized-keys +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Marc-André Lureau +Message-id: <20210609100615.2501448-4-marcandre.lureau@redhat.com> +Patchwork-id: 101689 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 3/4] qga: add *reset argument to ssh-add-authorized-keys +Bugzilla: 1967716 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Michal Privoznik + +From: Michael Roth + +I prefer 'reset' over 'clear', since 'clear' and keys may have some +other relations or meaning. + +Signed-off-by: Marc-André Lureau +*fix disallowed g_assert* usage reported by checkpatch +Signed-off-by: Michael Roth + +(cherry picked from commit 0e3c94758e3851f0ab30d2a1e63a73284499775d) +Signed-off-by: Marc-André Lureau +Signed-off-by: Miroslav Rezanina +--- + qga/commands-posix-ssh.c | 53 ++++++++++++++++++++++++++++++++++++---- + qga/qapi-schema.json | 3 ++- + 2 files changed, 50 insertions(+), 6 deletions(-) + +diff --git a/qga/commands-posix-ssh.c b/qga/commands-posix-ssh.c +index f74d89679c..362c9e8816 100644 +--- a/qga/commands-posix-ssh.c ++++ b/qga/commands-posix-ssh.c +@@ -168,6 +168,7 @@ read_authkeys(const char *path, Error **errp) + + void + qmp_guest_ssh_add_authorized_keys(const char *username, strList *keys, ++ bool has_reset, bool reset, + Error **errp) + { + g_autofree struct passwd *p = NULL; +@@ -178,6 +179,7 @@ qmp_guest_ssh_add_authorized_keys(const char *username, strList *keys, + size_t nkeys, nauthkeys; + + ERRP_GUARD(); ++ reset = has_reset && reset; + + if (!check_openssh_pub_keys(keys, &nkeys, errp)) { + return; +@@ -191,7 +193,9 @@ qmp_guest_ssh_add_authorized_keys(const char *username, strList *keys, + ssh_path = g_build_filename(p->pw_dir, ".ssh", NULL); + authkeys_path = g_build_filename(ssh_path, "authorized_keys", NULL); + +- authkeys = read_authkeys(authkeys_path, NULL); ++ if (!reset) { ++ authkeys = read_authkeys(authkeys_path, NULL); ++ } + if (authkeys == NULL) { + if (!g_file_test(ssh_path, G_FILE_TEST_IS_DIR) && + !mkdir_for_user(ssh_path, p, 0700, errp)) { +@@ -318,7 +322,7 @@ test_invalid_user(void) + { + Error *err = NULL; + +- qmp_guest_ssh_add_authorized_keys("", NULL, &err); ++ qmp_guest_ssh_add_authorized_keys("", NULL, FALSE, FALSE, &err); + error_free_or_abort(&err); + + qmp_guest_ssh_remove_authorized_keys("", NULL, &err); +@@ -333,7 +337,8 @@ test_invalid_key(void) + }; + Error *err = NULL; + +- qmp_guest_ssh_add_authorized_keys(g_get_user_name(), &key, &err); ++ qmp_guest_ssh_add_authorized_keys(g_get_user_name(), &key, ++ FALSE, FALSE, &err); + error_free_or_abort(&err); + + qmp_guest_ssh_remove_authorized_keys(g_get_user_name(), &key, &err); +@@ -346,13 +351,17 @@ test_add_keys(void) + Error *err = NULL; + + qmp_guest_ssh_add_authorized_keys(g_get_user_name(), +- (strList *)&test_key2, &err); ++ (strList *)&test_key2, ++ FALSE, FALSE, ++ &err); + g_assert(err == NULL); + + test_authorized_keys_equal("algo key2 comments"); + + qmp_guest_ssh_add_authorized_keys(g_get_user_name(), +- (strList *)&test_key1_2, &err); ++ (strList *)&test_key1_2, ++ FALSE, FALSE, ++ &err); + g_assert(err == NULL); + + /* key2 came first, and should'nt be duplicated */ +@@ -360,6 +369,39 @@ test_add_keys(void) + "algo key1 comments"); + } + ++static void ++test_add_reset_keys(void) ++{ ++ Error *err = NULL; ++ ++ qmp_guest_ssh_add_authorized_keys(g_get_user_name(), ++ (strList *)&test_key1_2, ++ FALSE, FALSE, ++ &err); ++ g_assert(err == NULL); ++ ++ /* reset with key2 only */ ++ test_authorized_keys_equal("algo key1 comments\n" ++ "algo key2 comments"); ++ ++ qmp_guest_ssh_add_authorized_keys(g_get_user_name(), ++ (strList *)&test_key2, ++ TRUE, TRUE, ++ &err); ++ g_assert(err == NULL); ++ ++ test_authorized_keys_equal("algo key2 comments"); ++ ++ /* empty should clear file */ ++ qmp_guest_ssh_add_authorized_keys(g_get_user_name(), ++ (strList *)NULL, ++ TRUE, TRUE, ++ &err); ++ g_assert(err == NULL); ++ ++ test_authorized_keys_equal(""); ++} ++ + static void + test_remove_keys(void) + { +@@ -393,6 +435,7 @@ int main(int argc, char *argv[]) + g_test_add_func("/qga/ssh/invalid_user", test_invalid_user); + g_test_add_func("/qga/ssh/invalid_key", test_invalid_key); + g_test_add_func("/qga/ssh/add_keys", test_add_keys); ++ g_test_add_func("/qga/ssh/add_reset_keys", test_add_reset_keys); + g_test_add_func("/qga/ssh/remove_keys", test_remove_keys); + + return g_test_run(); +diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json +index 3b85f5a03f..a70ea5da77 100644 +--- a/qga/qapi-schema.json ++++ b/qga/qapi-schema.json +@@ -1279,6 +1279,7 @@ + # + # @username: the user account to add the authorized keys + # @keys: the public keys to add (in OpenSSH/sshd(8) authorized_keys format) ++# @reset: ignore the existing content, set it with the given keys only + # + # Append public keys to user .ssh/authorized_keys on Unix systems (not + # implemented for other systems). +@@ -1288,7 +1289,7 @@ + # Since: 5.2 + ## + { 'command': 'guest-ssh-add-authorized-keys', +- 'data': { 'username': 'str', 'keys': ['str'] }, ++ 'data': { 'username': 'str', 'keys': ['str'], '*reset': 'bool' }, + 'if': 'defined(CONFIG_POSIX)' } + + ## +-- +2.27.0 + diff --git a/SOURCES/kvm-qga-add-ssh-add-remove-authorized-keys.patch b/SOURCES/kvm-qga-add-ssh-add-remove-authorized-keys.patch new file mode 100644 index 0000000..b767d42 --- /dev/null +++ b/SOURCES/kvm-qga-add-ssh-add-remove-authorized-keys.patch @@ -0,0 +1,525 @@ +From 4be6cb23235b29d6ce450c2dacaef09c52d1aeea Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Thu, 29 Jul 2021 04:55:52 -0400 +Subject: [PATCH 02/14] qga: add ssh-{add, remove}-authorized-keys +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Marc-André Lureau +Message-id: <20210609100615.2501448-3-marcandre.lureau@redhat.com> +Patchwork-id: 101688 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 2/4] qga: add ssh-{add, remove}-authorized-keys +Bugzilla: 1967716 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Michal Privoznik + +From: Marc-André Lureau + +Add new commands to add and remove SSH public keys from +~/.ssh/authorized_keys. + +I took a different approach for testing, including the unit tests right +with the code. I wanted to overwrite the function to get the user +details, I couldn't easily do that over QMP. Furthermore, I prefer +having unit tests very close to the code, and unit files that are domain +specific (commands-posix is too crowded already). FWIW, that +coding/testing style is Rust-style (where tests can or should even be +part of the documentation!). + +Fixes: +https://bugzilla.redhat.com/show_bug.cgi?id=1885332 + +Signed-off-by: Marc-André Lureau +Reviewed-by: Michal Privoznik +Reviewed-by: Daniel P. Berrangé +*squashed in fix-ups for setting file ownership and use of QAPI + conditionals for CONFIG_POSIX instead of stub definitions +*disable qga-ssh-test for now due to G_TEST_OPTION_ISOLATE_DIRS + triggering leak detector in build-oss-fuzz +*fix disallowed g_assert* usage reported by checkpatch +Signed-off-by: Michael Roth + +(cherry picked from commit 8d769ec777dccbff199711aba43aa6297fe4a0e0) +[ Fixes trivial backport conflicts and use Makefile.objs build-sys ] +Signed-off-by: Marc-André Lureau +Signed-off-by: Miroslav Rezanina +--- + qga/Makefile.objs | 2 +- + qga/commands-posix-ssh.c | 407 +++++++++++++++++++++++++++++++++++++++ + qga/qapi-schema.json | 35 ++++ + 3 files changed, 443 insertions(+), 1 deletion(-) + create mode 100644 qga/commands-posix-ssh.c + +diff --git a/qga/Makefile.objs b/qga/Makefile.objs +index 80e6bb3c2e..c8da634db0 100644 +--- a/qga/Makefile.objs ++++ b/qga/Makefile.objs +@@ -1,6 +1,6 @@ + commands-posix.o-libs := $(LIBUDEV_LIBS) + qga-obj-y = commands.o guest-agent-command-state.o main.o +-qga-obj-$(CONFIG_POSIX) += commands-posix.o channel-posix.o ++qga-obj-$(CONFIG_POSIX) += commands-posix.o channel-posix.o commands-posix-ssh.o + qga-obj-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o + qga-obj-$(CONFIG_WIN32) += vss-win32.o + qga-obj-y += qapi-generated/qga-qapi-types.o qapi-generated/qga-qapi-visit.o +diff --git a/qga/commands-posix-ssh.c b/qga/commands-posix-ssh.c +new file mode 100644 +index 0000000000..f74d89679c +--- /dev/null ++++ b/qga/commands-posix-ssh.c +@@ -0,0 +1,407 @@ ++ /* ++ * This work is licensed under the terms of the GNU GPL, version 2 or later. ++ * See the COPYING file in the top-level directory. ++ */ ++#include "qemu/osdep.h" ++ ++#include ++#include ++#include ++#include ++ ++#include "qapi/error.h" ++#include "qga-qapi-commands.h" ++ ++#ifdef QGA_BUILD_UNIT_TEST ++static struct passwd * ++test_get_passwd_entry(const gchar *user_name, GError **error) ++{ ++ struct passwd *p; ++ int ret; ++ ++ if (!user_name || g_strcmp0(user_name, g_get_user_name())) { ++ g_set_error(error, G_UNIX_ERROR, 0, "Invalid user name"); ++ return NULL; ++ } ++ ++ p = g_new0(struct passwd, 1); ++ p->pw_dir = (char *)g_get_home_dir(); ++ p->pw_uid = geteuid(); ++ p->pw_gid = getegid(); ++ ++ ret = g_mkdir_with_parents(p->pw_dir, 0700); ++ g_assert(ret == 0); ++ ++ return p; ++} ++ ++#define g_unix_get_passwd_entry_qemu(username, err) \ ++ test_get_passwd_entry(username, err) ++#endif ++ ++static struct passwd * ++get_passwd_entry(const char *username, Error **errp) ++{ ++ g_autoptr(GError) err = NULL; ++ struct passwd *p; ++ ++ ERRP_GUARD(); ++ ++ p = g_unix_get_passwd_entry_qemu(username, &err); ++ if (p == NULL) { ++ error_setg(errp, "failed to lookup user '%s': %s", ++ username, err->message); ++ return NULL; ++ } ++ ++ return p; ++} ++ ++static bool ++mkdir_for_user(const char *path, const struct passwd *p, ++ mode_t mode, Error **errp) ++{ ++ ERRP_GUARD(); ++ ++ if (g_mkdir(path, mode) == -1) { ++ error_setg(errp, "failed to create directory '%s': %s", ++ path, g_strerror(errno)); ++ return false; ++ } ++ ++ if (chown(path, p->pw_uid, p->pw_gid) == -1) { ++ error_setg(errp, "failed to set ownership of directory '%s': %s", ++ path, g_strerror(errno)); ++ return false; ++ } ++ ++ if (chmod(path, mode) == -1) { ++ error_setg(errp, "failed to set permissions of directory '%s': %s", ++ path, g_strerror(errno)); ++ return false; ++ } ++ ++ return true; ++} ++ ++static bool ++check_openssh_pub_key(const char *key, Error **errp) ++{ ++ ERRP_GUARD(); ++ ++ /* simple sanity-check, we may want more? */ ++ if (!key || key[0] == '#' || strchr(key, '\n')) { ++ error_setg(errp, "invalid OpenSSH public key: '%s'", key); ++ return false; ++ } ++ ++ return true; ++} ++ ++static bool ++check_openssh_pub_keys(strList *keys, size_t *nkeys, Error **errp) ++{ ++ size_t n = 0; ++ strList *k; ++ ++ ERRP_GUARD(); ++ ++ for (k = keys; k != NULL; k = k->next) { ++ if (!check_openssh_pub_key(k->value, errp)) { ++ return false; ++ } ++ n++; ++ } ++ ++ if (nkeys) { ++ *nkeys = n; ++ } ++ return true; ++} ++ ++static bool ++write_authkeys(const char *path, const GStrv keys, ++ const struct passwd *p, Error **errp) ++{ ++ g_autofree char *contents = NULL; ++ g_autoptr(GError) err = NULL; ++ ++ ERRP_GUARD(); ++ ++ contents = g_strjoinv("\n", keys); ++ if (!g_file_set_contents(path, contents, -1, &err)) { ++ error_setg(errp, "failed to write to '%s': %s", path, err->message); ++ return false; ++ } ++ ++ if (chown(path, p->pw_uid, p->pw_gid) == -1) { ++ error_setg(errp, "failed to set ownership of directory '%s': %s", ++ path, g_strerror(errno)); ++ return false; ++ } ++ ++ if (chmod(path, 0600) == -1) { ++ error_setg(errp, "failed to set permissions of '%s': %s", ++ path, g_strerror(errno)); ++ return false; ++ } ++ ++ return true; ++} ++ ++static GStrv ++read_authkeys(const char *path, Error **errp) ++{ ++ g_autoptr(GError) err = NULL; ++ g_autofree char *contents = NULL; ++ ++ ERRP_GUARD(); ++ ++ if (!g_file_get_contents(path, &contents, NULL, &err)) { ++ error_setg(errp, "failed to read '%s': %s", path, err->message); ++ return NULL; ++ } ++ ++ return g_strsplit(contents, "\n", -1); ++ ++} ++ ++void ++qmp_guest_ssh_add_authorized_keys(const char *username, strList *keys, ++ Error **errp) ++{ ++ g_autofree struct passwd *p = NULL; ++ g_autofree char *ssh_path = NULL; ++ g_autofree char *authkeys_path = NULL; ++ g_auto(GStrv) authkeys = NULL; ++ strList *k; ++ size_t nkeys, nauthkeys; ++ ++ ERRP_GUARD(); ++ ++ if (!check_openssh_pub_keys(keys, &nkeys, errp)) { ++ return; ++ } ++ ++ p = get_passwd_entry(username, errp); ++ if (p == NULL) { ++ return; ++ } ++ ++ ssh_path = g_build_filename(p->pw_dir, ".ssh", NULL); ++ authkeys_path = g_build_filename(ssh_path, "authorized_keys", NULL); ++ ++ authkeys = read_authkeys(authkeys_path, NULL); ++ if (authkeys == NULL) { ++ if (!g_file_test(ssh_path, G_FILE_TEST_IS_DIR) && ++ !mkdir_for_user(ssh_path, p, 0700, errp)) { ++ return; ++ } ++ } ++ ++ nauthkeys = authkeys ? g_strv_length(authkeys) : 0; ++ authkeys = g_realloc_n(authkeys, nauthkeys + nkeys + 1, sizeof(char *)); ++ memset(authkeys + nauthkeys, 0, (nkeys + 1) * sizeof(char *)); ++ ++ for (k = keys; k != NULL; k = k->next) { ++ if (g_strv_contains((const gchar * const *)authkeys, k->value)) { ++ continue; ++ } ++ authkeys[nauthkeys++] = g_strdup(k->value); ++ } ++ ++ write_authkeys(authkeys_path, authkeys, p, errp); ++} ++ ++void ++qmp_guest_ssh_remove_authorized_keys(const char *username, strList *keys, ++ Error **errp) ++{ ++ g_autofree struct passwd *p = NULL; ++ g_autofree char *authkeys_path = NULL; ++ g_autofree GStrv new_keys = NULL; /* do not own the strings */ ++ g_auto(GStrv) authkeys = NULL; ++ GStrv a; ++ size_t nkeys = 0; ++ ++ ERRP_GUARD(); ++ ++ if (!check_openssh_pub_keys(keys, NULL, errp)) { ++ return; ++ } ++ ++ p = get_passwd_entry(username, errp); ++ if (p == NULL) { ++ return; ++ } ++ ++ authkeys_path = g_build_filename(p->pw_dir, ".ssh", ++ "authorized_keys", NULL); ++ if (!g_file_test(authkeys_path, G_FILE_TEST_EXISTS)) { ++ return; ++ } ++ authkeys = read_authkeys(authkeys_path, errp); ++ if (authkeys == NULL) { ++ return; ++ } ++ ++ new_keys = g_new0(char *, g_strv_length(authkeys) + 1); ++ for (a = authkeys; *a != NULL; a++) { ++ strList *k; ++ ++ for (k = keys; k != NULL; k = k->next) { ++ if (g_str_equal(k->value, *a)) { ++ break; ++ } ++ } ++ if (k != NULL) { ++ continue; ++ } ++ ++ new_keys[nkeys++] = *a; ++ } ++ ++ write_authkeys(authkeys_path, new_keys, p, errp); ++} ++ ++ ++#ifdef QGA_BUILD_UNIT_TEST ++#if GLIB_CHECK_VERSION(2, 60, 0) ++static const strList test_key2 = { ++ .value = (char *)"algo key2 comments" ++}; ++ ++static const strList test_key1_2 = { ++ .value = (char *)"algo key1 comments", ++ .next = (strList *)&test_key2, ++}; ++ ++static char * ++test_get_authorized_keys_path(void) ++{ ++ return g_build_filename(g_get_home_dir(), ".ssh", "authorized_keys", NULL); ++} ++ ++static void ++test_authorized_keys_set(const char *contents) ++{ ++ g_autoptr(GError) err = NULL; ++ g_autofree char *path = NULL; ++ int ret; ++ ++ path = g_build_filename(g_get_home_dir(), ".ssh", NULL); ++ ret = g_mkdir_with_parents(path, 0700); ++ g_assert(ret == 0); ++ g_free(path); ++ ++ path = test_get_authorized_keys_path(); ++ g_file_set_contents(path, contents, -1, &err); ++ g_assert(err == NULL); ++} ++ ++static void ++test_authorized_keys_equal(const char *expected) ++{ ++ g_autoptr(GError) err = NULL; ++ g_autofree char *path = NULL; ++ g_autofree char *contents = NULL; ++ ++ path = test_get_authorized_keys_path(); ++ g_file_get_contents(path, &contents, NULL, &err); ++ g_assert(err == NULL); ++ ++ g_assert(g_strcmp0(contents, expected) == 0); ++} ++ ++static void ++test_invalid_user(void) ++{ ++ Error *err = NULL; ++ ++ qmp_guest_ssh_add_authorized_keys("", NULL, &err); ++ error_free_or_abort(&err); ++ ++ qmp_guest_ssh_remove_authorized_keys("", NULL, &err); ++ error_free_or_abort(&err); ++} ++ ++static void ++test_invalid_key(void) ++{ ++ strList key = { ++ .value = (char *)"not a valid\nkey" ++ }; ++ Error *err = NULL; ++ ++ qmp_guest_ssh_add_authorized_keys(g_get_user_name(), &key, &err); ++ error_free_or_abort(&err); ++ ++ qmp_guest_ssh_remove_authorized_keys(g_get_user_name(), &key, &err); ++ error_free_or_abort(&err); ++} ++ ++static void ++test_add_keys(void) ++{ ++ Error *err = NULL; ++ ++ qmp_guest_ssh_add_authorized_keys(g_get_user_name(), ++ (strList *)&test_key2, &err); ++ g_assert(err == NULL); ++ ++ test_authorized_keys_equal("algo key2 comments"); ++ ++ qmp_guest_ssh_add_authorized_keys(g_get_user_name(), ++ (strList *)&test_key1_2, &err); ++ g_assert(err == NULL); ++ ++ /* key2 came first, and should'nt be duplicated */ ++ test_authorized_keys_equal("algo key2 comments\n" ++ "algo key1 comments"); ++} ++ ++static void ++test_remove_keys(void) ++{ ++ Error *err = NULL; ++ static const char *authkeys = ++ "algo key1 comments\n" ++ /* originally duplicated */ ++ "algo key1 comments\n" ++ "# a commented line\n" ++ "algo some-key another\n"; ++ ++ test_authorized_keys_set(authkeys); ++ qmp_guest_ssh_remove_authorized_keys(g_get_user_name(), ++ (strList *)&test_key2, &err); ++ g_assert(err == NULL); ++ test_authorized_keys_equal(authkeys); ++ ++ qmp_guest_ssh_remove_authorized_keys(g_get_user_name(), ++ (strList *)&test_key1_2, &err); ++ g_assert(err == NULL); ++ test_authorized_keys_equal("# a commented line\n" ++ "algo some-key another\n"); ++} ++ ++int main(int argc, char *argv[]) ++{ ++ setlocale(LC_ALL, ""); ++ ++ g_test_init(&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL); ++ ++ g_test_add_func("/qga/ssh/invalid_user", test_invalid_user); ++ g_test_add_func("/qga/ssh/invalid_key", test_invalid_key); ++ g_test_add_func("/qga/ssh/add_keys", test_add_keys); ++ g_test_add_func("/qga/ssh/remove_keys", test_remove_keys); ++ ++ return g_test_run(); ++} ++#else ++int main(int argc, char *argv[]) ++{ ++ g_test_message("test skipped, needs glib >= 2.60"); ++ return 0; ++} ++#endif /* GLIB_2_60 */ ++#endif /* BUILD_UNIT_TEST */ +diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json +index 4222cb92d3..3b85f5a03f 100644 +--- a/qga/qapi-schema.json ++++ b/qga/qapi-schema.json +@@ -1273,3 +1273,38 @@ + ## + { 'command': 'guest-get-osinfo', + 'returns': 'GuestOSInfo' } ++ ++## ++# @guest-ssh-add-authorized-keys: ++# ++# @username: the user account to add the authorized keys ++# @keys: the public keys to add (in OpenSSH/sshd(8) authorized_keys format) ++# ++# Append public keys to user .ssh/authorized_keys on Unix systems (not ++# implemented for other systems). ++# ++# Returns: Nothing on success. ++# ++# Since: 5.2 ++## ++{ 'command': 'guest-ssh-add-authorized-keys', ++ 'data': { 'username': 'str', 'keys': ['str'] }, ++ 'if': 'defined(CONFIG_POSIX)' } ++ ++## ++# @guest-ssh-remove-authorized-keys: ++# ++# @username: the user account to remove the authorized keys ++# @keys: the public keys to remove (in OpenSSH/sshd(8) authorized_keys format) ++# ++# Remove public keys from the user .ssh/authorized_keys on Unix systems (not ++# implemented for other systems). It's not an error if the key is already ++# missing. ++# ++# Returns: Nothing on success. ++# ++# Since: 5.2 ++## ++{ 'command': 'guest-ssh-remove-authorized-keys', ++ 'data': { 'username': 'str', 'keys': ['str'] }, ++ 'if': 'defined(CONFIG_POSIX)' } +-- +2.27.0 + diff --git a/SOURCES/kvm-qga-add-ssh-get-authorized-keys.patch b/SOURCES/kvm-qga-add-ssh-get-authorized-keys.patch new file mode 100644 index 0000000..2b4c377 --- /dev/null +++ b/SOURCES/kvm-qga-add-ssh-get-authorized-keys.patch @@ -0,0 +1,170 @@ +From 1ed102f5489e6cf3168d9014e9a082909193b6fc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Thu, 29 Jul 2021 04:55:57 -0400 +Subject: [PATCH 04/14] qga: add ssh-get-authorized-keys +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Marc-André Lureau +Message-id: <20210609100615.2501448-5-marcandre.lureau@redhat.com> +Patchwork-id: 101690 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 4/4] qga: add ssh-get-authorized-keys +Bugzilla: 1967716 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Michal Privoznik + +From: Marc-André Lureau + +Signed-off-by: Marc-André Lureau +*fix-up merge conflicts due to qga-ssh-test being disabled in earlier + patch due to G_TEST_OPTION_ISOLATE_DIRS triggering build-oss-fuzz + leak detector. +*fix up style and disallowed g_assert* usage reported by checkpatch +Signed-off-by: Michael Roth + +(cherry picked from commit cad97c08a1c17830d77a46780088bc0199df89d1) +[ Fix trivial schema conflict ] +Signed-off-by: Marc-André Lureau +Signed-off-by: Miroslav Rezanina +--- + qga/commands-posix-ssh.c | 66 ++++++++++++++++++++++++++++++++++++++++ + qga/qapi-schema.json | 30 ++++++++++++++++++ + 2 files changed, 96 insertions(+) + +diff --git a/qga/commands-posix-ssh.c b/qga/commands-posix-ssh.c +index 362c9e8816..749167e82d 100644 +--- a/qga/commands-posix-ssh.c ++++ b/qga/commands-posix-ssh.c +@@ -268,6 +268,46 @@ qmp_guest_ssh_remove_authorized_keys(const char *username, strList *keys, + write_authkeys(authkeys_path, new_keys, p, errp); + } + ++GuestAuthorizedKeys * ++qmp_guest_ssh_get_authorized_keys(const char *username, Error **errp) ++{ ++ g_autofree struct passwd *p = NULL; ++ g_autofree char *authkeys_path = NULL; ++ g_auto(GStrv) authkeys = NULL; ++ g_autoptr(GuestAuthorizedKeys) ret = NULL; ++ int i; ++ ++ ERRP_GUARD(); ++ ++ p = get_passwd_entry(username, errp); ++ if (p == NULL) { ++ return NULL; ++ } ++ ++ authkeys_path = g_build_filename(p->pw_dir, ".ssh", ++ "authorized_keys", NULL); ++ authkeys = read_authkeys(authkeys_path, errp); ++ if (authkeys == NULL) { ++ return NULL; ++ } ++ ++ ret = g_new0(GuestAuthorizedKeys, 1); ++ for (i = 0; authkeys[i] != NULL; i++) { ++ strList *new; ++ ++ g_strstrip(authkeys[i]); ++ if (!authkeys[i][0] || authkeys[i][0] == '#') { ++ continue; ++ } ++ ++ new = g_new0(strList, 1); ++ new->value = g_strdup(authkeys[i]); ++ new->next = ret->keys; ++ ret->keys = new; ++ } ++ ++ return g_steal_pointer(&ret); ++} + + #ifdef QGA_BUILD_UNIT_TEST + #if GLIB_CHECK_VERSION(2, 60, 0) +@@ -426,6 +466,31 @@ test_remove_keys(void) + "algo some-key another\n"); + } + ++static void ++test_get_keys(void) ++{ ++ Error *err = NULL; ++ static const char *authkeys = ++ "algo key1 comments\n" ++ "# a commented line\n" ++ "algo some-key another\n"; ++ g_autoptr(GuestAuthorizedKeys) ret = NULL; ++ strList *k; ++ size_t len = 0; ++ ++ test_authorized_keys_set(authkeys); ++ ++ ret = qmp_guest_ssh_get_authorized_keys(g_get_user_name(), &err); ++ g_assert(err == NULL); ++ ++ for (len = 0, k = ret->keys; k != NULL; k = k->next) { ++ g_assert(g_str_has_prefix(k->value, "algo ")); ++ len++; ++ } ++ ++ g_assert(len == 2); ++} ++ + int main(int argc, char *argv[]) + { + setlocale(LC_ALL, ""); +@@ -437,6 +502,7 @@ int main(int argc, char *argv[]) + g_test_add_func("/qga/ssh/add_keys", test_add_keys); + g_test_add_func("/qga/ssh/add_reset_keys", test_add_reset_keys); + g_test_add_func("/qga/ssh/remove_keys", test_remove_keys); ++ g_test_add_func("/qga/ssh/get_keys", test_get_keys); + + return g_test_run(); + } +diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json +index a70ea5da77..97bf96712e 100644 +--- a/qga/qapi-schema.json ++++ b/qga/qapi-schema.json +@@ -1274,6 +1274,36 @@ + { 'command': 'guest-get-osinfo', + 'returns': 'GuestOSInfo' } + ++## ++# @GuestAuthorizedKeys: ++# ++# @keys: public keys (in OpenSSH/sshd(8) authorized_keys format) ++# ++# Since: 5.2 ++## ++{ 'struct': 'GuestAuthorizedKeys', ++ 'data': { ++ 'keys': ['str'] ++ }, ++ 'if': 'defined(CONFIG_POSIX)' } ++ ++## ++# @guest-ssh-get-authorized-keys: ++# ++# @username: the user account to add the authorized keys ++# ++# Return the public keys from user .ssh/authorized_keys on Unix systems (not ++# implemented for other systems). ++# ++# Returns: @GuestAuthorizedKeys ++# ++# Since: 5.2 ++## ++{ 'command': 'guest-ssh-get-authorized-keys', ++ 'data': { 'username': 'str' }, ++ 'returns': 'GuestAuthorizedKeys', ++ 'if': 'defined(CONFIG_POSIX)' } ++ + ## + # @guest-ssh-add-authorized-keys: + # +-- +2.27.0 + diff --git a/SOURCES/kvm-rtl8139-switch-to-use-qemu_receive_packet-for-loopba.patch b/SOURCES/kvm-rtl8139-switch-to-use-qemu_receive_packet-for-loopba.patch new file mode 100644 index 0000000..917e3ff --- /dev/null +++ b/SOURCES/kvm-rtl8139-switch-to-use-qemu_receive_packet-for-loopba.patch @@ -0,0 +1,54 @@ +From 4079c4e96f910fe7e57af13feb433f06246f1d79 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 29 Jun 2021 03:42:44 -0400 +Subject: [PATCH 6/9] rtl8139: switch to use qemu_receive_packet() for loopback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +Message-id: <20210629034247.3286477-7-jmaloy@redhat.com> +Patchwork-id: 101792 +O-Subject: [RHEL-8.4.0.z qemu-kvm PATCH v2 6/9] rtl8139: switch to use qemu_receive_packet() for loopback +Bugzilla: 1932917 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth + +From: Alexander Bulekov + +This patch switches to use qemu_receive_packet() which can detect +reentrancy and return early. + +This is intended to address CVE-2021-3416. + +Cc: Prasad J Pandit +Cc: qemu-stable@nongnu.org +Buglink: https://bugs.launchpad.net/qemu/+bug/1910826 +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Jason Wang + +(cherry picked from commit 5311fb805a4403bba024e83886fa0e7572265de4) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + 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 21d80e96cf..ccb04faa4c 100644 +--- a/hw/net/rtl8139.c ++++ b/hw/net/rtl8139.c +@@ -1793,7 +1793,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); +-- +2.27.0 + diff --git a/SOURCES/kvm-softmmu-memory-Log-invalid-memory-accesses.patch b/SOURCES/kvm-softmmu-memory-Log-invalid-memory-accesses.patch new file mode 100644 index 0000000..e4e1bc4 --- /dev/null +++ b/SOURCES/kvm-softmmu-memory-Log-invalid-memory-accesses.patch @@ -0,0 +1,84 @@ +From be0a190e3c5c4ff84f7c53630ed5a55644d18acc Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 21 Apr 2021 22:30:06 -0400 +Subject: [PATCH 7/7] softmmu/memory: Log invalid memory accesses +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +Message-id: <20210421223006.19650-7-jmaloy@redhat.com> +Patchwork-id: 101481 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH v2 6/6] softmmu/memory: Log invalid memory accesses +Bugzilla: 1842478 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laszlo Ersek + +From: Philippe Mathieu-Daudé + +Log invalid memory accesses with as GUEST_ERROR. + +This is particularly useful since commit 5d971f9e67 which reverted +("memory: accept mismatching sizes in memory_region_access_valid"). + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Michael S. Tsirkin +Message-Id: <20201005152725.2143444-1-philmd@redhat.com> +Signed-off-by: Laurent Vivier + +(cherry picked from commit 21786c7e59847b1612406ff394958f22e5b323f8) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + memory.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/memory.c b/memory.c +index 0cfcb72a5a..660df8159a 100644 +--- a/memory.c ++++ b/memory.c +@@ -14,6 +14,7 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/log.h" + #include "qapi/error.h" + #include "cpu.h" + #include "exec/memory.h" +@@ -1353,10 +1354,18 @@ bool memory_region_access_valid(MemoryRegion *mr, + { + if (mr->ops->valid.accepts + && !mr->ops->valid.accepts(mr->opaque, addr, size, is_write, attrs)) { ++ qemu_log_mask(LOG_GUEST_ERROR, "Invalid access at addr " ++ "0x%" HWADDR_PRIX ", size %u, " ++ "region '%s', reason: rejected\n", ++ addr, size, memory_region_name(mr)); + return false; + } + + if (!mr->ops->valid.unaligned && (addr & (size - 1))) { ++ qemu_log_mask(LOG_GUEST_ERROR, "Invalid access at addr " ++ "0x%" HWADDR_PRIX ", size %u, " ++ "region '%s', reason: unaligned\n", ++ addr, size, memory_region_name(mr)); + return false; + } + +@@ -1367,6 +1376,13 @@ bool memory_region_access_valid(MemoryRegion *mr, + + if (size > mr->ops->valid.max_access_size + || size < mr->ops->valid.min_access_size) { ++ qemu_log_mask(LOG_GUEST_ERROR, "Invalid access at addr " ++ "0x%" HWADDR_PRIX ", size %u, " ++ "region '%s', reason: invalid size " ++ "(min:%u max:%u)\n", ++ addr, size, memory_region_name(mr), ++ mr->ops->valid.min_access_size, ++ mr->ops->valid.max_access_size); + return false; + } + return true; +-- +2.27.0 + diff --git a/SOURCES/kvm-spapr-Adjust-firmware-path-of-PCI-devices.patch b/SOURCES/kvm-spapr-Adjust-firmware-path-of-PCI-devices.patch new file mode 100644 index 0000000..7aaa982 --- /dev/null +++ b/SOURCES/kvm-spapr-Adjust-firmware-path-of-PCI-devices.patch @@ -0,0 +1,205 @@ +From dfdf950e893c23e77c9dc0be18fca66ad195d260 Mon Sep 17 00:00:00 2001 +From: Greg Kurz +Date: Wed, 10 Feb 2021 15:56:45 +0000 +Subject: [PATCH 2/2] spapr: Adjust firmware path of PCI devices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Greg Kurz +Message-id: <20210210165645.470195-2-gkurz@redhat.com> +Patchwork-id: 101038 +O-Subject: [RHEL-8.4.0 qemu-kvm PATCH 1/1] spapr: Adjust firmware path of PCI devices +Bugzilla: 1912891 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: David Gibson +RH-Acked-by: Laszlo Ersek + +From: Greg Kurz + +It is currently not possible to perform a strict boot from USB storage: + +$ qemu-system-ppc64 -accel kvm -nodefaults -nographic -serial stdio \ + -boot strict=on \ + -device qemu-xhci \ + -device usb-storage,drive=disk,bootindex=0 \ + -blockdev driver=file,node-name=disk,filename=fedora-ppc64le.qcow2 + +SLOF ********************************************************************** +QEMU Starting + Build Date = Jul 17 2020 11:15:24 + FW Version = git-e18ddad8516ff2cf + Press "s" to enter Open Firmware. + +Populating /vdevice methods +Populating /vdevice/vty@71000000 +Populating /vdevice/nvram@71000001 +Populating /pci@800000020000000 + 00 0000 (D) : 1b36 000d serial bus [ usb-xhci ] +No NVRAM common partition, re-initializing... +Scanning USB + XHCI: Initializing + USB Storage + SCSI: Looking for devices + 101000000000000 DISK : "QEMU QEMU HARDDISK 2.5+" +Using default console: /vdevice/vty@71000000 + + Welcome to Open Firmware + + Copyright (c) 2004, 2017 IBM Corporation All rights reserved. + This program and the accompanying materials are made available + under the terms of the BSD License available at + http://www.opensource.org/licenses/bsd-license.php + +Trying to load: from: /pci@800000020000000/usb@0/storage@1/disk@101000000000000 ... +E3405: No such device + +E3407: Load failed + + Type 'boot' and press return to continue booting the system. + Type 'reset-all' and press return to reboot the system. + +Ready! +0 > + +The device tree handed over by QEMU to SLOF indeed contains: + +qemu,boot-list = + "/pci@800000020000000/usb@0/storage@1/disk@101000000000000 HALT"; + +but the device node is named usb-xhci@0, not usb@0. + +This happens because the firmware names of PCI devices returned +by get_boot_devices_list() come from pcibus_get_fw_dev_path(), +while the sPAPR PHB code uses a different naming scheme for +device nodes. This inconsistency has always been there but it was +hidden for a long time because SLOF used to rename USB device +nodes, until this commit, merged in QEMU 4.2.0 : + +commit 85164ad4ed9960cac842fa4cc067c6b6699b0994 +Author: Alexey Kardashevskiy +Date: Wed Sep 11 16:24:32 2019 +1000 + + pseries: Update SLOF firmware image + + This fixes USB host bus adapter name in the device tree to match QEMU's + one. + + Signed-off-by: Alexey Kardashevskiy + Signed-off-by: David Gibson + +Fortunately, sPAPR implements the firmware path provider interface. +This provides a way to override the default firmware paths. + +Just factor out the sPAPR PHB naming logic from spapr_dt_pci_device() +to a helper, and use it in the sPAPR firmware path provider hook. + +Fixes: 85164ad4ed99 ("pseries: Update SLOF firmware image") +Signed-off-by: Greg Kurz +Message-Id: <20210122170157.246374-1-groug@kaod.org> +Reviewed-by: Daniel Henrique Barboza +Signed-off-by: David Gibson +(cherry picked from commit 040bdafce12f750816d879442014df2999a995c4) +Signed-off-by: Greg Kurz +Signed-off-by: Danilo C. L. de Paula +--- + hw/ppc/spapr.c | 5 +++++ + hw/ppc/spapr_pci.c | 33 ++++++++++++++++++--------------- + include/hw/pci-host/spapr.h | 2 ++ + 3 files changed, 25 insertions(+), 15 deletions(-) + +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index 00b1ef075e..bee2299199 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -3013,6 +3013,7 @@ static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, + SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE); + SpaprPhbState *phb = CAST(SpaprPhbState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE); + VHostSCSICommon *vsc = CAST(VHostSCSICommon, dev, TYPE_VHOST_SCSI_COMMON); ++ PCIDevice *pcidev = CAST(PCIDevice, dev, TYPE_PCI_DEVICE); + + if (d) { + void *spapr = CAST(void, bus->parent, "spapr-vscsi"); +@@ -3086,6 +3087,10 @@ static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, + return g_strdup_printf("pci@%x", PCI_SLOT(pcidev->devfn)); + } + ++ if (pcidev) { ++ return spapr_pci_fw_dev_name(pcidev); ++ } ++ + return NULL; + } + +diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c +index f6fbcf99ed..befa570aa8 100644 +--- a/hw/ppc/spapr_pci.c ++++ b/hw/ppc/spapr_pci.c +@@ -1348,15 +1348,29 @@ static int spapr_dt_pci_bus(SpaprPhbState *sphb, PCIBus *bus, + return offset; + } + ++char *spapr_pci_fw_dev_name(PCIDevice *dev) ++{ ++ const gchar *basename; ++ int slot = PCI_SLOT(dev->devfn); ++ int func = PCI_FUNC(dev->devfn); ++ uint32_t ccode = pci_default_read_config(dev, PCI_CLASS_PROG, 3); ++ ++ basename = dt_name_from_class((ccode >> 16) & 0xff, (ccode >> 8) & 0xff, ++ ccode & 0xff); ++ ++ if (func != 0) { ++ return g_strdup_printf("%s@%x,%x", basename, slot, func); ++ } else { ++ return g_strdup_printf("%s@%x", basename, slot); ++ } ++} ++ + /* create OF node for pci device and required OF DT properties */ + static int spapr_dt_pci_device(SpaprPhbState *sphb, PCIDevice *dev, + void *fdt, int parent_offset) + { + int offset; +- const gchar *basename; +- gchar *nodename; +- int slot = PCI_SLOT(dev->devfn); +- int func = PCI_FUNC(dev->devfn); ++ g_autofree gchar *nodename = spapr_pci_fw_dev_name(dev); + PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); + ResourceProps rp; + SpaprDrc *drc = drc_from_dev(sphb, dev); +@@ -1373,19 +1387,8 @@ static int spapr_dt_pci_device(SpaprPhbState *sphb, PCIDevice *dev, + uint32_t pci_status = pci_default_read_config(dev, PCI_STATUS, 2); + gchar *loc_code; + +- basename = dt_name_from_class((ccode >> 16) & 0xff, (ccode >> 8) & 0xff, +- ccode & 0xff); +- +- if (func != 0) { +- nodename = g_strdup_printf("%s@%x,%x", basename, slot, func); +- } else { +- nodename = g_strdup_printf("%s@%x", basename, slot); +- } +- + _FDT(offset = fdt_add_subnode(fdt, parent_offset, nodename)); + +- g_free(nodename); +- + /* in accordance with PAPR+ v2.7 13.6.3, Table 181 */ + _FDT(fdt_setprop_cell(fdt, offset, "vendor-id", vendor_id)); + _FDT(fdt_setprop_cell(fdt, offset, "device-id", device_id)); +diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h +index 8877ff51fb..9522db9047 100644 +--- a/include/hw/pci-host/spapr.h ++++ b/include/hw/pci-host/spapr.h +@@ -212,4 +212,6 @@ static inline unsigned spapr_phb_windows_supported(SpaprPhbState *sphb) + return sphb->ddw_enabled ? SPAPR_PCI_DMA_MAX_WINDOWS : 1; + } + ++char *spapr_pci_fw_dev_name(PCIDevice *dev); ++ + #endif /* PCI_HOST_SPAPR_H */ +-- +2.27.0 + diff --git a/SOURCES/kvm-spapr-Fix-EEH-capability-issue-on-KVM-guest-for-PCI-.patch b/SOURCES/kvm-spapr-Fix-EEH-capability-issue-on-KVM-guest-for-PCI-.patch new file mode 100644 index 0000000..8d30406 --- /dev/null +++ b/SOURCES/kvm-spapr-Fix-EEH-capability-issue-on-KVM-guest-for-PCI-.patch @@ -0,0 +1,165 @@ +From f9d332b1280cd3f6009b59323719548a36a7c52b Mon Sep 17 00:00:00 2001 +From: Daniel Henrique Barboza +Date: Mon, 21 Jun 2021 14:40:24 -0400 +Subject: [PATCH 2/4] spapr: Fix EEH capability issue on KVM guest for PCI + passthru + +RH-Author: Daniel Henrique Barboza +Message-id: <20210621144024.199732-2-dbarboza@redhat.com> +Patchwork-id: 101740 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 1/1] spapr: Fix EEH capability issue on KVM guest for PCI passthru +Bugzilla: 1957866 +RH-Acked-by: Laurent Vivier +RH-Acked-by: Greg Kurz +RH-Acked-by: David Gibson + +From: Mahesh Salgaonkar + +With upstream kernel, especially after commit 98ba956f6a389 +("powerpc/pseries/eeh: Rework device EEH PE determination") we see that KVM +guest isn't able to enable EEH option for PCI pass-through devices anymore. + +[root@atest-guest ~]# dmesg | grep EEH +[ 0.032337] EEH: pSeries platform initialized +[ 0.298207] EEH: No capable adapters found: recovery disabled. +[root@atest-guest ~]# + +So far the linux kernel was assuming pe_config_addr equal to device's +config_addr and using it to enable EEH on the PE through ibm,set-eeh-option +RTAS call. Which wasn't the correct way as per PAPR. The linux kernel +commit 98ba956f6a389 fixed this flow. With that fixed, linux now uses PE +config address returned by ibm,get-config-addr-info2 RTAS call to enable +EEH option per-PE basis instead of per-device basis. However this has +uncovered a bug in qemu where ibm,set-eeh-option is treating PE config +address as per-device config address. + +Hence in qemu guest with recent kernel the ibm,set-eeh-option RTAS call +fails with -3 return value indicating that there is no PCI device exist for +the specified PE config address. The rtas_ibm_set_eeh_option call uses +pci_find_device() to get the PC device that matches specific bus and devfn +extracted from PE config address passed as argument. Thus it tries to map +the PE config address to a single specific PCI device 'bus->devices[devfn]' +which always results into checking device on slot 0 'bus->devices[0]'. +This succeeds when there is a pass-through device (vfio-pci) present on +slot 0. But in cases where there is no pass-through device present in slot +0, but present in non-zero slots, ibm,set-eeh-option call fails to enable +the EEH capability. + +hw/ppc/spapr_pci_vfio.c: spapr_phb_vfio_eeh_set_option() + case RTAS_EEH_ENABLE: { + PCIHostState *phb; + PCIDevice *pdev; + + /* + * The EEH functionality is enabled on basis of PCI device, + * instead of PE. We need check the validity of the PCI + * device address. + */ + phb = PCI_HOST_BRIDGE(sphb); + pdev = pci_find_device(phb->bus, + (addr >> 16) & 0xFF, (addr >> 8) & 0xFF); + if (!pdev || !object_dynamic_cast(OBJECT(pdev), "vfio-pci")) { + return RTAS_OUT_PARAM_ERROR; + } + +hw/pci/pci.c:pci_find_device() + +PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn) +{ + bus = pci_find_bus_nr(bus, bus_num); + + if (!bus) + return NULL; + + return bus->devices[devfn]; +} + +This patch fixes ibm,set-eeh-option to check for presence of any PCI device +(vfio-pci) under specified bus and enable the EEH if found. The current +code already makes sure that all the devices on that bus are from same +iommu group (within same PE) and fail very early if it does not. + +After this fix guest is able to find EEH capable devices and enable EEH +recovery on it. + +[root@atest-guest ~]# dmesg | grep EEH +[ 0.048139] EEH: pSeries platform initialized +[ 0.405115] EEH: Capable adapter found: recovery enabled. +[root@atest-guest ~]# + +Reviewed-by: Daniel Henrique Barboza +Signed-off-by: Mahesh Salgaonkar +Message-Id: <162158429107.145117.5843504911924013125.stgit@jupiter> +Signed-off-by: David Gibson +(cherry picked from commit ac9ef668321ebb6eb871a0c4dd380fa7d7891b4e) +Signed-off-by: Daniel Henrique Barboza +Signed-off-by: Danilo C. L. de Paula +--- + hw/ppc/spapr_pci_vfio.c | 40 +++++++++++++++++++++++++++++++++------- + 1 file changed, 33 insertions(+), 7 deletions(-) + +diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c +index ecb34aaade..a411b08d60 100644 +--- a/hw/ppc/spapr_pci_vfio.c ++++ b/hw/ppc/spapr_pci_vfio.c +@@ -48,6 +48,16 @@ void spapr_phb_vfio_reset(DeviceState *qdev) + spapr_phb_vfio_eeh_reenable(SPAPR_PCI_HOST_BRIDGE(qdev)); + } + ++static void spapr_eeh_pci_find_device(PCIBus *bus, PCIDevice *pdev, ++ void *opaque) ++{ ++ bool *found = opaque; ++ ++ if (object_dynamic_cast(OBJECT(pdev), "vfio-pci")) { ++ *found = true; ++ } ++} ++ + int spapr_phb_vfio_eeh_set_option(SpaprPhbState *sphb, + unsigned int addr, int option) + { +@@ -60,17 +70,33 @@ int spapr_phb_vfio_eeh_set_option(SpaprPhbState *sphb, + break; + case RTAS_EEH_ENABLE: { + PCIHostState *phb; +- PCIDevice *pdev; ++ bool found = false; + + /* +- * The EEH functionality is enabled on basis of PCI device, +- * instead of PE. We need check the validity of the PCI +- * device address. ++ * The EEH functionality is enabled per sphb level instead of ++ * per PCI device. We have already identified this specific sphb ++ * based on buid passed as argument to ibm,set-eeh-option rtas ++ * call. Now we just need to check the validity of the PCI ++ * pass-through devices (vfio-pci) under this sphb bus. ++ * We have already validated that all the devices under this sphb ++ * are from same iommu group (within same PE) before comming here. ++ * ++ * Prior to linux commit 98ba956f6a389 ("powerpc/pseries/eeh: ++ * Rework device EEH PE determination") kernel would call ++ * eeh-set-option for each device in the PE using the device's ++ * config_address as the argument rather than the PE address. ++ * Hence if we check validity of supplied config_addr whether ++ * it matches to this PHB will cause issues with older kernel ++ * versions v5.9 and older. If we return an error from ++ * eeh-set-option when the argument isn't a valid PE address ++ * then older kernels (v5.9 and older) will interpret that as ++ * EEH not being supported. + */ + phb = PCI_HOST_BRIDGE(sphb); +- pdev = pci_find_device(phb->bus, +- (addr >> 16) & 0xFF, (addr >> 8) & 0xFF); +- if (!pdev || !object_dynamic_cast(OBJECT(pdev), "vfio-pci")) { ++ pci_for_each_device(phb->bus, (addr >> 16) & 0xFF, ++ spapr_eeh_pci_find_device, &found); ++ ++ if (!found) { + return RTAS_OUT_PARAM_ERROR; + } + +-- +2.27.0 + diff --git a/SOURCES/kvm-spapr-Remove-stale-comment-about-power-saving-LPCR-b.patch b/SOURCES/kvm-spapr-Remove-stale-comment-about-power-saving-LPCR-b.patch new file mode 100644 index 0000000..4f15509 --- /dev/null +++ b/SOURCES/kvm-spapr-Remove-stale-comment-about-power-saving-LPCR-b.patch @@ -0,0 +1,50 @@ +From b46fdf56b1a7938468565838bdadf260870e4f9b Mon Sep 17 00:00:00 2001 +From: Laurent Vivier +Date: Wed, 9 Jun 2021 10:05:00 -0400 +Subject: [PATCH 3/4] spapr: Remove stale comment about power-saving LPCR bits +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Laurent Vivier +Message-id: <20210609100501.427096-2-lvivier@redhat.com> +Patchwork-id: 101682 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 1/2] spapr: Remove stale comment about power-saving LPCR bits +Bugzilla: 1969768 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: David Gibson +RH-Acked-by: Greg Kurz + +From: Nicholas Piggin + +Commit 47a9b551547 ("spapr: Clean up handling of LPCR power-saving exit +bits") moved this logic but did not remove the comment from the +previous location. + +Signed-off-by: Nicholas Piggin +Message-Id: <20210526091626.3388262-2-npiggin@gmail.com> +Reviewed-by: Cédric Le Goater +Reviewed-by: Greg Kurz +Signed-off-by: David Gibson +(cherry picked from commit 7be3bf6c8429969f97728bb712d9a99997835607) +Signed-off-by: Laurent Vivier +Signed-off-by: Danilo C. L. de Paula +--- + hw/ppc/spapr_rtas.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c +index 8d8d8cdfcb..295eac986e 100644 +--- a/hw/ppc/spapr_rtas.c ++++ b/hw/ppc/spapr_rtas.c +@@ -163,7 +163,6 @@ static void rtas_start_cpu(PowerPCCPU *callcpu, SpaprMachineState *spapr, + + env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME); + +- /* Enable Power-saving mode Exit Cause exceptions for the new CPU */ + lpcr = env->spr[SPR_LPCR]; + if (!pcc->interrupts_big_endian(callcpu)) { + lpcr |= LPCR_ILE; +-- +2.27.0 + diff --git a/SOURCES/kvm-spapr-Set-LPCR-to-current-AIL-mode-when-starting-a-n.patch b/SOURCES/kvm-spapr-Set-LPCR-to-current-AIL-mode-when-starting-a-n.patch new file mode 100644 index 0000000..84abc74 --- /dev/null +++ b/SOURCES/kvm-spapr-Set-LPCR-to-current-AIL-mode-when-starting-a-n.patch @@ -0,0 +1,89 @@ +From 28794dca79a94d01c8732b84fe6ac6ba2986ce45 Mon Sep 17 00:00:00 2001 +From: Laurent Vivier +Date: Wed, 9 Jun 2021 10:05:01 -0400 +Subject: [PATCH 4/4] spapr: Set LPCR to current AIL mode when starting a new + CPU +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Laurent Vivier +Message-id: <20210609100501.427096-3-lvivier@redhat.com> +Patchwork-id: 101683 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 2/2] spapr: Set LPCR to current AIL mode when starting a new CPU +Bugzilla: 1969768 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: David Gibson +RH-Acked-by: Greg Kurz + +From: Nicholas Piggin + +TCG does not keep track of AIL mode in a central place, it's based on +the current LPCR[AIL] bits. Synchronize the new CPU's LPCR to the +current LPCR in rtas_start_cpu(), similarly to the way the ILE bit is +synchronized. + +Open-code the ILE setting as well now that the caller's LPCR is +available directly, there is no need for the indirection. + +Without this, under both TCG and KVM, adding a POWER8/9/10 class CPU +with a new core ID after a modern Linux has booted results in the new +CPU's LPCR missing the LPCR[AIL]=0b11 setting that the other CPUs have. +This can cause crashes and unexpected behaviour. + +Signed-off-by: Nicholas Piggin +Message-Id: <20210526091626.3388262-3-npiggin@gmail.com> +Reviewed-by: Cédric Le Goater +Reviewed-by: Greg Kurz +Signed-off-by: David Gibson +(cherry picked from commit ac559ecbea2649819e7b3fdd09f4e0243e0128db) +Signed-off-by: Laurent Vivier +Signed-off-by: Danilo C. L. de Paula +--- + hw/ppc/spapr_rtas.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c +index 295eac986e..5acb7c1f10 100644 +--- a/hw/ppc/spapr_rtas.c ++++ b/hw/ppc/spapr_rtas.c +@@ -132,8 +132,8 @@ static void rtas_start_cpu(PowerPCCPU *callcpu, SpaprMachineState *spapr, + target_ulong id, start, r3; + PowerPCCPU *newcpu; + CPUPPCState *env; +- PowerPCCPUClass *pcc; + target_ulong lpcr; ++ target_ulong caller_lpcr; + + if (nargs != 3 || nret != 1) { + rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); +@@ -152,7 +152,6 @@ static void rtas_start_cpu(PowerPCCPU *callcpu, SpaprMachineState *spapr, + } + + env = &newcpu->env; +- pcc = POWERPC_CPU_GET_CLASS(newcpu); + + if (!CPU(newcpu)->halted) { + rtas_st(rets, 0, RTAS_OUT_HW_ERROR); +@@ -163,10 +162,15 @@ static void rtas_start_cpu(PowerPCCPU *callcpu, SpaprMachineState *spapr, + + env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME); + ++ caller_lpcr = callcpu->env.spr[SPR_LPCR]; + lpcr = env->spr[SPR_LPCR]; +- if (!pcc->interrupts_big_endian(callcpu)) { +- lpcr |= LPCR_ILE; +- } ++ ++ /* Set ILE the same way */ ++ lpcr = (lpcr & ~LPCR_ILE) | (caller_lpcr & LPCR_ILE); ++ ++ /* Set AIL the same way */ ++ lpcr = (lpcr & ~LPCR_AIL) | (caller_lpcr & LPCR_AIL); ++ + if (env->mmu_model == POWERPC_MMU_3_00) { + /* + * New cpus are expected to start in the same radix/hash mode +-- +2.27.0 + diff --git a/SOURCES/kvm-sungem-switch-to-use-qemu_receive_packet-for-loopbac.patch b/SOURCES/kvm-sungem-switch-to-use-qemu_receive_packet-for-loopbac.patch new file mode 100644 index 0000000..e8c9f8b --- /dev/null +++ b/SOURCES/kvm-sungem-switch-to-use-qemu_receive_packet-for-loopbac.patch @@ -0,0 +1,54 @@ +From 07df0f52c26a3819bc02b4f2970b6735bcf15c5b Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 29 Jun 2021 03:42:42 -0400 +Subject: [PATCH 4/9] sungem: switch to use qemu_receive_packet() for loopback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +Message-id: <20210629034247.3286477-5-jmaloy@redhat.com> +Patchwork-id: 101786 +O-Subject: [RHEL-8.4.0.z qemu-kvm PATCH v2 4/9] sungem: switch to use qemu_receive_packet() for loopback +Bugzilla: 1932917 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth + +From: Jason Wang + +This patch switches to use qemu_receive_packet() which can detect +reentrancy and return early. + +This is intended to address CVE-2021-3416. + +Cc: Prasad J Pandit +Cc: qemu-stable@nongnu.org +Reviewed-by: Mark Cave-Ayland +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Alistair Francis +Signed-off-by: Jason Wang + +(cherry picked from commit 8c92060d3c0248bd4d515719a35922cd2391b9b4) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + 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 f31d41ac5b..8b202b5c15 100644 +--- a/hw/net/sungem.c ++++ b/hw/net/sungem.c +@@ -305,7 +305,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); + } +-- +2.27.0 + diff --git a/SOURCES/kvm-target-i386-add-fast-short-REP-MOV-support.patch b/SOURCES/kvm-target-i386-add-fast-short-REP-MOV-support.patch new file mode 100644 index 0000000..51af7e7 --- /dev/null +++ b/SOURCES/kvm-target-i386-add-fast-short-REP-MOV-support.patch @@ -0,0 +1,59 @@ +From f33880c5f7a4e2cad25c22112da073273c6e2cfb Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Wed, 24 Feb 2021 11:30:35 -0500 +Subject: [PATCH 2/4] target/i386: add fast short REP MOV support + +RH-Author: Dr. David Alan Gilbert +Message-id: <20210224113037.15599-3-dgilbert@redhat.com> +Patchwork-id: 101201 +O-Subject: [RHEL-8.4.0 qemu-kvm PATCH 2/4] target/i386: add fast short REP MOV support +Bugzilla: 1790620 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: Peter Xu + +From: Chenyi Qiang + +For CPUs support fast short REP MOV[CPUID.(EAX=7,ECX=0):EDX(bit4)], e.g +Icelake and Tigerlake, expose it to the guest VM. + +Reviewed-by: Eduardo Habkost +Signed-off-by: Chenyi Qiang +Message-Id: <20200714084148.26690-2-chenyi.qiang@intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 5cb287d2bd578dfe4897458793b4fce35bc4f744) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + target/i386/cpu.h | 2 ++ + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 67dab94aa5..f6a9ed84b3 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1077,7 +1077,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + .type = CPUID_FEATURE_WORD, + .feat_names = { + NULL, NULL, "avx512-4vnniw", "avx512-4fmaps", +- NULL, NULL, NULL, NULL, ++ "fsrm", NULL, NULL, NULL, + "avx512-vp2intersect", NULL, "md-clear", NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL /* pconfig */, NULL, +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 8e2e52ed31..f5a4efcec6 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -770,6 +770,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) + /* AVX512 Multiply Accumulation Single Precision */ + #define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) ++/* Fast Short Rep Mov */ ++#define CPUID_7_0_EDX_FSRM (1U << 4) + /* AVX512 Vector Pair Intersection to a Pair of Mask Registers */ + #define CPUID_7_0_EDX_AVX512_VP2INTERSECT (1U << 8) + /* Speculation Control */ +-- +2.27.0 + diff --git a/SOURCES/kvm-tftp-check-tftp_input-buffer-size.patch b/SOURCES/kvm-tftp-check-tftp_input-buffer-size.patch new file mode 100644 index 0000000..85ed811 --- /dev/null +++ b/SOURCES/kvm-tftp-check-tftp_input-buffer-size.patch @@ -0,0 +1,53 @@ +From 6bd4d80f9274f76eb402ce85aa60729150b39980 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Thu, 29 Jul 2021 04:56:34 -0400 +Subject: [PATCH 09/14] tftp: check tftp_input buffer size +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Marc-André Lureau +Message-id: <20210708082537.1550263-6-marcandre.lureau@redhat.com> +Patchwork-id: 101823 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 5/8] tftp: check tftp_input buffer size +Bugzilla: 1970843 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Eric Blake +RH-Acked-by: Stefan Hajnoczi + +From: Marc-André Lureau + +Fixes: CVE-2021-3595 +Fixes: https://gitlab.freedesktop.org/slirp/libslirp/-/issues/46 + +Signed-off-by: Marc-André Lureau + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1970843 + +(cherry picked from commit 3f17948137155f025f7809fdc38576d5d2451c3d) +Signed-off-by: Marc-André Lureau +Signed-off-by: Miroslav Rezanina +--- + slirp/src/tftp.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/slirp/src/tftp.c b/slirp/src/tftp.c +index 093c2e06a3..07e8f3cb2f 100644 +--- a/slirp/src/tftp.c ++++ b/slirp/src/tftp.c +@@ -444,7 +444,11 @@ static void tftp_handle_error(Slirp *slirp, struct sockaddr_storage *srcsas, + + void tftp_input(struct sockaddr_storage *srcsas, struct mbuf *m) + { +- struct tftp_t *tp = (struct tftp_t *)m->m_data; ++ struct tftp_t *tp = mtod_check(m, offsetof(struct tftp_t, x.tp_buf)); ++ ++ if (tp == NULL) { ++ return; ++ } + + switch (ntohs(tp->tp_op)) { + case TFTP_RRQ: +-- +2.27.0 + diff --git a/SOURCES/kvm-tftp-introduce-a-header-structure.patch b/SOURCES/kvm-tftp-introduce-a-header-structure.patch new file mode 100644 index 0000000..d8c8ddb --- /dev/null +++ b/SOURCES/kvm-tftp-introduce-a-header-structure.patch @@ -0,0 +1,263 @@ +From af72e344459614fcf2746739f05494ef7e691a78 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Thu, 29 Jul 2021 04:56:36 -0400 +Subject: [PATCH 10/14] tftp: introduce a header structure +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Marc-André Lureau +Message-id: <20210708082537.1550263-7-marcandre.lureau@redhat.com> +Patchwork-id: 101825 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 6/8] tftp: introduce a header structure +Bugzilla: 1970819 1970835 1970843 1970853 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Eric Blake +RH-Acked-by: Stefan Hajnoczi + +From: Marc-André Lureau + +Instead of using a composed structure and potentially reading past the +incoming buffer, use a different structure for the header. + +Signed-off-by: Marc-André Lureau + +(cherry picked from commit 990163cf3ac86b7875559f49602c4d76f46f6f30) +Signed-off-by: Marc-André Lureau +Signed-off-by: Miroslav Rezanina +--- + slirp/src/tftp.c | 58 +++++++++++++++++++++++++----------------------- + slirp/src/tftp.h | 6 ++++- + 2 files changed, 35 insertions(+), 29 deletions(-) + +diff --git a/slirp/src/tftp.c b/slirp/src/tftp.c +index 07e8f3cb2f..53e04d0aeb 100644 +--- a/slirp/src/tftp.c ++++ b/slirp/src/tftp.c +@@ -50,7 +50,7 @@ static void tftp_session_terminate(struct tftp_session *spt) + } + + static int tftp_session_allocate(Slirp *slirp, struct sockaddr_storage *srcsas, +- struct tftp_t *tp) ++ struct tftphdr *hdr) + { + struct tftp_session *spt; + int k; +@@ -75,7 +75,7 @@ found: + memcpy(&spt->client_addr, srcsas, sockaddr_size(srcsas)); + spt->fd = -1; + spt->block_size = 512; +- spt->client_port = tp->udp.uh_sport; ++ spt->client_port = hdr->udp.uh_sport; + spt->slirp = slirp; + + tftp_session_update(spt); +@@ -84,7 +84,7 @@ found: + } + + static int tftp_session_find(Slirp *slirp, struct sockaddr_storage *srcsas, +- struct tftp_t *tp) ++ struct tftphdr *hdr) + { + struct tftp_session *spt; + int k; +@@ -94,7 +94,7 @@ static int tftp_session_find(Slirp *slirp, struct sockaddr_storage *srcsas, + + if (tftp_session_in_use(spt)) { + if (sockaddr_equal(&spt->client_addr, srcsas)) { +- if (spt->client_port == tp->udp.uh_sport) { ++ if (spt->client_port == hdr->udp.uh_sport) { + return k; + } + } +@@ -146,13 +146,13 @@ static struct tftp_t *tftp_prep_mbuf_data(struct tftp_session *spt, + } + + static void tftp_udp_output(struct tftp_session *spt, struct mbuf *m, +- struct tftp_t *recv_tp) ++ struct tftphdr *hdr) + { + if (spt->client_addr.ss_family == AF_INET6) { + struct sockaddr_in6 sa6, da6; + + sa6.sin6_addr = spt->slirp->vhost_addr6; +- sa6.sin6_port = recv_tp->udp.uh_dport; ++ sa6.sin6_port = hdr->udp.uh_dport; + da6.sin6_addr = ((struct sockaddr_in6 *)&spt->client_addr)->sin6_addr; + da6.sin6_port = spt->client_port; + +@@ -161,7 +161,7 @@ static void tftp_udp_output(struct tftp_session *spt, struct mbuf *m, + struct sockaddr_in sa4, da4; + + sa4.sin_addr = spt->slirp->vhost_addr; +- sa4.sin_port = recv_tp->udp.uh_dport; ++ sa4.sin_port = hdr->udp.uh_dport; + da4.sin_addr = ((struct sockaddr_in *)&spt->client_addr)->sin_addr; + da4.sin_port = spt->client_port; + +@@ -183,7 +183,7 @@ static int tftp_send_oack(struct tftp_session *spt, const char *keys[], + + tp = tftp_prep_mbuf_data(spt, m); + +- tp->tp_op = htons(TFTP_OACK); ++ tp->hdr.tp_op = htons(TFTP_OACK); + for (i = 0; i < nb; i++) { + n += snprintf(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%s", + keys[i]) + +@@ -195,7 +195,7 @@ static int tftp_send_oack(struct tftp_session *spt, const char *keys[], + + m->m_len = sizeof(struct tftp_t) - (TFTP_BLOCKSIZE_MAX + 2) + n - + sizeof(struct udphdr); +- tftp_udp_output(spt, m, recv_tp); ++ tftp_udp_output(spt, m, &recv_tp->hdr); + + return 0; + } +@@ -216,21 +216,21 @@ static void tftp_send_error(struct tftp_session *spt, uint16_t errorcode, + + tp = tftp_prep_mbuf_data(spt, m); + +- tp->tp_op = htons(TFTP_ERROR); ++ tp->hdr.tp_op = htons(TFTP_ERROR); + tp->x.tp_error.tp_error_code = htons(errorcode); + slirp_pstrcpy((char *)tp->x.tp_error.tp_msg, sizeof(tp->x.tp_error.tp_msg), + msg); + + m->m_len = sizeof(struct tftp_t) - (TFTP_BLOCKSIZE_MAX + 2) + 3 + + strlen(msg) - sizeof(struct udphdr); +- tftp_udp_output(spt, m, recv_tp); ++ tftp_udp_output(spt, m, &recv_tp->hdr); + + out: + tftp_session_terminate(spt); + } + + static void tftp_send_next_block(struct tftp_session *spt, +- struct tftp_t *recv_tp) ++ struct tftphdr *hdr) + { + struct mbuf *m; + struct tftp_t *tp; +@@ -244,7 +244,7 @@ static void tftp_send_next_block(struct tftp_session *spt, + + tp = tftp_prep_mbuf_data(spt, m); + +- tp->tp_op = htons(TFTP_DATA); ++ tp->hdr.tp_op = htons(TFTP_DATA); + tp->x.tp_data.tp_block_nr = htons((spt->block_nr + 1) & 0xffff); + + nobytes = tftp_read_data(spt, spt->block_nr, tp->x.tp_data.tp_buf, +@@ -262,7 +262,7 @@ static void tftp_send_next_block(struct tftp_session *spt, + + m->m_len = sizeof(struct tftp_t) - (TFTP_BLOCKSIZE_MAX - nobytes) - + sizeof(struct udphdr); +- tftp_udp_output(spt, m, recv_tp); ++ tftp_udp_output(spt, m, hdr); + + if (nobytes == spt->block_size) { + tftp_session_update(spt); +@@ -285,12 +285,12 @@ static void tftp_handle_rrq(Slirp *slirp, struct sockaddr_storage *srcsas, + int nb_options = 0; + + /* check if a session already exists and if so terminate it */ +- s = tftp_session_find(slirp, srcsas, tp); ++ s = tftp_session_find(slirp, srcsas, &tp->hdr); + if (s >= 0) { + tftp_session_terminate(&slirp->tftp_sessions[s]); + } + +- s = tftp_session_allocate(slirp, srcsas, tp); ++ s = tftp_session_allocate(slirp, srcsas, &tp->hdr); + + if (s < 0) { + return; +@@ -411,29 +411,29 @@ static void tftp_handle_rrq(Slirp *slirp, struct sockaddr_storage *srcsas, + } + + spt->block_nr = 0; +- tftp_send_next_block(spt, tp); ++ tftp_send_next_block(spt, &tp->hdr); + } + + static void tftp_handle_ack(Slirp *slirp, struct sockaddr_storage *srcsas, +- struct tftp_t *tp, int pktlen) ++ struct tftphdr *hdr) + { + int s; + +- s = tftp_session_find(slirp, srcsas, tp); ++ s = tftp_session_find(slirp, srcsas, hdr); + + if (s < 0) { + return; + } + +- tftp_send_next_block(&slirp->tftp_sessions[s], tp); ++ tftp_send_next_block(&slirp->tftp_sessions[s], hdr); + } + + static void tftp_handle_error(Slirp *slirp, struct sockaddr_storage *srcsas, +- struct tftp_t *tp, int pktlen) ++ struct tftphdr *hdr) + { + int s; + +- s = tftp_session_find(slirp, srcsas, tp); ++ s = tftp_session_find(slirp, srcsas, hdr); + + if (s < 0) { + return; +@@ -444,23 +444,25 @@ static void tftp_handle_error(Slirp *slirp, struct sockaddr_storage *srcsas, + + void tftp_input(struct sockaddr_storage *srcsas, struct mbuf *m) + { +- struct tftp_t *tp = mtod_check(m, offsetof(struct tftp_t, x.tp_buf)); ++ struct tftphdr *hdr = mtod_check(m, sizeof(struct tftphdr)); + +- if (tp == NULL) { ++ if (hdr == NULL) { + return; + } + +- switch (ntohs(tp->tp_op)) { ++ switch (ntohs(hdr->tp_op)) { + case TFTP_RRQ: +- tftp_handle_rrq(m->slirp, srcsas, tp, m->m_len); ++ tftp_handle_rrq(m->slirp, srcsas, ++ mtod(m, struct tftp_t *), ++ m->m_len); + break; + + case TFTP_ACK: +- tftp_handle_ack(m->slirp, srcsas, tp, m->m_len); ++ tftp_handle_ack(m->slirp, srcsas, hdr); + break; + + case TFTP_ERROR: +- tftp_handle_error(m->slirp, srcsas, tp, m->m_len); ++ tftp_handle_error(m->slirp, srcsas, hdr); + break; + } + } +diff --git a/slirp/src/tftp.h b/slirp/src/tftp.h +index c47bb43c7d..021f6cf109 100644 +--- a/slirp/src/tftp.h ++++ b/slirp/src/tftp.h +@@ -18,9 +18,13 @@ + #define TFTP_FILENAME_MAX 512 + #define TFTP_BLOCKSIZE_MAX 1428 + +-struct tftp_t { ++struct tftphdr { + struct udphdr udp; + uint16_t tp_op; ++} SLIRP_PACKED; ++ ++struct tftp_t { ++ struct tftphdr hdr; + union { + struct { + uint16_t tp_block_nr; +-- +2.27.0 + diff --git a/SOURCES/kvm-tx_pkt-switch-to-use-qemu_receive_packet_iov-for-loo.patch b/SOURCES/kvm-tx_pkt-switch-to-use-qemu_receive_packet_iov-for-loo.patch new file mode 100644 index 0000000..4da71cc --- /dev/null +++ b/SOURCES/kvm-tx_pkt-switch-to-use-qemu_receive_packet_iov-for-loo.patch @@ -0,0 +1,53 @@ +From 87cacc268f37758553ad93fefa8b312ed0bd2520 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 29 Jun 2021 03:42:43 -0400 +Subject: [PATCH 5/9] 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 + +RH-Author: Jon Maloy +Message-id: <20210629034247.3286477-6-jmaloy@redhat.com> +Patchwork-id: 101788 +O-Subject: [RHEL-8.4.0.z qemu-kvm PATCH v2 5/9] tx_pkt: switch to use qemu_receive_packet_iov() for loopback +Bugzilla: 1932917 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth + +From: Jason Wang + +This patch switches to use qemu_receive_receive_iov() which can detect +reentrancy and return early. + +This is intended to address CVE-2021-3416. + +Cc: Prasad J Pandit +Cc: qemu-stable@nongnu.org +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Jason Wang + +(cherry picked from commit 8c552542b81e56ff532dd27ec6e5328954bdda73) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + 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 54d4c3bbd0..646cdfaf4d 100644 +--- a/hw/net/net_tx_pkt.c ++++ b/hw/net/net_tx_pkt.c +@@ -544,7 +544,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); + } +-- +2.27.0 + diff --git a/SOURCES/kvm-udp-check-upd_input-buffer-size.patch b/SOURCES/kvm-udp-check-upd_input-buffer-size.patch new file mode 100644 index 0000000..0f3c6f3 --- /dev/null +++ b/SOURCES/kvm-udp-check-upd_input-buffer-size.patch @@ -0,0 +1,52 @@ +From 1b8aa33b218a8ff3e8aa2f1b6875df40fd70f0ed Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Thu, 29 Jul 2021 04:56:40 -0400 +Subject: [PATCH 11/14] udp: check upd_input buffer size +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Marc-André Lureau +Message-id: <20210708082537.1550263-8-marcandre.lureau@redhat.com> +Patchwork-id: 101826 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 7/8] udp: check upd_input buffer size +Bugzilla: 1970853 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Eric Blake +RH-Acked-by: Stefan Hajnoczi + +From: Marc-André Lureau + +Fixes: CVE-2021-3594 +Fixes: https://gitlab.freedesktop.org/slirp/libslirp/-/issues/47 + +Signed-off-by: Marc-André Lureau + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1970853 + +(cherry picked from commit 74572be49247c8c5feae7c6e0b50c4f569ca9824) +Signed-off-by: Marc-André Lureau +Signed-off-by: Miroslav Rezanina +--- + slirp/src/udp.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/slirp/src/udp.c b/slirp/src/udp.c +index ae23ba4b2a..86142bba14 100644 +--- a/slirp/src/udp.c ++++ b/slirp/src/udp.c +@@ -90,7 +90,10 @@ void udp_input(register struct mbuf *m, int iphlen) + /* + * Get IP and UDP header together in first mbuf. + */ +- ip = mtod(m, struct ip *); ++ ip = mtod_check(m, iphlen + sizeof(struct udphdr)); ++ if (ip == NULL) { ++ goto bad; ++ } + uh = (struct udphdr *)((char *)ip + iphlen); + + /* +-- +2.27.0 + diff --git a/SOURCES/kvm-upd6-check-udp6_input-buffer-size.patch b/SOURCES/kvm-upd6-check-udp6_input-buffer-size.patch new file mode 100644 index 0000000..2aa3a24 --- /dev/null +++ b/SOURCES/kvm-upd6-check-udp6_input-buffer-size.patch @@ -0,0 +1,52 @@ +From 6808086932ddc83fd748c46fea495e7004299b55 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Thu, 29 Jul 2021 04:56:31 -0400 +Subject: [PATCH 08/14] upd6: check udp6_input buffer size +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Marc-André Lureau +Message-id: <20210708082537.1550263-5-marcandre.lureau@redhat.com> +Patchwork-id: 101822 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 4/8] upd6: check udp6_input buffer size +Bugzilla: 1970835 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Eric Blake +RH-Acked-by: Stefan Hajnoczi + +From: Marc-André Lureau + +Fixes: CVE-2021-3593 +Fixes: https://gitlab.freedesktop.org/slirp/libslirp/-/issues/45 + +Signed-off-by: Marc-André Lureau + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1970835 + +(cherry picked from commit de71c15de66ba9350bf62c45b05f8fbff166517b) +Signed-off-by: Marc-André Lureau +Signed-off-by: Miroslav Rezanina +--- + slirp/src/udp6.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/slirp/src/udp6.c b/slirp/src/udp6.c +index 6f9486bbca..8c490e4d10 100644 +--- a/slirp/src/udp6.c ++++ b/slirp/src/udp6.c +@@ -28,7 +28,10 @@ void udp6_input(struct mbuf *m) + ip = mtod(m, struct ip6 *); + m->m_len -= iphlen; + m->m_data += iphlen; +- uh = mtod(m, struct udphdr *); ++ uh = mtod_check(m, sizeof(struct udphdr)); ++ if (uh == NULL) { ++ goto bad; ++ } + m->m_len += iphlen; + m->m_data -= iphlen; + +-- +2.27.0 + diff --git a/SOURCES/kvm-vfio-ccw-Connect-the-device-request-notifier.patch b/SOURCES/kvm-vfio-ccw-Connect-the-device-request-notifier.patch new file mode 100644 index 0000000..298fb29 --- /dev/null +++ b/SOURCES/kvm-vfio-ccw-Connect-the-device-request-notifier.patch @@ -0,0 +1,128 @@ +From db6a782f8b9ba062f195ff504b4d2f93e471fecc Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Tue, 11 May 2021 11:24:05 -0400 +Subject: [PATCH 2/5] vfio-ccw: Connect the device request notifier + +RH-Author: Thomas Huth +Message-id: <20210511112405.297037-3-thuth@redhat.com> +Patchwork-id: 101536 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 2/2] vfio-ccw: Connect the device request notifier +Bugzilla: 1940450 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand + +Now that the vfio-ccw code has a notifier interface to request that +a device be unplugged, let's wire that together. + +Signed-off-by: Eric Farman +Reviewed-by: Cornelia Huck +Message-Id: <20210104202057.48048-4-farman@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit b2f96f9e4f5fbc8f2770a436191cb328da4d5350) +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1940450 +Signed-off-by: Thomas Huth +Signed-off-by: Danilo C. L. de Paula +--- + hw/vfio/ccw.c | 40 ++++++++++++++++++++++++++++++++++++---- + 1 file changed, 36 insertions(+), 4 deletions(-) + +diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c +index b72a505893..3d450fe1c9 100644 +--- a/hw/vfio/ccw.c ++++ b/hw/vfio/ccw.c +@@ -49,6 +49,7 @@ struct VFIOCCWDevice { + struct ccw_crw_region *crw_region; + EventNotifier io_notifier; + EventNotifier crw_notifier; ++ EventNotifier req_notifier; + bool force_orb_pfch; + bool warned_orb_pfch; + }; +@@ -287,6 +288,21 @@ static void vfio_ccw_crw_read(VFIOCCWDevice *vcdev) + } while (1); + } + ++static void vfio_ccw_req_notifier_handler(void *opaque) ++{ ++ VFIOCCWDevice *vcdev = opaque; ++ Error *err = NULL; ++ ++ if (!event_notifier_test_and_clear(&vcdev->req_notifier)) { ++ return; ++ } ++ ++ qdev_unplug(DEVICE(vcdev), &err); ++ if (err) { ++ warn_reportf_err(err, VFIO_MSG_PREFIX, vcdev->vdev.name); ++ } ++} ++ + static void vfio_ccw_crw_notifier_handler(void *opaque) + { + VFIOCCWDevice *vcdev = opaque; +@@ -386,6 +402,10 @@ static void vfio_ccw_register_irq_notifier(VFIOCCWDevice *vcdev, + notifier = &vcdev->crw_notifier; + fd_read = vfio_ccw_crw_notifier_handler; + break; ++ case VFIO_CCW_REQ_IRQ_INDEX: ++ notifier = &vcdev->req_notifier; ++ fd_read = vfio_ccw_req_notifier_handler; ++ break; + default: + error_setg(errp, "vfio: Unsupported device irq(%d)", irq); + return; +@@ -440,6 +460,9 @@ static void vfio_ccw_unregister_irq_notifier(VFIOCCWDevice *vcdev, + case VFIO_CCW_CRW_IRQ_INDEX: + notifier = &vcdev->crw_notifier; + break; ++ case VFIO_CCW_REQ_IRQ_INDEX: ++ notifier = &vcdev->req_notifier; ++ break; + default: + error_report("vfio: Unsupported device irq(%d)", irq); + return; +@@ -657,20 +680,28 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp) + + vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX, &err); + if (err) { +- goto out_notifier_err; ++ goto out_io_notifier_err; + } + + if (vcdev->crw_region) { + vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_CRW_IRQ_INDEX, &err); + if (err) { +- vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX); +- goto out_notifier_err; ++ goto out_crw_notifier_err; + } + } + ++ vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_REQ_IRQ_INDEX, &err); ++ if (err) { ++ goto out_req_notifier_err; ++ } ++ + return; + +-out_notifier_err: ++out_req_notifier_err: ++ vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_CRW_IRQ_INDEX); ++out_crw_notifier_err: ++ vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX); ++out_io_notifier_err: + vfio_ccw_put_region(vcdev); + out_region_err: + vfio_ccw_put_device(vcdev); +@@ -692,6 +723,7 @@ static void vfio_ccw_unrealize(DeviceState *dev, Error **errp) + S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev); + VFIOGroup *group = vcdev->vdev.group; + ++ vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_REQ_IRQ_INDEX); + vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_CRW_IRQ_INDEX); + vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX); + vfio_ccw_put_region(vcdev); +-- +2.27.0 + diff --git a/SOURCES/kvm-virtiofsd-Disable-remote-posix-locks-by-default.patch b/SOURCES/kvm-virtiofsd-Disable-remote-posix-locks-by-default.patch new file mode 100644 index 0000000..90b6b35 --- /dev/null +++ b/SOURCES/kvm-virtiofsd-Disable-remote-posix-locks-by-default.patch @@ -0,0 +1,72 @@ +From 3ec945ba7c2649cca13cf6070c6365b1262ad1ec Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Fri, 6 Aug 2021 11:58:26 -0400 +Subject: [PATCH 1/2] virtiofsd: Disable remote posix locks by default +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Max Reitz +Message-id: <20210806115827.740945-2-mreitz@redhat.com> +Patchwork-id: 101970 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 1/2] virtiofsd: Disable remote posix locks by default +Bugzilla: 1967496 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Vivek Goyal + +From: Vivek Goyal + +Right now we enable remote posix locks by default. That means when guest +does a posix lock it sends request to server (virtiofsd). But currently +we only support non-blocking posix lock and return -EOPNOTSUPP for +blocking version. + +This means that existing applications which are doing blocking posix +locks get -EOPNOTSUPP and fail. To avoid this, people have been +running virtiosd with option "-o no_posix_lock". For new users it +is still a surprise and trial and error takes them to this option. + +Given posix lock implementation is not complete in virtiofsd, disable +it by default. This means that posix locks will work with-in applications +in a guest but not across guests. Anyway we don't support sharing +filesystem among different guests yet in virtiofs so this should +not lead to any kind of surprise or regression and will make life +little easier for virtiofs users. + +Reported-by: Aa Aa +Suggested-by: Miklos Szeredi +Signed-off-by: Vivek Goyal +Reviewed-by: Stefan Hajnoczi +Reviewed-by: Misono Tomohiro +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit 88fc107956a5812649e5918e0c092d3f78bb28ad) + +Conflicts: + docs/tools/virtiofsd.rst + We do not have virtiofsd.rst downstream (added upstream in + commit 6a7e2bbee5fa), so I dropped that hunk (which effectively + updated the default value in the man page). + +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + tools/virtiofsd/passthrough_ll.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c +index cb0992f2db..b47029da89 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -3001,7 +3001,7 @@ int main(int argc, char *argv[]) + struct lo_data lo = { + .debug = 0, + .writeback = 0, +- .posix_lock = 1, ++ .posix_lock = 0, + .proc_self_fd = -1, + }; + struct lo_map_elem *root_elem; +-- +2.27.0 + diff --git a/SOURCES/kvm-virtiofsd-Fix-the-help-message-of-posix-lock.patch b/SOURCES/kvm-virtiofsd-Fix-the-help-message-of-posix-lock.patch new file mode 100644 index 0000000..98907a5 --- /dev/null +++ b/SOURCES/kvm-virtiofsd-Fix-the-help-message-of-posix-lock.patch @@ -0,0 +1,51 @@ +From 6abfb7b3c37015ff901d11f178bc6900deec2acf Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Fri, 6 Aug 2021 11:58:27 -0400 +Subject: [PATCH 2/2] virtiofsd: Fix the help message of posix lock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Max Reitz +Message-id: <20210806115827.740945-3-mreitz@redhat.com> +Patchwork-id: 101969 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 2/2] virtiofsd: Fix the help message of posix lock +Bugzilla: 1967496 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Vivek Goyal + +From: Jiachen Zhang + +The commit 88fc107956a5812649e5918e0c092d3f78bb28ad disabled remote +posix locks by default. But the --help message still says it is enabled +by default. So fix it to output no_posix_lock. + +Signed-off-by: Jiachen Zhang +Message-Id: <20201027081558.29904-1-zhangjiachen.jaycee@bytedance.com> +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit 0429eaf518be1d4742356056e6c886b7f9bc9712) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + tools/virtiofsd/helper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/virtiofsd/helper.c b/tools/virtiofsd/helper.c +index 5b222ea49b..813d9490e5 100644 +--- a/tools/virtiofsd/helper.c ++++ b/tools/virtiofsd/helper.c +@@ -163,7 +163,7 @@ void fuse_cmdline_help(void) + " default: false\n" + " -o posix_lock|no_posix_lock\n" + " enable/disable remote posix lock\n" +- " default: posix_lock\n" ++ " default: no_posix_lock\n" + " -o readdirplus|no_readdirplus\n" + " enable/disable readirplus\n" + " default: readdirplus except with " +-- +2.27.0 + diff --git a/SOURCES/kvm-virtiofsd-Whitelist-fchmod.patch b/SOURCES/kvm-virtiofsd-Whitelist-fchmod.patch new file mode 100644 index 0000000..a4f95d9 --- /dev/null +++ b/SOURCES/kvm-virtiofsd-Whitelist-fchmod.patch @@ -0,0 +1,79 @@ +From 181ed1777c3dd50b1ff9907b0a4199e845af1270 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Fri, 18 Jun 2021 16:21:17 -0400 +Subject: [PATCH 1/4] virtiofsd: Whitelist fchmod +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Max Reitz +Message-id: <20210618162117.97775-2-mreitz@redhat.com> +Patchwork-id: 101719 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH 1/1] virtiofsd: Whitelist fchmod +Bugzilla: 1967914 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Vivek Goyal +RH-Acked-by: Connor Kuehl + +lo_setattr() invokes fchmod() in a rarely used code path, so it should +be whitelisted or virtiofsd will crash with EBADSYS. + +Said code path can be triggered for example as follows: + +On the host, in the shared directory, create a file with the sticky bit +set and a security.capability xattr: +(1) # touch foo +(2) # chmod u+s foo +(3) # setcap '' foo + +Then in the guest let some process truncate that file after it has +dropped all of its capabilities (at least CAP_FSETID): + +int main(int argc, char *argv[]) +{ + capng_setpid(getpid()); + capng_clear(CAPNG_SELECT_BOTH); + capng_updatev(CAPNG_ADD, CAPNG_PERMITTED | CAPNG_EFFECTIVE, 0); + capng_apply(CAPNG_SELECT_BOTH); + + ftruncate(open(argv[1], O_RDWR), 0); +} + +This will cause the guest kernel to drop the sticky bit (i.e. perform a +mode change) as part of the truncate (where FATTR_FH is set), and that +will cause virtiofsd to invoke fchmod() instead of fchmodat(). + +(A similar configuration exists further below with futimens() vs. +utimensat(), but the former is not a syscall but just a wrapper for the +latter, so no further whitelisting is required.) + +Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1842667 +Reported-by: Qian Cai +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Message-Id: <20200608093111.14942-1-mreitz@redhat.com> +Reviewed-by: Dr. David Alan Gilbert +Reviewed-by: Vivek Goyal +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit 63659fe74e76f5c5285466f0c5cfbdca65b3688e) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + tools/virtiofsd/seccomp.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/virtiofsd/seccomp.c b/tools/virtiofsd/seccomp.c +index bd9e7b083c..3b1522acdd 100644 +--- a/tools/virtiofsd/seccomp.c ++++ b/tools/virtiofsd/seccomp.c +@@ -42,6 +42,7 @@ static const int syscall_whitelist[] = { + SCMP_SYS(exit_group), + SCMP_SYS(fallocate), + SCMP_SYS(fchdir), ++ SCMP_SYS(fchmod), + SCMP_SYS(fchmodat), + SCMP_SYS(fchownat), + SCMP_SYS(fcntl), +-- +2.27.0 + diff --git a/SOURCES/kvm-virtiofsd-extract-lo_do_open-from-lo_open.patch b/SOURCES/kvm-virtiofsd-extract-lo_do_open-from-lo_open.patch new file mode 100644 index 0000000..b0f678f --- /dev/null +++ b/SOURCES/kvm-virtiofsd-extract-lo_do_open-from-lo_open.patch @@ -0,0 +1,167 @@ +From c02ebc7e43f55b9423a065a7c53ba72bdb821c98 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 9 Feb 2021 23:14:54 -0500 +Subject: [PATCH 1/3] virtiofsd: extract lo_do_open() from lo_open() + +RH-Author: Jon Maloy +Message-id: <20210209231456.1555472-2-jmaloy@redhat.com> +Patchwork-id: 101024 +O-Subject: [RHEL-8.4.0 qemu-kvm PATCH 1/3] virtiofsd: extract lo_do_open() from lo_open() +Bugzilla: 1919111 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Greg Kurz +RH-Acked-by: Dr. David Alan Gilbert + +From: Stefan Hajnoczi + +Both lo_open() and lo_create() have similar code to open a file. Extract +a common lo_do_open() function from lo_open() that will be used by +lo_create() in a later commit. + +Since lo_do_open() does not otherwise need fuse_req_t req, convert +lo_add_fd_mapping() to use struct lo_data *lo instead. + +Signed-off-by: Stefan Hajnoczi +Message-Id: <20210204150208.367837-2-stefanha@redhat.com> +Reviewed-by: Greg Kurz +Signed-off-by: Dr. David Alan Gilbert + +(cherry-picked from commit 8afaaee976965b7fb90ec225a51d60f35c5f173c) + +Conflict: update_open_flags() takes fewer arguments in this version + than in upstream. Instead of applying commit e12a0edafeb + ("virtiofsd: Add -o allow_direct_io|no_allow_direct_io + options") we keep the old signature, since this seems to + be an unrelated change. + +Signed-off-by: Jon Maloy +Signed-off-by: Jon Maloy +--- + 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 f41a6b07c8..518ba11c47 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -439,17 +439,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 */ +@@ -1712,6 +1712,38 @@ static void update_open_flags(int writeback, struct fuse_file_info *fi) + fi->flags &= ~O_DIRECT; + } + ++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, 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) + { +@@ -1752,7 +1784,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); +@@ -1943,38 +1975,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, 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, +-- +2.18.2 + diff --git a/SOURCES/kvm-virtiofsd-optionally-return-inode-pointer-from-lo_do.patch b/SOURCES/kvm-virtiofsd-optionally-return-inode-pointer-from-lo_do.patch new file mode 100644 index 0000000..f21d793 --- /dev/null +++ b/SOURCES/kvm-virtiofsd-optionally-return-inode-pointer-from-lo_do.patch @@ -0,0 +1,124 @@ +From f2c0b07088966c396ddcee54f4bed97cdb01192f Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 9 Feb 2021 23:14:55 -0500 +Subject: [PATCH 2/3] virtiofsd: optionally return inode pointer from + lo_do_lookup() + +RH-Author: Jon Maloy +Message-id: <20210209231456.1555472-3-jmaloy@redhat.com> +Patchwork-id: 101022 +O-Subject: [RHEL-8.4.0 qemu-kvm PATCH 2/3] virtiofsd: optionally return inode pointer from lo_do_lookup() +Bugzilla: 1919111 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Greg Kurz +RH-Acked-by: Dr. David Alan Gilbert + +From: Stefan Hajnoczi + +lo_do_lookup() finds an existing inode or allocates a new one. It +increments nlookup so that the inode stays alive until the client +releases it. + +Existing callers don't need the struct lo_inode so the function doesn't +return it. Extend the function to optionally return the inode. The next +commit will need it. + +Signed-off-by: Stefan Hajnoczi +Reviewed-by: Greg Kurz +Message-Id: <20210204150208.367837-3-stefanha@redhat.com> +Signed-off-by: Dr. David Alan Gilbert + +(cherry-picked from commit 22d2ece71e533310da31f2857ebc4a00d91968b3) +Signed-off-by: Jon Maloy +Signed-off-by: Jon Maloy +--- + 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 518ba11c47..e5bd3d73e4 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -878,11 +878,13 @@ static void posix_locks_value_destroy(gpointer data) + } + + /* +- * 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; +@@ -891,6 +893,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 +@@ -953,7 +959,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, +@@ -988,7 +1001,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 { +@@ -1098,7 +1111,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; + } +@@ -1599,7 +1612,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; + } +@@ -1793,7 +1806,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; +-- +2.18.2 + diff --git a/SOURCES/kvm-virtiofsd-prevent-opening-of-special-files-CVE-2020-.patch b/SOURCES/kvm-virtiofsd-prevent-opening-of-special-files-CVE-2020-.patch new file mode 100644 index 0000000..5956dce --- /dev/null +++ b/SOURCES/kvm-virtiofsd-prevent-opening-of-special-files-CVE-2020-.patch @@ -0,0 +1,314 @@ +From cc9a776fba8ec62c862db55753107f19459dafa8 Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Tue, 9 Feb 2021 23:14:56 -0500 +Subject: [PATCH 3/3] virtiofsd: prevent opening of special files + (CVE-2020-35517) + +RH-Author: Jon Maloy +Message-id: <20210209231456.1555472-4-jmaloy@redhat.com> +Patchwork-id: 101023 +O-Subject: [RHEL-8.4.0 qemu-kvm PATCH 3/3] virtiofsd: prevent opening of special files (CVE-2020-35517) +Bugzilla: 1919111 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Greg Kurz +RH-Acked-by: Dr. David Alan Gilbert + +From: Stefan Hajnoczi + +A well-behaved FUSE client does not attempt to open special files with +FUSE_OPEN because they are handled on the client side (e.g. device nodes +are handled by client-side device drivers). + +The check to prevent virtiofsd from opening special files is missing in +a few cases, most notably FUSE_OPEN. A malicious client can cause +virtiofsd to open a device node, potentially allowing the guest to +escape. This can be exploited by a modified guest device driver. It is +not exploitable from guest userspace since the guest kernel will handle +special files inside the guest instead of sending FUSE requests. + +This patch fixes this issue by introducing the lo_inode_open() function +to check the file type before opening it. This is a short-term solution +because it does not prevent a compromised virtiofsd process from opening +device nodes on the host. + +Restructure lo_create() to try O_CREAT | O_EXCL first. Note that O_CREAT +| O_EXCL does not follow symlinks, so O_NOFOLLOW masking is not +necessary here. If the file exists and the user did not specify O_EXCL, +open it via lo_do_open(). + +Reported-by: Alex Xu +Fixes: CVE-2020-35517 +Reviewed-by: Dr. David Alan Gilbert +Reviewed-by: Vivek Goyal +Reviewed-by: Greg Kurz +Signed-off-by: Stefan Hajnoczi +Message-Id: <20210204150208.367837-4-stefanha@redhat.com> +Signed-off-by: Dr. David Alan Gilbert + +(cherry picked from commit a3fdbbc7f271bff7d53d0501b29d910ece0b3789) +Signed-off-by: Jon Maloy +Signed-off-by: Jon Maloy +--- + 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 e5bd3d73e4..cb0992f2db 100644 +--- a/tools/virtiofsd/passthrough_ll.c ++++ b/tools/virtiofsd/passthrough_ll.c +@@ -535,6 +535,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; +@@ -788,9 +820,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; + } + } +@@ -894,7 +926,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 */ + } + + /* +@@ -1725,19 +1757,26 @@ static void update_open_flags(int writeback, struct fuse_file_info *fi) + fi->flags &= ~O_DIRECT; + } + ++/* ++ * 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, 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); +@@ -1760,9 +1799,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 = {}; +@@ -1788,36 +1828,38 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name, + + update_open_flags(lo->writeback, 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); +@@ -1831,7 +1873,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 = +@@ -1848,12 +1889,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; + } +@@ -2000,7 +2039,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); +@@ -2056,39 +2095,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, +-- +2.18.2 + diff --git a/SOURCES/kvm-x86-cpu-Enable-AVX512_VP2INTERSECT-cpu-feature.patch b/SOURCES/kvm-x86-cpu-Enable-AVX512_VP2INTERSECT-cpu-feature.patch new file mode 100644 index 0000000..dbcf2a7 --- /dev/null +++ b/SOURCES/kvm-x86-cpu-Enable-AVX512_VP2INTERSECT-cpu-feature.patch @@ -0,0 +1,63 @@ +From ad50e0e2d310277f06a9c512fe6e31da183ead6e Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Wed, 24 Feb 2021 11:30:34 -0500 +Subject: [PATCH 1/4] x86/cpu: Enable AVX512_VP2INTERSECT cpu feature + +RH-Author: Dr. David Alan Gilbert +Message-id: <20210224113037.15599-2-dgilbert@redhat.com> +Patchwork-id: 101203 +O-Subject: [RHEL-8.4.0 qemu-kvm PATCH 1/4] x86/cpu: Enable AVX512_VP2INTERSECT cpu feature +Bugzilla: 1790620 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: Peter Xu + +From: Cathy Zhang + +AVX512_VP2INTERSECT compute vector pair intersection to a pair +of mask registers, which is introduced with intel Tiger Lake, +defining as CPUID.(EAX=7,ECX=0):EDX[bit 08]. + +Refer to the following release spec: +https://software.intel.com/sites/default/files/managed/c5/15/\ +architecture-instruction-set-extensions-programming-reference.pdf + +Signed-off-by: Cathy Zhang +Message-Id: <1586760758-13638-1-git-send-email-cathy.zhang@intel.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 353f98c9ad52ff4b8cfe553c90be04f747a14c98) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + target/i386/cpu.h | 2 ++ + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index ff39fc9905..67dab94aa5 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1078,7 +1078,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + .feat_names = { + NULL, NULL, "avx512-4vnniw", "avx512-4fmaps", + NULL, NULL, NULL, NULL, +- NULL, NULL, "md-clear", NULL, ++ "avx512-vp2intersect", NULL, "md-clear", NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL /* pconfig */, NULL, + NULL, NULL, NULL, NULL, +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index f3da25cb8a..8e2e52ed31 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -770,6 +770,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) + /* AVX512 Multiply Accumulation Single Precision */ + #define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) ++/* AVX512 Vector Pair Intersection to a Pair of Mask Registers */ ++#define CPUID_7_0_EDX_AVX512_VP2INTERSECT (1U << 8) + /* Speculation Control */ + #define CPUID_7_0_EDX_SPEC_CTRL (1U << 26) + /* Single Thread Indirect Branch Predictors */ +-- +2.27.0 + diff --git a/SOURCES/kvm-x86-cpu-Populate-SVM-CPUID-feature-bits.patch b/SOURCES/kvm-x86-cpu-Populate-SVM-CPUID-feature-bits.patch new file mode 100644 index 0000000..9ef6d04 --- /dev/null +++ b/SOURCES/kvm-x86-cpu-Populate-SVM-CPUID-feature-bits.patch @@ -0,0 +1,91 @@ +From 655e723a5190206302f6cc4f2e794563b8e1c226 Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Wed, 24 Feb 2021 11:30:36 -0500 +Subject: [PATCH 3/4] x86/cpu: Populate SVM CPUID feature bits + +RH-Author: Dr. David Alan Gilbert +Message-id: <20210224113037.15599-4-dgilbert@redhat.com> +Patchwork-id: 101200 +O-Subject: [RHEL-8.4.0 qemu-kvm PATCH 3/4] x86/cpu: Populate SVM CPUID feature bits +Bugzilla: 1790620 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: Peter Xu + +From: Wei Huang + +Newer AMD CPUs will add CPUID_0x8000000A_EDX[28] bit, which indicates +that SVM instructions (VMRUN/VMSAVE/VMLOAD) will trigger #VMEXIT before +CPU checking their EAX against reserved memory regions. This change will +allow the hypervisor to avoid intercepting #GP and emulating SVM +instructions. KVM turns on this CPUID bit for nested VMs. In order to +support it, let us populate this bit, along with other SVM feature bits, +in FEAT_SVM. + +Signed-off-by: Wei Huang +Message-Id: <20210126202456.589932-1-wei.huang2@amd.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 5447089c2b3b084b51670af36fc86ee3979e04be) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 6 +++--- + target/i386/cpu.h | 24 ++++++++++++++---------- + 2 files changed, 17 insertions(+), 13 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index f6a9ed84b3..7227c803c3 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1026,11 +1026,11 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + "npt", "lbrv", "svm-lock", "nrip-save", + "tsc-scale", "vmcb-clean", "flushbyasid", "decodeassists", + NULL, NULL, "pause-filter", NULL, +- "pfthreshold", NULL, NULL, NULL, +- NULL, NULL, NULL, NULL, +- NULL, NULL, NULL, NULL, ++ "pfthreshold", "avic", NULL, "v-vmsave-vmload", ++ "vgif", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, ++ "svme-addr-chk", NULL, NULL, NULL, + }, + .cpuid = { .eax = 0x8000000A, .reg = R_EDX, }, + .tcg_features = TCG_SVM_FEATURES, +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index f5a4efcec6..e1b67910c2 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -667,16 +667,20 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_EXT3_PERFCORE (1U << 23) + #define CPUID_EXT3_PERFNB (1U << 24) + +-#define CPUID_SVM_NPT (1U << 0) +-#define CPUID_SVM_LBRV (1U << 1) +-#define CPUID_SVM_SVMLOCK (1U << 2) +-#define CPUID_SVM_NRIPSAVE (1U << 3) +-#define CPUID_SVM_TSCSCALE (1U << 4) +-#define CPUID_SVM_VMCBCLEAN (1U << 5) +-#define CPUID_SVM_FLUSHASID (1U << 6) +-#define CPUID_SVM_DECODEASSIST (1U << 7) +-#define CPUID_SVM_PAUSEFILTER (1U << 10) +-#define CPUID_SVM_PFTHRESHOLD (1U << 12) ++#define CPUID_SVM_NPT (1U << 0) ++#define CPUID_SVM_LBRV (1U << 1) ++#define CPUID_SVM_SVMLOCK (1U << 2) ++#define CPUID_SVM_NRIPSAVE (1U << 3) ++#define CPUID_SVM_TSCSCALE (1U << 4) ++#define CPUID_SVM_VMCBCLEAN (1U << 5) ++#define CPUID_SVM_FLUSHASID (1U << 6) ++#define CPUID_SVM_DECODEASSIST (1U << 7) ++#define CPUID_SVM_PAUSEFILTER (1U << 10) ++#define CPUID_SVM_PFTHRESHOLD (1U << 12) ++#define CPUID_SVM_AVIC (1U << 13) ++#define CPUID_SVM_V_VMSAVE_VMLOAD (1U << 15) ++#define CPUID_SVM_VGIF (1U << 16) ++#define CPUID_SVM_SVME_ADDR_CHK (1U << 28) + + /* Support RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE */ + #define CPUID_7_0_EBX_FSGSBASE (1U << 0) +-- +2.27.0 + diff --git a/SOURCES/kvm-xhci-fix-valid.max_access_size-to-access-address-reg.patch b/SOURCES/kvm-xhci-fix-valid.max_access_size-to-access-address-reg.patch new file mode 100644 index 0000000..aabe041 --- /dev/null +++ b/SOURCES/kvm-xhci-fix-valid.max_access_size-to-access-address-reg.patch @@ -0,0 +1,76 @@ +From f38f51d422e82d1241b678960dd6a033ffa398da Mon Sep 17 00:00:00 2001 +From: Jon Maloy +Date: Wed, 21 Apr 2021 22:30:05 -0400 +Subject: [PATCH 6/7] xhci: fix valid.max_access_size to access address + registers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Jon Maloy +Message-id: <20210421223006.19650-6-jmaloy@redhat.com> +Patchwork-id: 101483 +O-Subject: [RHEL-8.5.0 qemu-kvm PATCH v2 5/6] xhci: fix valid.max_access_size to access address registers +Bugzilla: 1842478 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laszlo Ersek + +From: Laurent Vivier + +QEMU XHCI advertises AC64 (64-bit addressing) but doesn't allow +64-bit mode access in "runtime" and "operational" MemoryRegionOps. + +Set the max_access_size based on sizeof(dma_addr_t) as AC64 is set. + +XHCI specs: +"If the xHC supports 64-bit addressing (AC64 = ‘1’), then software +should write 64-bit registers using only Qword accesses. If a +system is incapable of issuing Qword accesses, then writes to the +64-bit address fields shall be performed using 2 Dword accesses; +low Dword-first, high-Dword second. If the xHC supports 32-bit +addressing (AC64 = ‘0’), then the high Dword of registers containing +64-bit address fields are unused and software should write addresses +using only Dword accesses" + +The problem has been detected with SLOF, as linux kernel always accesses +registers using 32-bit access even if AC64 is set and revealed by +5d971f9e6725 ("memory: Revert "memory: accept mismatching sizes in memory_region_access_valid"") + +Suggested-by: Alexey Kardashevskiy +Signed-off-by: Laurent Vivier +Message-id: 20200721083322.90651-1-lvivier@redhat.com +Signed-off-by: Gerd Hoffmann + +(cherry picked from commit 8e67fda2dd6202ccec093fda561107ba14830a17) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + hw/usb/hcd-xhci.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c +index 646c78cde9..ab449bb003 100644 +--- a/hw/usb/hcd-xhci.c ++++ b/hw/usb/hcd-xhci.c +@@ -3183,7 +3183,7 @@ static const MemoryRegionOps xhci_oper_ops = { + .read = xhci_oper_read, + .write = xhci_oper_write, + .valid.min_access_size = 4, +- .valid.max_access_size = 4, ++ .valid.max_access_size = sizeof(dma_addr_t), + .endianness = DEVICE_LITTLE_ENDIAN, + }; + +@@ -3199,7 +3199,7 @@ static const MemoryRegionOps xhci_runtime_ops = { + .read = xhci_runtime_read, + .write = xhci_runtime_write, + .valid.min_access_size = 4, +- .valid.max_access_size = 4, ++ .valid.max_access_size = sizeof(dma_addr_t), + .endianness = DEVICE_LITTLE_ENDIAN, + }; + +-- +2.27.0 + diff --git a/SPECS/qemu-kvm.spec b/SPECS/qemu-kvm.spec index e8a06e1..22e8f20 100644 --- a/SPECS/qemu-kvm.spec +++ b/SPECS/qemu-kvm.spec @@ -61,13 +61,13 @@ Requires: %{name}-block-ssh = %{epoch}:%{version}-%{release} # Macro to properly setup RHEL/RHEV conflict handling %define rhev_ma_conflicts() \ -Obsoletes: %1-ma \ -Obsoletes: %1-rhev +Obsoletes: %1-ma <= %{epoch}:%{version}-%{release} \ +Obsoletes: %1-rhev <= %{epoch}:%{version}-%{release} Summary: QEMU is a machine emulator and virtualizer Name: qemu-kvm Version: 4.2.0 -Release: 44%{?dist} +Release: 58%{?dist} # Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped Epoch: 15 License: GPLv2 and GPLv2+ and CC-BY @@ -1112,6 +1112,140 @@ Patch479: kvm-block-Require-aligned-image-size-to-avoid-assertion-.patch Patch480: kvm-file-posix-Allow-byte-aligned-O_DIRECT-with-NFS.patch # For bz#1912974 - CVE-2020-11947 virt:rhel/qemu-kvm: QEMU: heap buffer overflow in iscsi_aio_ioctl_cb() in block/iscsi.c may lead to information disclosure [rhel-8] Patch481: kvm-block-iscsi-fix-heap-buffer-overflow-in-iscsi_aio_io.patch +# For bz#1919111 - CVE-2020-35517 virt:rhel/qemu-kvm: QEMU: virtiofsd: potential privileged host device access from guest [rhel-8.4.0] +Patch482: kvm-virtiofsd-extract-lo_do_open-from-lo_open.patch +# For bz#1919111 - CVE-2020-35517 virt:rhel/qemu-kvm: QEMU: virtiofsd: potential privileged host device access from guest [rhel-8.4.0] +Patch483: kvm-virtiofsd-optionally-return-inode-pointer-from-lo_do.patch +# For bz#1919111 - CVE-2020-35517 virt:rhel/qemu-kvm: QEMU: virtiofsd: potential privileged host device access from guest [rhel-8.4.0] +Patch484: kvm-virtiofsd-prevent-opening-of-special-files-CVE-2020-.patch +# For bz#1912891 - [ppc64le] --disk cdimage.iso,bus=usb fails to boot +Patch486: kvm-spapr-Adjust-firmware-path-of-PCI-devices.patch +# For bz#1790620 - [RFE] AMD Milan - Add KVM/support for EPYC-Milan CPU Model - Slow Train +Patch487: kvm-x86-cpu-Enable-AVX512_VP2INTERSECT-cpu-feature.patch +# For bz#1790620 - [RFE] AMD Milan - Add KVM/support for EPYC-Milan CPU Model - Slow Train +Patch488: kvm-target-i386-add-fast-short-REP-MOV-support.patch +# For bz#1790620 - [RFE] AMD Milan - Add KVM/support for EPYC-Milan CPU Model - Slow Train +Patch489: kvm-x86-cpu-Populate-SVM-CPUID-feature-bits.patch +# For bz#1790620 - [RFE] AMD Milan - Add KVM/support for EPYC-Milan CPU Model - Slow Train +Patch490: kvm-i386-Add-the-support-for-AMD-EPYC-3rd-generation-pro.patch +# For bz#1917451 - CVE-2020-29443 virt:rhel/qemu-kvm: QEMU: ide: atapi: OOB access while processing read commands [rhel-8.4.0] +Patch491: kvm-ide-atapi-check-logical-block-address-and-read-size-.patch +# For bz#1892350 - CVE-2020-27617 virt:rhel/qemu-kvm: QEMU: net: an assert failure via eth_get_gso_type [rhel-8.5.0] +Patch492: kvm-net-remove-an-assert-call-in-eth_get_gso_type.patch +# For bz#1930092 - CVE-2021-20257 virt:rhel/qemu-kvm: QEMU: net: e1000: infinite loop while processing transmit descriptors [rhel-8.5.0] +Patch493: kvm-e1000-fail-early-for-evil-descriptor.patch +# For bz#1859175 - CVE-2020-15859 virt:rhel/qemu-kvm: QEMU: net: e1000e: use-after-free while sending packets [rhel-8] +Patch494: kvm-net-forbid-the-reentrant-RX.patch +# For bz#1855250 - qemu-img convert uses possibly slow pre-zeroing on block storage +Patch495: kvm-qemu-img-convert-Don-t-pre-zero-images.patch +# For bz#1932823 - after upgrade from 4.3 to 4.4 audio stops working in guests after couple of seconds +Patch496: kvm-audio-audio_generic_get_buffer_in-should-honor-size.patch +# For bz#1925430 - CVE-2021-20221 virt:rhel/qemu-kvm: qemu: out-of-bound heap buffer access via an interrupt ID field [rhel-8.5.0] +Patch497: kvm-hw-intc-arm_gic-Fix-interrupt-ID-in-GICD_SGIR-regist.patch +# For bz#1842478 - CVE-2020-13754 virt:rhel/qemu-kvm: QEMU: msix: OOB access during mmio operations may lead to DoS [rhel-8.5.0] +Patch498: kvm-libqos-usb-hcd-ehci-use-32-bit-write-for-config-regi.patch +# For bz#1842478 - CVE-2020-13754 virt:rhel/qemu-kvm: QEMU: msix: OOB access during mmio operations may lead to DoS [rhel-8.5.0] +Patch499: kvm-libqos-pci-pc-use-32-bit-write-for-EJ-register.patch +# For bz#1842478 - CVE-2020-13754 virt:rhel/qemu-kvm: QEMU: msix: OOB access during mmio operations may lead to DoS [rhel-8.5.0] +Patch500: kvm-memory-Revert-memory-accept-mismatching-sizes-in-mem.patch +# For bz#1842478 - CVE-2020-13754 virt:rhel/qemu-kvm: QEMU: msix: OOB access during mmio operations may lead to DoS [rhel-8.5.0] +Patch501: kvm-acpi-accept-byte-and-word-access-to-core-ACPI-regist.patch +# For bz#1842478 - CVE-2020-13754 virt:rhel/qemu-kvm: QEMU: msix: OOB access during mmio operations may lead to DoS [rhel-8.5.0] +Patch502: kvm-xhci-fix-valid.max_access_size-to-access-address-reg.patch +# For bz#1842478 - CVE-2020-13754 virt:rhel/qemu-kvm: QEMU: msix: OOB access during mmio operations may lead to DoS [rhel-8.5.0] +Patch503: kvm-softmmu-memory-Log-invalid-memory-accesses.patch +# For bz#1940450 - RHEL8.5 - Mediated Device already in use by same domain we are booting (vfio-ccw/Multipath Testing) (kvm) - qemu-kvm part (also has kernel and libvirt parts) +Patch504: kvm-linux-headers-Add-VFIO_CCW_REQ_IRQ_INDEX.patch +# For bz#1940450 - RHEL8.5 - Mediated Device already in use by same domain we are booting (vfio-ccw/Multipath Testing) (kvm) - qemu-kvm part (also has kernel and libvirt parts) +Patch505: kvm-vfio-ccw-Connect-the-device-request-notifier.patch +# For bz#1942880 - RHEL8.4 Nightly[0322] - KVM guest fails to find zipl boot menu index (qemu-kvm) +Patch506: kvm-pc-bios-s390-ccw-fix-off-by-one-error.patch +# For bz#1942880 - RHEL8.4 Nightly[0322] - KVM guest fails to find zipl boot menu index (qemu-kvm) +Patch507: kvm-pc-bios-s390-ccw-break-loop-if-a-null-block-number-i.patch +# For bz#1942880 - RHEL8.4 Nightly[0322] - KVM guest fails to find zipl boot menu index (qemu-kvm) +Patch508: kvm-pc-bios-s390-ccw-don-t-try-to-read-the-next-block-if.patch +# For bz#1877163 - [FJ 8.3 Bug] The progress bar of the "virt-clone --nonsparse" command shows the progress rate exceeding 100%. +Patch509: kvm-file-posix-Mitigate-file-fragmentation-with-extent-s.patch +# For bz#1944861 - Qemu-img convert fails when source image is on gpfs +Patch510: kvm-block-file-posix-Fix-problem-with-fallocate-PUNCH_HO.patch +# For bz#1969768 - [ppc64le] Hotplug vcpu device hit call trace:[qemu output] KVM: unknown exit, hardware reason 7fff9ce87ed8 +Patch511: kvm-spapr-Remove-stale-comment-about-power-saving-LPCR-b.patch +# For bz#1969768 - [ppc64le] Hotplug vcpu device hit call trace:[qemu output] KVM: unknown exit, hardware reason 7fff9ce87ed8 +Patch512: kvm-spapr-Set-LPCR-to-current-AIL-mode-when-starting-a-n.patch +# For bz#1967914 - [virtio-fs] virtiofsd quit when coping file to a folder in virtio-fs mounted volume(windows guest) +Patch513: kvm-virtiofsd-Whitelist-fchmod.patch +# For bz#1957866 - RHEL8.4 - EEH capability disabled on KVM guest and recovery of PCI passthru device fails(CX5 / mlx5_core) (qemu-kvm) +Patch514: kvm-spapr-Fix-EEH-capability-issue-on-KVM-guest-for-PCI-.patch +# For bz#1970912 - Deployment fails with "Invalid or missing agent token received" +Patch515: kvm-Compress-lines-for-immediate-return.patch +# For bz#1970912 - Deployment fails with "Invalid or missing agent token received" +Patch516: kvm-file-posix-Handle-EINVAL-fallocate-return-value.patch +# For bz#1932917 - CVE-2021-3416 virt:rhel/qemu-kvm: QEMU: net: infinite loop in loopback mode may lead to stack overflow +Patch517: kvm-net-introduce-qemu_receive_packet.patch +# For bz#1932917 - CVE-2021-3416 virt:rhel/qemu-kvm: QEMU: net: infinite loop in loopback mode may lead to stack overflow +Patch518: kvm-e1000-switch-to-use-qemu_receive_packet-for-loopback.patch +# For bz#1932917 - CVE-2021-3416 virt:rhel/qemu-kvm: QEMU: net: infinite loop in loopback mode may lead to stack overflow +Patch519: kvm-dp8393x-switch-to-use-qemu_receive_packet-for-loopba.patch +# For bz#1932917 - CVE-2021-3416 virt:rhel/qemu-kvm: QEMU: net: infinite loop in loopback mode may lead to stack overflow +Patch520: kvm-sungem-switch-to-use-qemu_receive_packet-for-loopbac.patch +# For bz#1932917 - CVE-2021-3416 virt:rhel/qemu-kvm: QEMU: net: infinite loop in loopback mode may lead to stack overflow +Patch521: kvm-tx_pkt-switch-to-use-qemu_receive_packet_iov-for-loo.patch +# For bz#1932917 - CVE-2021-3416 virt:rhel/qemu-kvm: QEMU: net: infinite loop in loopback mode may lead to stack overflow +Patch522: kvm-rtl8139-switch-to-use-qemu_receive_packet-for-loopba.patch +# For bz#1932917 - CVE-2021-3416 virt:rhel/qemu-kvm: QEMU: net: infinite loop in loopback mode may lead to stack overflow +Patch523: kvm-pcnet-switch-to-use-qemu_receive_packet-for-loopback.patch +# For bz#1932917 - CVE-2021-3416 virt:rhel/qemu-kvm: QEMU: net: infinite loop in loopback mode may lead to stack overflow +Patch524: kvm-cadence_gem-switch-to-use-qemu_receive_packet-for-lo.patch +# For bz#1932917 - CVE-2021-3416 virt:rhel/qemu-kvm: QEMU: net: infinite loop in loopback mode may lead to stack overflow +Patch525: kvm-lan9118-switch-to-use-qemu_receive_packet-for-loopba.patch +# For bz#1967716 - RFE: rebuild guest agent to include public ssh injection api support +Patch526: kvm-glib-compat-add-g_unix_get_passwd_entry_qemu.patch +# For bz#1967716 - RFE: rebuild guest agent to include public ssh injection api support +Patch527: kvm-qga-add-ssh-add-remove-authorized-keys.patch +# For bz#1967716 - RFE: rebuild guest agent to include public ssh injection api support +Patch528: kvm-qga-add-reset-argument-to-ssh-add-authorized-keys.patch +# For bz#1967716 - RFE: rebuild guest agent to include public ssh injection api support +Patch529: kvm-qga-add-ssh-get-authorized-keys.patch +# For bz#1970819 - CVE-2021-3592 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (bootp) [rhel-8] +# For bz#1970835 - CVE-2021-3593 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (udp6) [rhel-8] +# For bz#1970843 - CVE-2021-3595 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (tftp) [rhel-8] +# For bz#1970853 - CVE-2021-3594 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (udp) [rhel-8] +Patch530: kvm-Add-mtod_check.patch +# For bz#1970819 - CVE-2021-3592 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (bootp) [rhel-8] +# For bz#1970835 - CVE-2021-3593 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (udp6) [rhel-8] +# For bz#1970843 - CVE-2021-3595 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (tftp) [rhel-8] +# For bz#1970853 - CVE-2021-3594 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (udp) [rhel-8] +Patch531: kvm-bootp-limit-vendor-specific-area-to-input-packet-mem.patch +# For bz#1970819 - CVE-2021-3592 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (bootp) [rhel-8] +Patch532: kvm-bootp-check-bootp_input-buffer-size.patch +# For bz#1970835 - CVE-2021-3593 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (udp6) [rhel-8] +Patch533: kvm-upd6-check-udp6_input-buffer-size.patch +# For bz#1970843 - CVE-2021-3595 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (tftp) [rhel-8] +Patch534: kvm-tftp-check-tftp_input-buffer-size.patch +# For bz#1970819 - CVE-2021-3592 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (bootp) [rhel-8] +# For bz#1970835 - CVE-2021-3593 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (udp6) [rhel-8] +# For bz#1970843 - CVE-2021-3595 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (tftp) [rhel-8] +# For bz#1970853 - CVE-2021-3594 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (udp) [rhel-8] +Patch535: kvm-tftp-introduce-a-header-structure.patch +# For bz#1970853 - CVE-2021-3594 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (udp) [rhel-8] +Patch536: kvm-udp-check-upd_input-buffer-size.patch +# For bz#1970819 - CVE-2021-3592 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (bootp) [rhel-8] +# For bz#1970835 - CVE-2021-3593 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (udp6) [rhel-8] +# For bz#1970843 - CVE-2021-3595 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (tftp) [rhel-8] +# For bz#1970853 - CVE-2021-3594 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (udp) [rhel-8] +Patch537: kvm-Fix-DHCP-broken-in-libslirp-v4.6.0.patch +# For bz#1982134 - QEMU core dump while booting guest with a non-exist fd on tap +Patch538: kvm-net-check-if-the-file-descriptor-is-valid-before-usi.patch +# For bz#1982134 - QEMU core dump while booting guest with a non-exist fd on tap +Patch539: kvm-net-detect-errors-from-probing-vnet-hdr-flag-for-TAP.patch +# For bz#1969848 - qemu-img convert hangs on aarch64 +Patch540: kvm-aio-wait-delegate-polling-of-main-AioContext-if-BQL-.patch +# For bz#1969848 - qemu-img convert hangs on aarch64 +Patch541: kvm-async-use-explicit-memory-barriers.patch +# For bz#1967496 - [virtio-fs] nfs/xfstest generic/089 generic/478 generic/632 failed +Patch542: kvm-virtiofsd-Disable-remote-posix-locks-by-default.patch +# For bz#1967496 - [virtio-fs] nfs/xfstest generic/089 generic/478 generic/632 failed +Patch543: kvm-virtiofsd-Fix-the-help-message-of-posix-lock.patch BuildRequires: wget BuildRequires: rpm-build @@ -1486,7 +1620,7 @@ buildldflags="VL_LDFLAGS=-Wl,--build-id" --audio-drv-list= \ --block-drv-ro-whitelist=vmdk,vhdx,vpc,https,ssh \ --with-coroutine=ucontext \ - --tls-priority=NORMAL \ + --tls-priority=@QEMU,SYSTEM \ --disable-bluez \ --disable-brlapi \ --enable-cap-ng \ @@ -2060,6 +2194,157 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %changelog +* Wed Aug 18 2021 Danilo Cesar Lemes de Paula - 4.2.0-58.el8 +- kvm-virtiofsd-Disable-remote-posix-locks-by-default.patch [bz#1967496] +- kvm-virtiofsd-Fix-the-help-message-of-posix-lock.patch [bz#1967496] +- Resolves: bz#1967496 + ([virtio-fs] nfs/xfstest generic/089 generic/478 generic/632 failed) + +* Wed Aug 04 2021 Miroslav Rezanina - 4.2.0-57 +- kvm-aio-wait-delegate-polling-of-main-AioContext-if-BQL-.patch [bz#1969848] +- kvm-async-use-explicit-memory-barriers.patch [bz#1969848] +- Resolves: bz#1969848 + (qemu-img convert hangs on aarch64) + +* Thu Jul 29 2021 Miroslav Rezanina - 4.2.0-56 +- kvm-glib-compat-add-g_unix_get_passwd_entry_qemu.patch [bz#1967716] +- kvm-qga-add-ssh-add-remove-authorized-keys.patch [bz#1967716] +- kvm-qga-add-reset-argument-to-ssh-add-authorized-keys.patch [bz#1967716] +- kvm-qga-add-ssh-get-authorized-keys.patch [bz#1967716] +- kvm-Add-mtod_check.patch [bz#1970819 bz#1970835 bz#1970843 bz#1970853] +- kvm-bootp-limit-vendor-specific-area-to-input-packet-mem.patch [bz#1970819 bz#1970835 bz#1970843 bz#1970853] +- kvm-bootp-check-bootp_input-buffer-size.patch [bz#1970819] +- kvm-upd6-check-udp6_input-buffer-size.patch [bz#1970835] +- kvm-tftp-check-tftp_input-buffer-size.patch [bz#1970843] +- kvm-tftp-introduce-a-header-structure.patch [bz#1970819 bz#1970835 bz#1970843 bz#1970853] +- kvm-udp-check-upd_input-buffer-size.patch [bz#1970853] +- kvm-Fix-DHCP-broken-in-libslirp-v4.6.0.patch [bz#1970819 bz#1970835 bz#1970843 bz#1970853] +- kvm-net-check-if-the-file-descriptor-is-valid-before-usi.patch [bz#1982134] +- kvm-net-detect-errors-from-probing-vnet-hdr-flag-for-TAP.patch [bz#1982134] +- Resolves: bz#1967716 + (RFE: rebuild guest agent to include public ssh injection api support) +- Resolves: bz#1970819 + (CVE-2021-3592 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (bootp) [rhel-8]) +- Resolves: bz#1970835 + (CVE-2021-3593 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (udp6) [rhel-8]) +- Resolves: bz#1970843 + (CVE-2021-3595 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (tftp) [rhel-8]) +- Resolves: bz#1970853 + (CVE-2021-3594 virt:rhel/qemu-kvm: QEMU: slirp: invalid pointer initialization may lead to information disclosure (udp) [rhel-8]) +- Resolves: bz#1982134 + (QEMU core dump while booting guest with a non-exist fd on tap) + +* Fri Jul 23 2021 Danilo Cesar Lemes de Paula - 4.2.0-55.el8 +- kvm-net-introduce-qemu_receive_packet.patch [bz#1932917] +- kvm-e1000-switch-to-use-qemu_receive_packet-for-loopback.patch [bz#1932917] +- kvm-dp8393x-switch-to-use-qemu_receive_packet-for-loopba.patch [bz#1932917] +- kvm-sungem-switch-to-use-qemu_receive_packet-for-loopbac.patch [bz#1932917] +- kvm-tx_pkt-switch-to-use-qemu_receive_packet_iov-for-loo.patch [bz#1932917] +- kvm-rtl8139-switch-to-use-qemu_receive_packet-for-loopba.patch [bz#1932917] +- kvm-pcnet-switch-to-use-qemu_receive_packet-for-loopback.patch [bz#1932917] +- kvm-cadence_gem-switch-to-use-qemu_receive_packet-for-lo.patch [bz#1932917] +- kvm-lan9118-switch-to-use-qemu_receive_packet-for-loopba.patch [bz#1932917] +- Resolves: bz#1932917 + (CVE-2021-3416 virt:rhel/qemu-kvm: QEMU: net: infinite loop in loopback mode may lead to stack overflow) + +* Thu Jul 22 2021 Danilo Cesar Lemes de Paula - 4.2.0-54.el8 +- kvm-redhat-Fix-unversioned-Obsoletes-warning.patch [bz#1967329] +- Resolves: bz#1967329 + (Make qemu-kvm use versioned obsoletes for qemu-kvm-ma and qemu-kvm-rhev) + +* Fri Jul 02 2021 Danilo Cesar Lemes de Paula - 4.2.0-53.el8 +- kvm-virtiofsd-Whitelist-fchmod.patch [bz#1967914] +- kvm-spapr-Fix-EEH-capability-issue-on-KVM-guest-for-PCI-.patch [bz#1957866] +- kvm-Compress-lines-for-immediate-return.patch [bz#1970912] +- kvm-file-posix-Handle-EINVAL-fallocate-return-value.patch [bz#1970912] +- Resolves: bz#1967914 + ([virtio-fs] virtiofsd quit when coping file to a folder in virtio-fs mounted volume(windows guest)) +- Resolves: bz#1957866 + (RHEL8.4 - EEH capability disabled on KVM guest and recovery of PCI passthru device fails(CX5 / mlx5_core) (qemu-kvm)) +- Resolves: bz#1970912 + (Deployment fails with "Invalid or missing agent token received") + +* Fri Jun 11 2021 Danilo Cesar Lemes de Paula - 4.2.0-52.el8 +- kvm-file-posix-Mitigate-file-fragmentation-with-extent-s.patch [bz#1877163] +- kvm-block-file-posix-Fix-problem-with-fallocate-PUNCH_HO.patch [bz#1944861] +- kvm-spapr-Remove-stale-comment-about-power-saving-LPCR-b.patch [bz#1969768] +- kvm-spapr-Set-LPCR-to-current-AIL-mode-when-starting-a-n.patch [bz#1969768] +- Resolves: bz#1877163 + ([FJ 8.3 Bug] The progress bar of the "virt-clone --nonsparse" command shows the progress rate exceeding 100%.) +- Resolves: bz#1944861 + (Qemu-img convert fails when source image is on gpfs) +- Resolves: bz#1969768 + ([ppc64le] Hotplug vcpu device hit call trace:[qemu output] KVM: unknown exit, hardware reason 7fff9ce87ed8) + +* Tue May 25 2021 Danilo Cesar Lemes de Paula - 4.2.0-51.el8 +- kvm-linux-headers-Add-VFIO_CCW_REQ_IRQ_INDEX.patch [bz#1940450] +- kvm-vfio-ccw-Connect-the-device-request-notifier.patch [bz#1940450] +- kvm-pc-bios-s390-ccw-fix-off-by-one-error.patch [bz#1942880] +- kvm-pc-bios-s390-ccw-break-loop-if-a-null-block-number-i.patch [bz#1942880] +- kvm-pc-bios-s390-ccw-don-t-try-to-read-the-next-block-if.patch [bz#1942880] +- Resolves: bz#1940450 + (RHEL8.5 - Mediated Device already in use by same domain we are booting (vfio-ccw/Multipath Testing) (kvm) - qemu-kvm part (also has kernel and libvirt parts)) +- Resolves: bz#1942880 + (RHEL8.4 Nightly[0322] - KVM guest fails to find zipl boot menu index (qemu-kvm)) + +* Wed May 05 2021 Danilo Cesar Lemes de Paula - 4.2.0-50.el8 +- kvm-hw-intc-arm_gic-Fix-interrupt-ID-in-GICD_SGIR-regist.patch [bz#1925430] +- kvm-libqos-usb-hcd-ehci-use-32-bit-write-for-config-regi.patch [bz#1842478] +- kvm-libqos-pci-pc-use-32-bit-write-for-EJ-register.patch [bz#1842478] +- kvm-memory-Revert-memory-accept-mismatching-sizes-in-mem.patch [bz#1842478] +- kvm-acpi-accept-byte-and-word-access-to-core-ACPI-regist.patch [bz#1842478] +- kvm-xhci-fix-valid.max_access_size-to-access-address-reg.patch [bz#1842478] +- kvm-softmmu-memory-Log-invalid-memory-accesses.patch [bz#1842478] +- Resolves: bz#1925430 + (CVE-2021-20221 virt:rhel/qemu-kvm: qemu: out-of-bound heap buffer access via an interrupt ID field [rhel-8.5.0]) +- Resolves: bz#1842478 + (CVE-2020-13754 virt:rhel/qemu-kvm: QEMU: msix: OOB access during mmio operations may lead to DoS [rhel-8.5.0]) + +* Wed Apr 28 2021 Danilo Cesar Lemes de Paula - 4.2.0-49.el8 +- kvm-net-remove-an-assert-call-in-eth_get_gso_type.patch [bz#1892350] +- kvm-e1000-fail-early-for-evil-descriptor.patch [bz#1930092] +- kvm-net-forbid-the-reentrant-RX.patch [bz#1859175] +- kvm-qemu-img-convert-Don-t-pre-zero-images.patch [bz#1855250] +- kvm-audio-audio_generic_get_buffer_in-should-honor-size.patch [bz#1932823] +- Resolves: bz#1892350 + (CVE-2020-27617 virt:rhel/qemu-kvm: QEMU: net: an assert failure via eth_get_gso_type [rhel-8.5.0]) +- Resolves: bz#1930092 + (CVE-2021-20257 virt:rhel/qemu-kvm: QEMU: net: e1000: infinite loop while processing transmit descriptors [rhel-8.5.0]) +- Resolves: bz#1859175 + (CVE-2020-15859 virt:rhel/qemu-kvm: QEMU: net: e1000e: use-after-free while sending packets [rhel-8]) +- Resolves: bz#1855250 + (qemu-img convert uses possibly slow pre-zeroing on block storage) +- Resolves: bz#1932823 + (after upgrade from 4.3 to 4.4 audio stops working in guests after couple of seconds) + +* Tue Mar 16 2021 Danilo Cesar Lemes de Paula - 4.2.0-48.el8 +- kvm-ide-atapi-check-logical-block-address-and-read-size-.patch [bz#1917451] +- Resolves: bz#1917451 + (CVE-2020-29443 virt:rhel/qemu-kvm: QEMU: ide: atapi: OOB access while processing read commands [rhel-8.4.0]) + +* Mon Mar 08 2021 Danilo Cesar Lemes de Paula - 4.2.0-47.el8 +- kvm-x86-cpu-Enable-AVX512_VP2INTERSECT-cpu-feature.patch [bz#1790620] +- kvm-target-i386-add-fast-short-REP-MOV-support.patch [bz#1790620] +- kvm-x86-cpu-Populate-SVM-CPUID-feature-bits.patch [bz#1790620] +- kvm-i386-Add-the-support-for-AMD-EPYC-3rd-generation-pro.patch [bz#1790620] +- Resolves: bz#1790620 + ([RFE] AMD Milan - Add KVM/support for EPYC-Milan CPU Model - Slow Train) + +* Wed Mar 03 2021 Danilo Cesar Lemes de Paula - 4.2.0-46.el8 +- kvm-redhat-makes-qemu-respect-system-s-crypto-profile.patch [bz#1902960] +- kvm-spapr-Adjust-firmware-path-of-PCI-devices.patch [bz#1912891] +- Resolves: bz#1902960 + (QEMU doesn't honour system crypto policies) +- Resolves: bz#1912891 + ([ppc64le] --disk cdimage.iso,bus=usb fails to boot) + +* Wed Feb 10 2021 Jon Maloy - 4.2.0-45.el8 +- kvm-virtiofsd-extract-lo_do_open-from-lo_open.patch [bz#1919111] +- kvm-virtiofsd-optionally-return-inode-pointer-from-lo_do.patch [bz#1919111] +- kvm-virtiofsd-prevent-opening-of-special-files-CVE-2020-.patch [bz#1919111] +- Resolves: bz#1919111 + (CVE-2020-35517 virt:rhel/qemu-kvm: QEMU: virtiofsd: potential privileged host device access from guest [rhel-8.4.0]) + * Tue Feb 02 2021 Jon Maloy - 4.2.0-44.el8 - kvm-spapr-Improve-handling-of-fdt-buffer-size.patch [bz#1901837] - kvm-spapr-Fold-h_cas_compose_response-into-h_client_arch.patch [bz#1901837]