Skip to content

Commit aad6f26

Browse files
pm215philmd
authored andcommitted
hw/net/smc91c111: Sanitize packet length on tx
When the smc91c111 transmits a packet, it must read a control byte which is at the end of the data area and CRC. However, we don't sanitize the length field in the packet buffer, so if the guest sets the length field to something large we will try to read past the end of the packet data buffer when we access the control byte. As usual, the datasheet says nothing about the behaviour of the hardware if the guest misprograms it in this way. It says only that the maximum valid length is 2048 bytes. We choose to log the guest error and silently drop the packet. This requires us to factor out the "mark the tx packet as complete" logic, so we can call it for this "drop packet" case as well as at the end of the loop when we send a valid packet. Cc: [email protected] Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2742 Signed-off-by: Peter Maydell <[email protected]> Reviewed-by: Philippe Mathieu-Daudé <[email protected]> Message-ID: <[email protected]> [PMD: Update smc91c111_do_tx() as len > MAX_PACKET_SIZE] Signed-off-by: Philippe Mathieu-Daudé <[email protected]>
1 parent 2fa3a5b commit aad6f26

File tree

1 file changed

+29
-5
lines changed

1 file changed

+29
-5
lines changed

hw/net/smc91c111.c

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@
2222

2323
/* Number of 2k memory pages available. */
2424
#define NUM_PACKETS 4
25+
/*
26+
* Maximum size of a data frame, including the leading status word
27+
* and byte count fields and the trailing CRC, last data byte
28+
* and control byte (per figure 8-1 in the Microchip Technology
29+
* LAN91C111 datasheet).
30+
*/
31+
#define MAX_PACKET_SIZE 2048
2532

2633
#define TYPE_SMC91C111 "smc91c111"
2734
OBJECT_DECLARE_SIMPLE_TYPE(smc91c111_state, SMC91C111)
@@ -240,6 +247,16 @@ static void smc91c111_release_packet(smc91c111_state *s, int packet)
240247
smc91c111_flush_queued_packets(s);
241248
}
242249

250+
static void smc91c111_complete_tx_packet(smc91c111_state *s, int packetnum)
251+
{
252+
if (s->ctr & CTR_AUTO_RELEASE) {
253+
/* Race? */
254+
smc91c111_release_packet(s, packetnum);
255+
} else if (s->tx_fifo_done_len < NUM_PACKETS) {
256+
s->tx_fifo_done[s->tx_fifo_done_len++] = packetnum;
257+
}
258+
}
259+
243260
/* Flush the TX FIFO. */
244261
static void smc91c111_do_tx(smc91c111_state *s)
245262
{
@@ -263,6 +280,17 @@ static void smc91c111_do_tx(smc91c111_state *s)
263280
*(p++) = 0x40;
264281
len = *(p++);
265282
len |= ((int)*(p++)) << 8;
283+
if (len > MAX_PACKET_SIZE) {
284+
/*
285+
* Datasheet doesn't say what to do here, and there is no
286+
* relevant tx error condition listed. Log, and drop the packet.
287+
*/
288+
qemu_log_mask(LOG_GUEST_ERROR,
289+
"smc91c111: tx packet with bad length %d, dropping\n",
290+
len);
291+
smc91c111_complete_tx_packet(s, packetnum);
292+
continue;
293+
}
266294
len -= 6;
267295
control = p[len + 1];
268296
if (control & 0x20)
@@ -291,11 +319,7 @@ static void smc91c111_do_tx(smc91c111_state *s)
291319
}
292320
}
293321
#endif
294-
if (s->ctr & CTR_AUTO_RELEASE)
295-
/* Race? */
296-
smc91c111_release_packet(s, packetnum);
297-
else if (s->tx_fifo_done_len < NUM_PACKETS)
298-
s->tx_fifo_done[s->tx_fifo_done_len++] = packetnum;
322+
smc91c111_complete_tx_packet(s, packetnum);
299323
qemu_send_packet(qemu_get_queue(s->nic), p, len);
300324
}
301325
s->tx_fifo_len = 0;

0 commit comments

Comments
 (0)