@samitouri / QOSamiQemu / commits / b395a655ae

hw/net/e1000e: recalculate rx_desc_len on migration load

rx_desc_len is migrated as a raw uint8_t from the stream, but it is a derived value that can be computed from the register state in core.mac[RFCTL] and core.mac[RCTL]. A crafted migration stream can set rx_desc_len to an invalid value (e.g. 64), causing a stack buffer overflow in e1000e_write_packet_to_guest() which copies rx_desc_len bytes into a 32-byte stack union. Recalculate rx_desc_len and other derived values from the register state in post_load, ignoring the untrusted values from the stream. Cc: qemu-stable@nongnu.org Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3869 Signed-off-by: Laurent Vivier <lvivier@redhat.com> Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> Message-ID: <20260722112449.1386162-2-lvivier@redhat.com> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>

Laurent Vivier committed Jul 22, 2026 at 13:24 UTC b395a655ae0eb8d38c1e61a6bcaadb2e79326a5b
1 file changed +13 -5
hw/net/e1000e_core.c
+13 -5
@@ -1948,6 +1948,16 @@ e1000e_calc_rxdesclen(E1000ECore *core)
1948 trace_e1000e_rx_desc_len(core->rx_desc_len);
1949 }
1950
1951 +static void
1952 +e1000e_calc_rxconf(E1000ECore *core)
1953 +{
1954 + e1000e_parse_rxbufsize(core);
1955 + e1000e_calc_rxdesclen(core);
1956 + core->rxbuf_min_shift =
1957 + ((core->mac[RCTL] / E1000_RCTL_RDMTS_QUAT) & 3) + 1 +
1958 + E1000_RING_DESC_LEN_SHIFT;
1959 +}
1960 +
1961 static void
1962 e1000e_set_rx_control(E1000ECore *core, int index, uint32_t val)
1963 {
@@ -1955,11 +1965,7 @@ e1000e_set_rx_control(E1000ECore *core, int index, uint32_t val)
1965 trace_e1000e_rx_set_rctl(core->mac[RCTL]);
1966
1967 if (val & E1000_RCTL_EN) {
1958 - e1000e_parse_rxbufsize(core);
1959 - e1000e_calc_rxdesclen(core);
1960 - core->rxbuf_min_shift = ((val / E1000_RCTL_RDMTS_QUAT) & 3) + 1 +
1961 - E1000_RING_DESC_LEN_SHIFT;
1962 -
1968 + e1000e_calc_rxconf(core);
1969 e1000e_start_recv(core);
1970 }
1971 }
@@ -3557,5 +3563,7 @@ e1000e_core_post_load(E1000ECore *core)
3563 e1000e_intrmgr_resume(core);
3564 e1000e_autoneg_resume(core);
3565
3566 + e1000e_calc_rxconf(core);
3567 +
3568 return 0;
3569 }