* [PATCH] virtio-net: validate RSS indirections_len in post_load
@ 2026-03-23 13:15 Junjie Cao
2026-03-23 13:41 ` Daniel P. Berrangé
` (2 more replies)
0 siblings, 3 replies; 13+ messages in thread
From: Junjie Cao @ 2026-03-23 13:15 UTC (permalink / raw)
To: qemu-devel
Cc: jasowang, mst, yuri.benditovich, akihiko.odaki, qemu-stable,
junjie.cao
virtio_net_handle_rss() enforces that indirections_len is a non-zero
power of two no larger than VIRTIO_NET_RSS_MAX_TABLE_LEN, but
virtio_net_rss_post_load() applies none of these checks to values
restored from the migration stream.
A crafted migration stream can set indirections_len to 0. Even if it
also clears redirect, virtio_load() calls set_features_nocheck() after
the device vmstate (including the RSS subsection and its post_load) has
already been loaded, re-deriving redirect from the negotiated guest
features. When VIRTIO_NET_F_RSS was negotiated, redirect is set back
to true regardless of the migration stream value. The receive path
then computes
hash & (indirections_len - 1) /* wraps to 0xFFFFFFFF via int promotion */
and uses the result to index into indirections_table, which was not
allocated by the VMState loader when the element count is zero (see
vmstate_handle_alloc()), resulting in a NULL pointer dereference that
crashes QEMU:
#0 virtio_net_process_rss ../hw/net/virtio-net.c:1901
#1 virtio_net_receive_rcu ../hw/net/virtio-net.c:1921
#2 virtio_net_do_receive ../hw/net/virtio-net.c:2061
#3 nc_sendv_compat ../net/net.c:823
#4 qemu_deliver_packet_iov ../net/net.c:870
The RSS subsection is only loaded when rss_data.enabled is true (via
virtio_net_rss_needed()), and the command path always produces
indirections_len in {1, 2, 4, …, 128}, so an unconditional check
cannot reject a legitimate migration stream.
Fixes: e41b711485e5 ("virtio-net: add migration support for RSS and hash report")
Cc: qemu-stable@nongnu.org
Signed-off-by: Junjie Cao <junjie.cao@intel.com>
---
hw/net/virtio-net.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 2a5d642a64..3038836098 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -3427,6 +3427,15 @@ static int virtio_net_rss_post_load(void *opaque, int version_id)
n->rss_data.supported_hash_types = VIRTIO_NET_RSS_SUPPORTED_HASHES;
}
+ if (n->rss_data.indirections_len == 0 ||
+ n->rss_data.indirections_len > VIRTIO_NET_RSS_MAX_TABLE_LEN ||
+ !is_power_of_2(n->rss_data.indirections_len)) {
+ error_report("virtio-net: saved image has invalid RSS "
+ "indirections_len: %u",
+ n->rss_data.indirections_len);
+ return -EINVAL;
+ }
+
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH] virtio-net: validate RSS indirections_len in post_load 2026-03-23 13:15 [PATCH] virtio-net: validate RSS indirections_len in post_load Junjie Cao @ 2026-03-23 13:41 ` Daniel P. Berrangé 2026-03-23 13:53 ` Peter Maydell 2026-03-23 13:56 ` Michael S. Tsirkin 2026-03-24 6:04 ` Junjie Cao 2 siblings, 1 reply; 13+ messages in thread From: Daniel P. Berrangé @ 2026-03-23 13:41 UTC (permalink / raw) To: Junjie Cao Cc: qemu-devel, jasowang, mst, yuri.benditovich, akihiko.odaki, qemu-stable On Mon, Mar 23, 2026 at 09:15:31PM +0800, Junjie Cao wrote: > virtio_net_handle_rss() enforces that indirections_len is a non-zero > power of two no larger than VIRTIO_NET_RSS_MAX_TABLE_LEN, but > virtio_net_rss_post_load() applies none of these checks to values > restored from the migration stream. > > A crafted migration stream can set indirections_len to 0. Even if it The migration stream originating from the source QEMU is trusted. Is there a problem you can demonstrate with regular QEMU commands / versions, not crafting a malicious migration stream. > also clears redirect, virtio_load() calls set_features_nocheck() after > the device vmstate (including the RSS subsection and its post_load) has > already been loaded, re-deriving redirect from the negotiated guest > features. When VIRTIO_NET_F_RSS was negotiated, redirect is set back > to true regardless of the migration stream value. The receive path > then computes > > hash & (indirections_len - 1) /* wraps to 0xFFFFFFFF via int promotion */ > > and uses the result to index into indirections_table, which was not > allocated by the VMState loader when the element count is zero (see > vmstate_handle_alloc()), resulting in a NULL pointer dereference that > crashes QEMU: > > #0 virtio_net_process_rss ../hw/net/virtio-net.c:1901 > #1 virtio_net_receive_rcu ../hw/net/virtio-net.c:1921 > #2 virtio_net_do_receive ../hw/net/virtio-net.c:2061 > #3 nc_sendv_compat ../net/net.c:823 > #4 qemu_deliver_packet_iov ../net/net.c:870 > > The RSS subsection is only loaded when rss_data.enabled is true (via > virtio_net_rss_needed()), and the command path always produces > indirections_len in {1, 2, 4, …, 128}, so an unconditional check > cannot reject a legitimate migration stream. > > Fixes: e41b711485e5 ("virtio-net: add migration support for RSS and hash report") > Cc: qemu-stable@nongnu.org > Signed-off-by: Junjie Cao <junjie.cao@intel.com> > --- > hw/net/virtio-net.c | 9 +++++++++ > 1 file changed, 9 insertions(+) > > diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c > index 2a5d642a64..3038836098 100644 > --- a/hw/net/virtio-net.c > +++ b/hw/net/virtio-net.c > @@ -3427,6 +3427,15 @@ static int virtio_net_rss_post_load(void *opaque, int version_id) > n->rss_data.supported_hash_types = VIRTIO_NET_RSS_SUPPORTED_HASHES; > } > > + if (n->rss_data.indirections_len == 0 || > + n->rss_data.indirections_len > VIRTIO_NET_RSS_MAX_TABLE_LEN || > + !is_power_of_2(n->rss_data.indirections_len)) { > + error_report("virtio-net: saved image has invalid RSS " > + "indirections_len: %u", > + n->rss_data.indirections_len); > + return -EINVAL; > + } > + > return 0; > } > > -- > 2.43.0 > > With regards, Daniel -- |: https://berrange.com ~~ https://hachyderm.io/@berrange :| |: https://libvirt.org ~~ https://entangle-photo.org :| |: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :| ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] virtio-net: validate RSS indirections_len in post_load 2026-03-23 13:41 ` Daniel P. Berrangé @ 2026-03-23 13:53 ` Peter Maydell 2026-03-23 13:57 ` Michael S. Tsirkin 2026-03-23 14:11 ` Daniel P. Berrangé 0 siblings, 2 replies; 13+ messages in thread From: Peter Maydell @ 2026-03-23 13:53 UTC (permalink / raw) To: Daniel P. Berrangé Cc: Junjie Cao, qemu-devel, jasowang, mst, yuri.benditovich, akihiko.odaki, qemu-stable On Mon, 23 Mar 2026 at 13:43, Daniel P. Berrangé <berrange@redhat.com> wrote: > > On Mon, Mar 23, 2026 at 09:15:31PM +0800, Junjie Cao wrote: > > virtio_net_handle_rss() enforces that indirections_len is a non-zero > > power of two no larger than VIRTIO_NET_RSS_MAX_TABLE_LEN, but > > virtio_net_rss_post_load() applies none of these checks to values > > restored from the migration stream. > > > > A crafted migration stream can set indirections_len to 0. Even if it > > The migration stream originating from the source QEMU is trusted. Is it? In https://www.qemu.org/docs/master/system/security.html we say: # The following entities are untrusted, meaning that they may be buggy # or malicious: # * Guest # * User-facing interfaces (e.g. VNC, SPICE, WebSocket) # * Network protocols (e.g. NBD, live migration) # * User-supplied files (e.g. disk images, kernels, device trees) # * Passthrough devices (e.g. PCI, USB) which explicitly lists "live migration" as an untrusted entity. I would definitely be extremely cautious about having a threat model where I had to distrust inbound migration data, but the above does suggest we aim to handle that, and we have I think in the past taken patches which add sanity-checking to the migration data. thanks -- PMM ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] virtio-net: validate RSS indirections_len in post_load 2026-03-23 13:53 ` Peter Maydell @ 2026-03-23 13:57 ` Michael S. Tsirkin 2026-03-23 14:56 ` Daniel P. Berrangé 2026-03-23 14:11 ` Daniel P. Berrangé 1 sibling, 1 reply; 13+ messages in thread From: Michael S. Tsirkin @ 2026-03-23 13:57 UTC (permalink / raw) To: Peter Maydell Cc: Daniel P. Berrangé, Junjie Cao, qemu-devel, jasowang, yuri.benditovich, akihiko.odaki, qemu-stable On Mon, Mar 23, 2026 at 01:53:53PM +0000, Peter Maydell wrote: > On Mon, 23 Mar 2026 at 13:43, Daniel P. Berrangé <berrange@redhat.com> wrote: > > > > On Mon, Mar 23, 2026 at 09:15:31PM +0800, Junjie Cao wrote: > > > virtio_net_handle_rss() enforces that indirections_len is a non-zero > > > power of two no larger than VIRTIO_NET_RSS_MAX_TABLE_LEN, but > > > virtio_net_rss_post_load() applies none of these checks to values > > > restored from the migration stream. > > > > > > A crafted migration stream can set indirections_len to 0. Even if it > > > > The migration stream originating from the source QEMU is trusted. > > Is it? In https://www.qemu.org/docs/master/system/security.html we say: > > # The following entities are untrusted, meaning that they may be buggy > # or malicious: > > # * Guest > # * User-facing interfaces (e.g. VNC, SPICE, WebSocket) > # * Network protocols (e.g. NBD, live migration) > # * User-supplied files (e.g. disk images, kernels, device trees) > # * Passthrough devices (e.g. PCI, USB) > > which explicitly lists "live migration" as an untrusted entity. > > I would definitely be extremely cautious about having a threat > model where I had to distrust inbound migration data, but the > above does suggest we aim to handle that, and we have I think > in the past taken patches which add sanity-checking to the > migration data. > > thanks > -- PMM And we even assigned a low priority CVEs to these. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] virtio-net: validate RSS indirections_len in post_load 2026-03-23 13:57 ` Michael S. Tsirkin @ 2026-03-23 14:56 ` Daniel P. Berrangé 2026-03-23 15:25 ` Peter Maydell 0 siblings, 1 reply; 13+ messages in thread From: Daniel P. Berrangé @ 2026-03-23 14:56 UTC (permalink / raw) To: Michael S. Tsirkin Cc: Peter Maydell, Junjie Cao, qemu-devel, jasowang, yuri.benditovich, akihiko.odaki, qemu-stable On Mon, Mar 23, 2026 at 09:57:24AM -0400, Michael S. Tsirkin wrote: > On Mon, Mar 23, 2026 at 01:53:53PM +0000, Peter Maydell wrote: > > On Mon, 23 Mar 2026 at 13:43, Daniel P. Berrangé <berrange@redhat.com> wrote: > > > > > > On Mon, Mar 23, 2026 at 09:15:31PM +0800, Junjie Cao wrote: > > > > virtio_net_handle_rss() enforces that indirections_len is a non-zero > > > > power of two no larger than VIRTIO_NET_RSS_MAX_TABLE_LEN, but > > > > virtio_net_rss_post_load() applies none of these checks to values > > > > restored from the migration stream. > > > > > > > > A crafted migration stream can set indirections_len to 0. Even if it > > > > > > The migration stream originating from the source QEMU is trusted. > > > > Is it? In https://www.qemu.org/docs/master/system/security.html we say: > > > > # The following entities are untrusted, meaning that they may be buggy > > # or malicious: > > > > # * Guest > > # * User-facing interfaces (e.g. VNC, SPICE, WebSocket) > > # * Network protocols (e.g. NBD, live migration) > > # * User-supplied files (e.g. disk images, kernels, device trees) > > # * Passthrough devices (e.g. PCI, USB) > > > > which explicitly lists "live migration" as an untrusted entity. > > > > I would definitely be extremely cautious about having a threat > > model where I had to distrust inbound migration data, but the > > above does suggest we aim to handle that, and we have I think > > in the past taken patches which add sanity-checking to the > > migration data. > > And we even assigned a low priority CVEs to these. Do you have an example of that ? With regards, Daniel -- |: https://berrange.com ~~ https://hachyderm.io/@berrange :| |: https://libvirt.org ~~ https://entangle-photo.org :| |: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :| ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] virtio-net: validate RSS indirections_len in post_load 2026-03-23 14:56 ` Daniel P. Berrangé @ 2026-03-23 15:25 ` Peter Maydell 2026-03-23 15:58 ` Daniel P. Berrangé 0 siblings, 1 reply; 13+ messages in thread From: Peter Maydell @ 2026-03-23 15:25 UTC (permalink / raw) To: Daniel P. Berrangé Cc: Michael S. Tsirkin, Junjie Cao, qemu-devel, jasowang, yuri.benditovich, akihiko.odaki, qemu-stable On Mon, 23 Mar 2026 at 14:56, Daniel P. Berrangé <berrange@redhat.com> wrote: > > On Mon, Mar 23, 2026 at 09:57:24AM -0400, Michael S. Tsirkin wrote: > > On Mon, Mar 23, 2026 at 01:53:53PM +0000, Peter Maydell wrote: > > > On Mon, 23 Mar 2026 at 13:43, Daniel P. Berrangé <berrange@redhat.com> wrote: > > > > > > > > On Mon, Mar 23, 2026 at 09:15:31PM +0800, Junjie Cao wrote: > > > > > virtio_net_handle_rss() enforces that indirections_len is a non-zero > > > > > power of two no larger than VIRTIO_NET_RSS_MAX_TABLE_LEN, but > > > > > virtio_net_rss_post_load() applies none of these checks to values > > > > > restored from the migration stream. > > > > > > > > > > A crafted migration stream can set indirections_len to 0. Even if it > > > > > > > > The migration stream originating from the source QEMU is trusted. > > > > > > Is it? In https://www.qemu.org/docs/master/system/security.html we say: > > > > > > # The following entities are untrusted, meaning that they may be buggy > > > # or malicious: > > > > > > # * Guest > > > # * User-facing interfaces (e.g. VNC, SPICE, WebSocket) > > > # * Network protocols (e.g. NBD, live migration) > > > # * User-supplied files (e.g. disk images, kernels, device trees) > > > # * Passthrough devices (e.g. PCI, USB) > > > > > > which explicitly lists "live migration" as an untrusted entity. > > > > > > I would definitely be extremely cautious about having a threat > > > model where I had to distrust inbound migration data, but the > > > above does suggest we aim to handle that, and we have I think > > > in the past taken patches which add sanity-checking to the > > > migration data. > > > > And we even assigned a low priority CVEs to these. > > Do you have an example of that ? Here's one from last year: https://access.redhat.com/security/cve/cve-2025-54566 I vaguely recall we had a set of them some years ago too (probably somebody specifically looking for flaws in the category). https://access.redhat.com/security/cve/cve-2013-4536 might be an example of that. -- PMM ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] virtio-net: validate RSS indirections_len in post_load 2026-03-23 15:25 ` Peter Maydell @ 2026-03-23 15:58 ` Daniel P. Berrangé 2026-03-23 16:15 ` Peter Maydell 0 siblings, 1 reply; 13+ messages in thread From: Daniel P. Berrangé @ 2026-03-23 15:58 UTC (permalink / raw) To: Peter Maydell Cc: Michael S. Tsirkin, Junjie Cao, qemu-devel, jasowang, yuri.benditovich, akihiko.odaki, qemu-stable On Mon, Mar 23, 2026 at 03:25:10PM +0000, Peter Maydell wrote: > On Mon, 23 Mar 2026 at 14:56, Daniel P. Berrangé <berrange@redhat.com> wrote: > > > > On Mon, Mar 23, 2026 at 09:57:24AM -0400, Michael S. Tsirkin wrote: > > > On Mon, Mar 23, 2026 at 01:53:53PM +0000, Peter Maydell wrote: > > > > On Mon, 23 Mar 2026 at 13:43, Daniel P. Berrangé <berrange@redhat.com> wrote: > > > > > > > > > > On Mon, Mar 23, 2026 at 09:15:31PM +0800, Junjie Cao wrote: > > > > > > virtio_net_handle_rss() enforces that indirections_len is a non-zero > > > > > > power of two no larger than VIRTIO_NET_RSS_MAX_TABLE_LEN, but > > > > > > virtio_net_rss_post_load() applies none of these checks to values > > > > > > restored from the migration stream. > > > > > > > > > > > > A crafted migration stream can set indirections_len to 0. Even if it > > > > > > > > > > The migration stream originating from the source QEMU is trusted. > > > > > > > > Is it? In https://www.qemu.org/docs/master/system/security.html we say: > > > > > > > > # The following entities are untrusted, meaning that they may be buggy > > > > # or malicious: > > > > > > > > # * Guest > > > > # * User-facing interfaces (e.g. VNC, SPICE, WebSocket) > > > > # * Network protocols (e.g. NBD, live migration) > > > > # * User-supplied files (e.g. disk images, kernels, device trees) > > > > # * Passthrough devices (e.g. PCI, USB) > > > > > > > > which explicitly lists "live migration" as an untrusted entity. > > > > > > > > I would definitely be extremely cautious about having a threat > > > > model where I had to distrust inbound migration data, but the > > > > above does suggest we aim to handle that, and we have I think > > > > in the past taken patches which add sanity-checking to the > > > > migration data. > > > > > > And we even assigned a low priority CVEs to these. > > > > Do you have an example of that ? > > Here's one from last year: > https://access.redhat.com/security/cve/cve-2025-54566 I think this one is valid, because it involves incorrect handling of settings that are controlled by the guest OS. There's no external party claimed to be modifying the migration stream IIUC > I vaguely recall we had a set of them some years ago too > (probably somebody specifically looking for flaws in the > category). https://access.redhat.com/security/cve/cve-2013-4536 > might be an example of that. I think this one is probably issued in error. If we're considering that the migration data stream is modifiable by an attacker, the implication is that the attacker has arbitrary read and write over the entire of guest RAM. That in turn implies no guest OS can ever be trusted after a migration has been performed, That is certainly not the case though. We establish trust in the guest RAM after migration by protecting the live migration data stream with TLS (or an equivalent mechanism external to QEMU), and including some mechanism for authenticating the connections. We prove the incoming connection is from the expected source QEMU. That protection also applies to the VMstate data. So the only entity would can give us malicious vmstate data would be the source QEMU. The risk would appear to be that the source QEMU has been compromised, but has been unable to break out into the source host OS. The migration data would thus be leveraged as a way to break out into the target host OS instead. This feels dubious though. The source QEMU and target QEMU would be assumed to be using the same security facilities (running non-root, using seccomp, using selinux/apparmor, using namespaces, etc). So if it could not break out of QEMU on the source host, I can't see that migration would make it possible todo that on the target host either. The save/restore of VM state to/from disk, for the purpose of VM snapshotting is slightly different as we don't have a network channel involved. None the less, I'd claim that the saved snapshot file must be considered trusted, because it again contains data (guest RAM) that we inherently must trust. If an attacker has the ability to modify a saved state file, then we've already lost all trust. I can see scope for CVEs in QEMU wrt vmstate, if: * a malicious guest OS driver is able to configure some aspect of a virtual device, such that it then causes misbehaviour in later handling of the VM state. IIUC the recent cve-2025-54566 is an example of that * untrusted data being processed by the virtual device, causes the device to get itself into a state which then causes misbehaviour in handling of VM state. I don't accept scope for CVEs in QEMU for an external attacker modifying the migration data stream or saved state file contents though. AFAICS, such possibilities imply gross misconfiguration of QEMU by the mgmt app, and should be CVEs in the mgmt app instead. With regards, Daniel -- |: https://berrange.com ~~ https://hachyderm.io/@berrange :| |: https://libvirt.org ~~ https://entangle-photo.org :| |: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :| ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] virtio-net: validate RSS indirections_len in post_load 2026-03-23 15:58 ` Daniel P. Berrangé @ 2026-03-23 16:15 ` Peter Maydell 2026-03-23 16:45 ` Daniel P. Berrangé 0 siblings, 1 reply; 13+ messages in thread From: Peter Maydell @ 2026-03-23 16:15 UTC (permalink / raw) To: Daniel P. Berrangé Cc: Michael S. Tsirkin, Junjie Cao, qemu-devel, jasowang, qemu-stable, Paolo Bonzini, Stefan Hajnoczi On Mon, 23 Mar 2026 at 15:58, Daniel P. Berrangé <berrange@redhat.com> wrote: > > On Mon, Mar 23, 2026 at 03:25:10PM +0000, Peter Maydell wrote: > > On Mon, 23 Mar 2026 at 14:56, Daniel P. Berrangé <berrange@redhat.com> wrote: > > > > > > On Mon, Mar 23, 2026 at 09:57:24AM -0400, Michael S. Tsirkin wrote: > > > > On Mon, Mar 23, 2026 at 01:53:53PM +0000, Peter Maydell wrote: > > > > > On Mon, 23 Mar 2026 at 13:43, Daniel P. Berrangé <berrange@redhat.com> wrote: > > > > > > > > > > > > On Mon, Mar 23, 2026 at 09:15:31PM +0800, Junjie Cao wrote: > > > > > > > virtio_net_handle_rss() enforces that indirections_len is a non-zero > > > > > > > power of two no larger than VIRTIO_NET_RSS_MAX_TABLE_LEN, but > > > > > > > virtio_net_rss_post_load() applies none of these checks to values > > > > > > > restored from the migration stream. > > > > > > > > > > > > > > A crafted migration stream can set indirections_len to 0. Even if it > > > > > > > > > > > > The migration stream originating from the source QEMU is trusted. > > > > > > > > > > Is it? In https://www.qemu.org/docs/master/system/security.html we say: > > > > > > > > > > # The following entities are untrusted, meaning that they may be buggy > > > > > # or malicious: > > > > > > > > > > # * Guest > > > > > # * User-facing interfaces (e.g. VNC, SPICE, WebSocket) > > > > > # * Network protocols (e.g. NBD, live migration) > > > > > # * User-supplied files (e.g. disk images, kernels, device trees) > > > > > # * Passthrough devices (e.g. PCI, USB) > > > > > > > > > > which explicitly lists "live migration" as an untrusted entity. > > > > > > > > > > I would definitely be extremely cautious about having a threat > > > > > model where I had to distrust inbound migration data, but the > > > > > above does suggest we aim to handle that, and we have I think > > > > > in the past taken patches which add sanity-checking to the > > > > > migration data. > > > > > > > > And we even assigned a low priority CVEs to these. > > > > > > Do you have an example of that ? > > > > Here's one from last year: > > https://access.redhat.com/security/cve/cve-2025-54566 > > I think this one is valid, because it involves incorrect handling > of settings that are controlled by the guest OS. There's no > external party claimed to be modifying the migration stream IIUC I think the "guest OS sets things wrongly" is CVE-2025-54567, and 54566 is specifically for the "migration stream is malicious" case. The commit fixing them: https://gitlab.com/qemu-project/qemu/-/commit/cad9aa6fbdccd95e56e10cfa57c354a20a333717 fixes both at the same time, by providing a validation function and calling it both (a) when the guest OS writes the settings and (b) in post_load. If we trust migration data then we don't need to validate it in post-load, we could just say "make sure your source QEMU has the fix for (a) and that you've restarted the guest". > > I vaguely recall we had a set of them some years ago too > > (probably somebody specifically looking for flaws in the > > category). https://access.redhat.com/security/cve/cve-2013-4536 > > might be an example of that. > > I think this one is probably issued in error. > > If we're considering that the migration data stream is modifiable > by an attacker, the implication is that the attacker has arbitrary > read and write over the entire of guest RAM. That in turn implies > no guest OS can ever be trusted after a migration has been performed, > That is certainly not the case though. Trusted by whom? If I'm a cloud vendor then I don't trust the guest OS in the first place. QEMU itself should consider everything in guest RAM untrusted data, because it's guest-controlled. You can probably have setups where the user who owns the VM might be able to modify the migration stream but no third party can (e.g. if you give them the ability to vmsave/vmload to a file that they own), in the same way you can give the VM owner the ability to directly write to the disk images the VM is using without that being a way for them to escape to the host. > I don't accept scope for CVEs in QEMU for an external attacker modifying > the migration data stream or saved state file contents though. AFAICS, > such possibilities imply gross misconfiguration of QEMU by the mgmt app, > and should be CVEs in the mgmt app instead. I agree that you have a pretty weird threat/operating model if you allow the migration-stream to be considered untrusted, because it's reasonable and sensible to secure it. But I have a vague recollection that this language is in the doc precisely because at least one person/party has argued in the past in favour of treating the migration stream as on the security boundary. I don't object to our deciding we want to call the migration-stream trusted -- but I do think this is a policy change from our current stance. Paolo, Stefan, do you happen to remember anything about this ? thanks -- PMM ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] virtio-net: validate RSS indirections_len in post_load 2026-03-23 16:15 ` Peter Maydell @ 2026-03-23 16:45 ` Daniel P. Berrangé 0 siblings, 0 replies; 13+ messages in thread From: Daniel P. Berrangé @ 2026-03-23 16:45 UTC (permalink / raw) To: Peter Maydell Cc: Michael S. Tsirkin, Junjie Cao, qemu-devel, jasowang, qemu-stable, Paolo Bonzini, Stefan Hajnoczi On Mon, Mar 23, 2026 at 04:15:56PM +0000, Peter Maydell wrote: > On Mon, 23 Mar 2026 at 15:58, Daniel P. Berrangé <berrange@redhat.com> wrote: > > > > On Mon, Mar 23, 2026 at 03:25:10PM +0000, Peter Maydell wrote: > > > On Mon, 23 Mar 2026 at 14:56, Daniel P. Berrangé <berrange@redhat.com> wrote: > > > > > > > > On Mon, Mar 23, 2026 at 09:57:24AM -0400, Michael S. Tsirkin wrote: > > > > > On Mon, Mar 23, 2026 at 01:53:53PM +0000, Peter Maydell wrote: > > > > > > On Mon, 23 Mar 2026 at 13:43, Daniel P. Berrangé <berrange@redhat.com> wrote: > > > > > > > > > > > > > > On Mon, Mar 23, 2026 at 09:15:31PM +0800, Junjie Cao wrote: > > > > > > > > virtio_net_handle_rss() enforces that indirections_len is a non-zero > > > > > > > > power of two no larger than VIRTIO_NET_RSS_MAX_TABLE_LEN, but > > > > > > > > virtio_net_rss_post_load() applies none of these checks to values > > > > > > > > restored from the migration stream. > > > > > > > > > > > > > > > > A crafted migration stream can set indirections_len to 0. Even if it > > > > > > > > > > > > > > The migration stream originating from the source QEMU is trusted. > > > > > > > > > > > > Is it? In https://www.qemu.org/docs/master/system/security.html we say: > > > > > > > > > > > > # The following entities are untrusted, meaning that they may be buggy > > > > > > # or malicious: > > > > > > > > > > > > # * Guest > > > > > > # * User-facing interfaces (e.g. VNC, SPICE, WebSocket) > > > > > > # * Network protocols (e.g. NBD, live migration) > > > > > > # * User-supplied files (e.g. disk images, kernels, device trees) > > > > > > # * Passthrough devices (e.g. PCI, USB) > > > > > > > > > > > > which explicitly lists "live migration" as an untrusted entity. > > > > > > > > > > > > I would definitely be extremely cautious about having a threat > > > > > > model where I had to distrust inbound migration data, but the > > > > > > above does suggest we aim to handle that, and we have I think > > > > > > in the past taken patches which add sanity-checking to the > > > > > > migration data. > > > > > > > > > > And we even assigned a low priority CVEs to these. > > > > > > > > Do you have an example of that ? > > > > > > Here's one from last year: > > > https://access.redhat.com/security/cve/cve-2025-54566 > > > > I think this one is valid, because it involves incorrect handling > > of settings that are controlled by the guest OS. There's no > > external party claimed to be modifying the migration stream IIUC > > I think the "guest OS sets things wrongly" is CVE-2025-54567, > and 54566 is specifically for the "migration stream is malicious" > case. The commit fixing them: > https://gitlab.com/qemu-project/qemu/-/commit/cad9aa6fbdccd95e56e10cfa57c354a20a333717 > fixes both at the same time, by providing a validation function > and calling it both (a) when the guest OS writes the settings > and (b) in post_load. If we trust migration data then we don't need > to validate it in post-load, we could just say "make sure your > source QEMU has the fix for (a) and that you've restarted the guest". Ah, yes, the pairing of CVEs is key here. Our users expect their workloads to execute without interruption. Thus our story for fixing CVEs bugs without guest impact is to live migrate the guest onto the fixed CVE. So in this case, I think we do need the fix in post_load as a way to mitigate the root cause CVE in existing workloads that cannot be restarted. > > > I vaguely recall we had a set of them some years ago too > > > (probably somebody specifically looking for flaws in the > > > category). https://access.redhat.com/security/cve/cve-2013-4536 > > > might be an example of that. > > > > I think this one is probably issued in error. > > > > If we're considering that the migration data stream is modifiable > > by an attacker, the implication is that the attacker has arbitrary > > read and write over the entire of guest RAM. That in turn implies > > no guest OS can ever be trusted after a migration has been performed, > > > That is certainly not the case though. > > Trusted by whom? If I'm a cloud vendor then I don't trust the > guest OS in the first place. QEMU itself should consider everything > in guest RAM untrusted data, because it's guest-controlled. > You can probably have setups where the user who owns the VM might > be able to modify the migration stream but no third party can > (e.g. if you give them the ability to vmsave/vmload to a file > that they own), in the same way you can give the VM owner the > ability to directly write to the disk images the VM is using > without that being a way for them to escape to the host. Hmm, yes, load/save into a file that the guest owner controls is a good point. I'm fairly sure I recall that OpenStack allows for exactly that scenario. So the host owner would need to treat the vmstate as potentially hostile in that case. IOW, bugs that affect handling of vm state that merely result in an assert are merely self-inflicted DoS by the guest owner. Bugs that could be leveraged to exploit QEMU itself should be CVE worthy. So even if the migration stream can be considerd trusted, we can't trust vmstate in general due to the load/save scenario. This is probably a case where we ought to have had a host controlled digital signature over vmstate data to validate its integrity. > > I don't accept scope for CVEs in QEMU for an external attacker modifying > > the migration data stream or saved state file contents though. AFAICS, > > such possibilities imply gross misconfiguration of QEMU by the mgmt app, > > and should be CVEs in the mgmt app instead. > > I agree that you have a pretty weird threat/operating model if > you allow the migration-stream to be considered untrusted, because > it's reasonable and sensible to secure it. But I have a vague > recollection that this language is in the doc precisely because > at least one person/party has argued in the past in favour of > treating the migration stream as on the security boundary. I don't > object to our deciding we want to call the migration-stream trusted -- > but I do think this is a policy change from our current stance. Possibly we should clarify the language to say that the vmstate format is untrusted due to the load/save possibility to guest owner controlled storage. With regards, Daniel -- |: https://berrange.com ~~ https://hachyderm.io/@berrange :| |: https://libvirt.org ~~ https://entangle-photo.org :| |: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :| ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] virtio-net: validate RSS indirections_len in post_load 2026-03-23 13:53 ` Peter Maydell 2026-03-23 13:57 ` Michael S. Tsirkin @ 2026-03-23 14:11 ` Daniel P. Berrangé 2026-03-23 15:33 ` Peter Maydell 1 sibling, 1 reply; 13+ messages in thread From: Daniel P. Berrangé @ 2026-03-23 14:11 UTC (permalink / raw) To: Peter Maydell Cc: Junjie Cao, qemu-devel, jasowang, mst, yuri.benditovich, akihiko.odaki, qemu-stable On Mon, Mar 23, 2026 at 01:53:53PM +0000, Peter Maydell wrote: > On Mon, 23 Mar 2026 at 13:43, Daniel P. Berrangé <berrange@redhat.com> wrote: > > > > On Mon, Mar 23, 2026 at 09:15:31PM +0800, Junjie Cao wrote: > > > virtio_net_handle_rss() enforces that indirections_len is a non-zero > > > power of two no larger than VIRTIO_NET_RSS_MAX_TABLE_LEN, but > > > virtio_net_rss_post_load() applies none of these checks to values > > > restored from the migration stream. > > > > > > A crafted migration stream can set indirections_len to 0. Even if it > > > > The migration stream originating from the source QEMU is trusted. > > Is it? In https://www.qemu.org/docs/master/system/security.html we say: > > # The following entities are untrusted, meaning that they may be buggy > # or malicious: > > # * Guest > # * User-facing interfaces (e.g. VNC, SPICE, WebSocket) > # * Network protocols (e.g. NBD, live migration) > # * User-supplied files (e.g. disk images, kernels, device trees) > # * Passthrough devices (e.g. PCI, USB) > > which explicitly lists "live migration" as an untrusted entity. > > I would definitely be extremely cautious about having a threat > model where I had to distrust inbound migration data, but the > above does suggest we aim to handle that, and we have I think > in the past taken patches which add sanity-checking to the > migration data. My view of the migration stream is that we authenticate the client at the point of connection (either explicitly with SASL, or implicitly with a x509 certificate validation), and protect the data stream integrity with TLS, or equivalent. For the vmstate data, we simply expect that to reflect the current QEMU configuration, and variation of that is liable to lead to a crash or worse. With regards, Daniel -- |: https://berrange.com ~~ https://hachyderm.io/@berrange :| |: https://libvirt.org ~~ https://entangle-photo.org :| |: https://pixelfed.art/berrange ~~ https://fstop138.berrange.com :| ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] virtio-net: validate RSS indirections_len in post_load 2026-03-23 14:11 ` Daniel P. Berrangé @ 2026-03-23 15:33 ` Peter Maydell 0 siblings, 0 replies; 13+ messages in thread From: Peter Maydell @ 2026-03-23 15:33 UTC (permalink / raw) To: Daniel P. Berrangé Cc: Junjie Cao, qemu-devel, jasowang, mst, qemu-stable On Mon, 23 Mar 2026 at 14:12, Daniel P. Berrangé <berrange@redhat.com> wrote: > > On Mon, Mar 23, 2026 at 01:53:53PM +0000, Peter Maydell wrote: > > I would definitely be extremely cautious about having a threat > > model where I had to distrust inbound migration data, but the > > above does suggest we aim to handle that, and we have I think > > in the past taken patches which add sanity-checking to the > > migration data. > > My view of the migration stream is that we authenticate the client > at the point of connection (either explicitly with SASL, or implicitly > with a x509 certificate validation), and protect the data stream > integrity with TLS, or equivalent. This seems like it would be useful clarifying information to add to the security.rst document under the "Sensitive configurations" subsection as part of documenting what we recommend, even if we decide that we want to continue treating malicious migration-data as part of our threat model / security boundary. -- PMM ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] virtio-net: validate RSS indirections_len in post_load 2026-03-23 13:15 [PATCH] virtio-net: validate RSS indirections_len in post_load Junjie Cao 2026-03-23 13:41 ` Daniel P. Berrangé @ 2026-03-23 13:56 ` Michael S. Tsirkin 2026-03-24 6:04 ` Junjie Cao 2 siblings, 0 replies; 13+ messages in thread From: Michael S. Tsirkin @ 2026-03-23 13:56 UTC (permalink / raw) To: Junjie Cao Cc: qemu-devel, jasowang, yuri.benditovich, akihiko.odaki, qemu-stable On Mon, Mar 23, 2026 at 09:15:31PM +0800, Junjie Cao wrote: > virtio_net_handle_rss() enforces that indirections_len is a non-zero > power of two no larger than VIRTIO_NET_RSS_MAX_TABLE_LEN, but > virtio_net_rss_post_load() applies none of these checks to values > restored from the migration stream. > > A crafted migration stream can set indirections_len to 0. Even if it > also clears redirect, virtio_load() calls set_features_nocheck() after > the device vmstate (including the RSS subsection and its post_load) has > already been loaded, re-deriving redirect from the negotiated guest > features. When VIRTIO_NET_F_RSS was negotiated, redirect is set back > to true regardless of the migration stream value. The receive path > then computes > > hash & (indirections_len - 1) /* wraps to 0xFFFFFFFF via int promotion */ > > and uses the result to index into indirections_table, which was not > allocated by the VMState loader when the element count is zero (see > vmstate_handle_alloc()), resulting in a NULL pointer dereference that > crashes QEMU: > > #0 virtio_net_process_rss ../hw/net/virtio-net.c:1901 > #1 virtio_net_receive_rcu ../hw/net/virtio-net.c:1921 > #2 virtio_net_do_receive ../hw/net/virtio-net.c:2061 > #3 nc_sendv_compat ../net/net.c:823 > #4 qemu_deliver_packet_iov ../net/net.c:870 > > The RSS subsection is only loaded when rss_data.enabled is true (via > virtio_net_rss_needed()), and the command path always produces > indirections_len in {1, 2, 4, …, 128}, so an unconditional check > cannot reject a legitimate migration stream. > > Fixes: e41b711485e5 ("virtio-net: add migration support for RSS and hash report") > Cc: qemu-stable@nongnu.org > Signed-off-by: Junjie Cao <junjie.cao@intel.com> Thanks for the patch! Yet something to improve: > --- > hw/net/virtio-net.c | 9 +++++++++ > 1 file changed, 9 insertions(+) > > diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c > index 2a5d642a64..3038836098 100644 > --- a/hw/net/virtio-net.c > +++ b/hw/net/virtio-net.c > @@ -3427,6 +3427,15 @@ static int virtio_net_rss_post_load(void *opaque, int version_id) > n->rss_data.supported_hash_types = VIRTIO_NET_RSS_SUPPORTED_HASHES; > } > > + if (n->rss_data.indirections_len == 0 || not needed since it's included in is_power_of_2 check below? > + n->rss_data.indirections_len > VIRTIO_NET_RSS_MAX_TABLE_LEN || > + !is_power_of_2(n->rss_data.indirections_len)) { with == 0 removed, the logic is duplicated from virtio_net_device_realize. How about factoring it out to a helper? > + error_report("virtio-net: saved image has invalid RSS " > + "indirections_len: %u", > + n->rss_data.indirections_len); > + return -EINVAL; > + } > + > return 0; > } > > -- > 2.43.0 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] virtio-net: validate RSS indirections_len in post_load 2026-03-23 13:15 [PATCH] virtio-net: validate RSS indirections_len in post_load Junjie Cao 2026-03-23 13:41 ` Daniel P. Berrangé 2026-03-23 13:56 ` Michael S. Tsirkin @ 2026-03-24 6:04 ` Junjie Cao 2 siblings, 0 replies; 13+ messages in thread From: Junjie Cao @ 2026-03-24 6:04 UTC (permalink / raw) To: qemu-devel; +Cc: mst, berrange, peter.maydell, jasowang, junjie.cao Thanks everyone for the discussion, very rewarding for me. I've sent v2, addressing Michael's review. I also tightened the commit message to scope the trigger explicitly to corrupted save files and crafted migration streams. Thanks, Junjie ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-03-24 6:05 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-03-23 13:15 [PATCH] virtio-net: validate RSS indirections_len in post_load Junjie Cao 2026-03-23 13:41 ` Daniel P. Berrangé 2026-03-23 13:53 ` Peter Maydell 2026-03-23 13:57 ` Michael S. Tsirkin 2026-03-23 14:56 ` Daniel P. Berrangé 2026-03-23 15:25 ` Peter Maydell 2026-03-23 15:58 ` Daniel P. Berrangé 2026-03-23 16:15 ` Peter Maydell 2026-03-23 16:45 ` Daniel P. Berrangé 2026-03-23 14:11 ` Daniel P. Berrangé 2026-03-23 15:33 ` Peter Maydell 2026-03-23 13:56 ` Michael S. Tsirkin 2026-03-24 6:04 ` Junjie Cao
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox