All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] net/e1000e_core: adjust count if RDH exceeds RDT in e1000e_ring_advance()
@ 2020-11-13 10:31 Mauro Matteo Cascella
  2020-11-18  3:56 ` Jason Wang
  0 siblings, 1 reply; 10+ messages in thread
From: Mauro Matteo Cascella @ 2020-11-13 10:31 UTC (permalink / raw)
  To: qemu-devel
  Cc: mcascell, dmitry.fleytman, gaoning.pgn, jasowang, lersek, 330cjfdn

The e1000e_write_packet_to_guest() function iterates over a set of
receive descriptors by advancing rx descriptor head register (RDH) from
its initial value to rx descriptor tail register (RDT). The check in
e1000e_ring_empty() is responsible for detecting whether RDH has reached
RDT, terminating the loop if that's the case. Additional checks have
been added in the past to deal with bogus values submitted by the guest
to prevent possible infinite loop. This is done by "wrapping around" RDH
at some point and detecting whether it assumes the original value during
the loop.

However, when e1000e is configured to use the packet split feature, RDH is
incremented by two instead of one, as the packet split descriptors are
32 bytes while regular descriptors are 16 bytes. A malicious or buggy
guest may set RDT to an odd value and transmit only null RX descriptors.
This corner case would prevent RDH from ever matching RDT, leading to an
infinite loop. This patch adds a check in e1000e_ring_advance() to make sure
RDH does not exceed RDT in a single incremental step, adjusting the count
value accordingly.

This issue was independently reported by Gaoning Pan (Zhejiang University)
and Cheolwoo Myung.

Signed-off-by: Mauro Matteo Cascella <mcascell@redhat.com>
Tested-by: Mauro Matteo Cascella <mcascell@redhat.com>
Reported-by: Gaoning Pan <gaoning.pgn@antgroup.com>
Reported-by: Cheolwoo Myung <330cjfdn@gmail.com>
---
Changes since previous version:
Take the initial values of RDH/RDT into account. Address the case where RDH is
less than RDT and (RDH + count) would exceed RDT.

Patch v1:
https://lists.nongnu.org/archive/html/qemu-devel/2020-11/msg01492.html

References:
https://git.qemu.org/?p=qemu.git;a=commit;h=dd793a74882477ca38d49e191110c17dfe
https://git.qemu.org/?p=qemu.git;a=commit;h=4154c7e03fa55b4cf52509a83d50d6c09d743b7
http://www.intel.com/content/dam/doc/datasheet/82574l-gbe-controller-datasheet.pdf

 hw/net/e1000e_core.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index bcfd46696f..324cc14ffb 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -829,6 +829,11 @@ e1000e_ring_head_descr(E1000ECore *core, const E1000E_RingInfo *r)
 static inline void
 e1000e_ring_advance(E1000ECore *core, const E1000E_RingInfo *r, uint32_t count)
 {
+    if (count > 1 && core->mac[r->dh] < core->mac[r->dt] &&
+        core->mac[r->dh] + count > core->mac[r->dt]) {
+        count = core->mac[r->dt] - core->mac[r->dh];
+    }
+
     core->mac[r->dh] += count;
 
     if (core->mac[r->dh] * E1000_RING_DESC_LEN >= core->mac[r->dlen]) {
-- 
2.28.0



^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2020-12-01  5:43 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-13 10:31 [PATCH v2] net/e1000e_core: adjust count if RDH exceeds RDT in e1000e_ring_advance() Mauro Matteo Cascella
2020-11-18  3:56 ` Jason Wang
2020-11-18  8:53   ` Mauro Matteo Cascella
2020-11-19  5:57     ` Jason Wang
2020-11-23 21:30       ` Mauro Matteo Cascella
2020-11-27  5:21         ` Jason Wang
2020-11-27 14:49           ` Mauro Matteo Cascella
2020-11-30  2:58             ` Jason Wang
2020-11-30 14:12               ` Mauro Matteo Cascella
2020-12-01  5:42                 ` Jason Wang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.