* [PATCH v2] virtio-net: validate RSS indirections_len in post_load
@ 2026-03-24 6:01 Junjie Cao
2026-05-13 6:42 ` Michael Tokarev
0 siblings, 1 reply; 4+ messages in thread
From: Junjie Cao @ 2026-03-24 6:01 UTC (permalink / raw)
To: qemu-devel
Cc: jasowang, mst, yuri.benditovich, berrange, peter.maydell,
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 corrupted save file or 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.
Factor the validation into virtio_net_rss_indirections_len_valid()
and call it from both virtio_net_handle_rss() and
virtio_net_rss_post_load().
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>
---
v1 -> v2:
- Drop the redundant == 0 check; is_power_of_2() already handles
it. [MST]
- Factor the validation into virtio_net_rss_indirections_len_valid()
and use it from both virtio_net_handle_rss() and
virtio_net_rss_post_load(), replacing the two separate checks in
the command path. [MST]
v1: https://lore.kernel.org/qemu-devel/20260323131531.1976-1-junjie.cao@intel.com/
hw/net/virtio-net.c | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 2a5d642a64..f0e3beb290 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1374,6 +1374,11 @@ static void virtio_net_unload_ebpf(VirtIONet *n)
ebpf_rss_unload(&n->ebpf_rss);
}
+static bool virtio_net_rss_indirections_len_valid(uint16_t len)
+{
+ return is_power_of_2(len) && len <= VIRTIO_NET_RSS_MAX_TABLE_LEN;
+}
+
static uint16_t virtio_net_handle_rss(VirtIONet *n,
struct iovec *iov,
unsigned int iov_cnt,
@@ -1411,14 +1416,9 @@ static uint16_t virtio_net_handle_rss(VirtIONet *n,
if (!do_rss) {
n->rss_data.indirections_len = 0;
}
- if (n->rss_data.indirections_len >= VIRTIO_NET_RSS_MAX_TABLE_LEN) {
- err_msg = "Too large indirection table";
- err_value = n->rss_data.indirections_len;
- goto error;
- }
n->rss_data.indirections_len++;
- if (!is_power_of_2(n->rss_data.indirections_len)) {
- err_msg = "Invalid size of indirection table";
+ if (!virtio_net_rss_indirections_len_valid(n->rss_data.indirections_len)) {
+ err_msg = "Invalid indirection table length";
err_value = n->rss_data.indirections_len;
goto error;
}
@@ -3427,6 +3427,13 @@ static int virtio_net_rss_post_load(void *opaque, int version_id)
n->rss_data.supported_hash_types = VIRTIO_NET_RSS_SUPPORTED_HASHES;
}
+ if (!virtio_net_rss_indirections_len_valid(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] 4+ messages in thread
* Re: [PATCH v2] virtio-net: validate RSS indirections_len in post_load
2026-03-24 6:01 [PATCH v2] virtio-net: validate RSS indirections_len in post_load Junjie Cao
@ 2026-05-13 6:42 ` Michael Tokarev
2026-05-13 7:02 ` Philippe Mathieu-Daudé
2026-05-13 9:59 ` Michael S. Tsirkin
0 siblings, 2 replies; 4+ messages in thread
From: Michael Tokarev @ 2026-05-13 6:42 UTC (permalink / raw)
To: Junjie Cao, qemu-devel
Cc: jasowang, mst, yuri.benditovich, berrange, peter.maydell,
qemu-stable
On 24.03.2026 09:01, 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 corrupted save file or 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.
>
> Factor the validation into virtio_net_rss_indirections_len_valid()
> and call it from both virtio_net_handle_rss() and
> virtio_net_rss_post_load().
>
> 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>
Hi!
Has this patch been forgotten, or is it not needed anymore?
I'm preparing next set of the stable qemu releases, if it's needed,
it would be nice if it lands in the master branch in the next 10
days.
Thanks,
/mjt
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] virtio-net: validate RSS indirections_len in post_load
2026-05-13 6:42 ` Michael Tokarev
@ 2026-05-13 7:02 ` Philippe Mathieu-Daudé
2026-05-13 9:59 ` Michael S. Tsirkin
1 sibling, 0 replies; 4+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-05-13 7:02 UTC (permalink / raw)
To: Michael Tokarev, Junjie Cao, qemu-devel
Cc: jasowang, mst, yuri.benditovich, berrange, peter.maydell,
qemu-stable
On 13/5/26 08:42, Michael Tokarev wrote:
> On 24.03.2026 09:01, 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 corrupted save file or 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.
>>
>> Factor the validation into virtio_net_rss_indirections_len_valid()
>> and call it from both virtio_net_handle_rss() and
>> virtio_net_rss_post_load().
>>
>> 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>
>
> Hi!
>
> Has this patch been forgotten, or is it not needed anymore?
Jason went AWOL regarding net/ and hw/net/ related patches
(while net/ is 'Maintained', hw/net/ only supports 'Odd Fixes').
BTW eBPF is also listed as 'Maintained' by Jason.
I'm trying to help with hw/net/ when it isn't too specific.
This particular one is VirtIO so I'll let Michael have a look,
as per MAINTAINERS:
virtio
M: Michael S. Tsirkin <mst@redhat.com>
S: Supported
F: hw/*/virtio*
> I'm preparing next set of the stable qemu releases, if it's needed,
> it would be nice if it lands in the master branch in the next 10
> days.
>
> Thanks,
>
> /mjt
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] virtio-net: validate RSS indirections_len in post_load
2026-05-13 6:42 ` Michael Tokarev
2026-05-13 7:02 ` Philippe Mathieu-Daudé
@ 2026-05-13 9:59 ` Michael S. Tsirkin
1 sibling, 0 replies; 4+ messages in thread
From: Michael S. Tsirkin @ 2026-05-13 9:59 UTC (permalink / raw)
To: Michael Tokarev
Cc: Junjie Cao, qemu-devel, jasowang, yuri.benditovich, berrange,
peter.maydell, qemu-stable
On Wed, May 13, 2026 at 09:42:59AM +0300, Michael Tokarev wrote:
> On 24.03.2026 09:01, 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 corrupted save file or 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.
> >
> > Factor the validation into virtio_net_rss_indirections_len_valid()
> > and call it from both virtio_net_handle_rss() and
> > virtio_net_rss_post_load().
> >
> > 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>
>
> Hi!
>
> Has this patch been forgotten, or is it not needed anymore?
>
> I'm preparing next set of the stable qemu releases, if it's needed,
> it would be nice if it lands in the master branch in the next 10
> days.
>
> Thanks,
>
> /mjt
I'll pick it now, thanks.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-05-13 10:01 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-24 6:01 [PATCH v2] virtio-net: validate RSS indirections_len in post_load Junjie Cao
2026-05-13 6:42 ` Michael Tokarev
2026-05-13 7:02 ` Philippe Mathieu-Daudé
2026-05-13 9:59 ` Michael S. Tsirkin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox