aboutsummaryrefslogtreecommitdiff
path: root/hw/net/dp8393x.c
diff options
context:
space:
mode:
authorFinn Thain <fthain@telegraphics.com.au>2020-01-29 20:27:49 +1100
committerJason Wang <jasowang@redhat.com>2020-03-03 18:04:47 +0800
commitada74315270d1dcabf4c9d4fece19df7ef5b9577 (patch)
tree6228520087f920e3ea4bdd98fb30a73996aa3f5a /hw/net/dp8393x.c
parenta3cce2825a0b12bb717a5106daaca245557cc9ae (diff)
downloadqemu-ada74315270d1dcabf4c9d4fece19df7ef5b9577.zip
qemu-ada74315270d1dcabf4c9d4fece19df7ef5b9577.tar.gz
qemu-ada74315270d1dcabf4c9d4fece19df7ef5b9577.tar.bz2
dp8393x: Implement packet size limit and RBAE interrupt
Add a bounds check to prevent a large packet from causing a buffer overflow. This is defensive programming -- I haven't actually tried sending an oversized packet or a jumbo ethernet frame. The SONIC handles packets that are too big for the buffer by raising the RBAE interrupt and dropping them. Linux uses that interrupt to count dropped packets. Signed-off-by: Finn Thain <fthain@telegraphics.com.au> Tested-by: Laurent Vivier <laurent@vivier.eu> Signed-off-by: Jason Wang <jasowang@redhat.com>
Diffstat (limited to 'hw/net/dp8393x.c')
-rw-r--r--hw/net/dp8393x.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index b5a9c6a..911f59e 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -137,6 +137,7 @@ do { printf("sonic ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0)
#define SONIC_TCR_CRCI 0x2000
#define SONIC_TCR_PINT 0x8000
+#define SONIC_ISR_RBAE 0x0010
#define SONIC_ISR_RBE 0x0020
#define SONIC_ISR_RDE 0x0040
#define SONIC_ISR_TC 0x0080
@@ -772,6 +773,14 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
s->regs[SONIC_RCR] &= ~(SONIC_RCR_PRX | SONIC_RCR_LBK | SONIC_RCR_FAER |
SONIC_RCR_CRCR | SONIC_RCR_LPKT | SONIC_RCR_BC | SONIC_RCR_MC);
+ if (pkt_size + 4 > dp8393x_rbwc(s) * 2) {
+ DPRINTF("oversize packet, pkt_size is %d\n", pkt_size);
+ s->regs[SONIC_ISR] |= SONIC_ISR_RBAE;
+ dp8393x_update_irq(s);
+ dp8393x_do_read_rra(s);
+ return pkt_size;
+ }
+
packet_type = dp8393x_receive_filter(s, buf, pkt_size);
if (packet_type < 0) {
DPRINTF("packet not for netcard\n");