Skip to content

Commit 2fa3a5b

Browse files
pm215philmd
authored andcommitted
hw/net/smc91c111: Sanitize packet numbers
The smc91c111 uses packet numbers as an index into its internal s->data[][] array. Valid packet numbers are between 0 and 3, but the code does not generally check this, and there are various places where the guest can hand us an arbitrary packet number and cause an out-of-bounds access to the data array. Add validation of packet numbers. The datasheet is not very helpful about how guest errors like this should be handled: it says nothing on the subject, and none of the documented error conditions are relevant. We choose to log the situation with LOG_GUEST_ERROR and silently ignore the attempted operation. In the places where we are about to access the data[][] array using a packet number and we know the number is valid because we got it from somewhere that has already validated, we add an assert() to document that belief. Cc: [email protected] Signed-off-by: Peter Maydell <[email protected]> Reviewed-by: Philippe Mathieu-Daudé <[email protected]> Message-ID: <[email protected]> Signed-off-by: Philippe Mathieu-Daudé <[email protected]>
1 parent 822405b commit 2fa3a5b

File tree

1 file changed

+45
-0
lines changed

1 file changed

+45
-0
lines changed

hw/net/smc91c111.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ static const VMStateDescription vmstate_smc91c111 = {
118118
#define RS_TOOSHORT 0x0400
119119
#define RS_MULTICAST 0x0001
120120

121+
static inline bool packetnum_valid(int packet_num)
122+
{
123+
return packet_num >= 0 && packet_num < NUM_PACKETS;
124+
}
125+
121126
/* Update interrupt status. */
122127
static void smc91c111_update(smc91c111_state *s)
123128
{
@@ -218,6 +223,17 @@ static void smc91c111_pop_tx_fifo_done(smc91c111_state *s)
218223
/* Release the memory allocated to a packet. */
219224
static void smc91c111_release_packet(smc91c111_state *s, int packet)
220225
{
226+
if (!packetnum_valid(packet)) {
227+
/*
228+
* Data sheet doesn't document behaviour in this guest error
229+
* case, and there is no error status register to report it.
230+
* Log and ignore the attempt.
231+
*/
232+
qemu_log_mask(LOG_GUEST_ERROR,
233+
"smc91c111: attempt to release invalid packet %d\n",
234+
packet);
235+
return;
236+
}
221237
s->allocated &= ~(1 << packet);
222238
if (s->tx_alloc == 0x80)
223239
smc91c111_tx_alloc(s);
@@ -239,6 +255,8 @@ static void smc91c111_do_tx(smc91c111_state *s)
239255
return;
240256
for (i = 0; i < s->tx_fifo_len; i++) {
241257
packetnum = s->tx_fifo[i];
258+
/* queue_tx checked the packet number was valid */
259+
assert(packetnum_valid(packetnum));
242260
p = &s->data[packetnum][0];
243261
/* Set status word. */
244262
*(p++) = 0x01;
@@ -287,6 +305,17 @@ static void smc91c111_do_tx(smc91c111_state *s)
287305
/* Add a packet to the TX FIFO. */
288306
static void smc91c111_queue_tx(smc91c111_state *s, int packet)
289307
{
308+
if (!packetnum_valid(packet)) {
309+
/*
310+
* Datasheet doesn't document behaviour in this error case, and
311+
* there's no error status register we could report it in.
312+
* Log and ignore.
313+
*/
314+
qemu_log_mask(LOG_GUEST_ERROR,
315+
"smc91c111: attempt to queue invalid packet %d\n",
316+
packet);
317+
return;
318+
}
290319
if (s->tx_fifo_len == NUM_PACKETS)
291320
return;
292321
s->tx_fifo[s->tx_fifo_len++] = packet;
@@ -457,6 +486,13 @@ static void smc91c111_writeb(void *opaque, hwaddr offset,
457486
n = s->rx_fifo[0];
458487
else
459488
n = s->packet_num;
489+
if (!packetnum_valid(n)) {
490+
/* Datasheet doesn't document what to do here */
491+
qemu_log_mask(LOG_GUEST_ERROR,
492+
"smc91c111: attempt to write data to invalid packet %d\n",
493+
n);
494+
return;
495+
}
460496
p = s->ptr & 0x07ff;
461497
if (s->ptr & 0x4000) {
462498
s->ptr = (s->ptr & 0xf800) | ((s->ptr + 1) & 0x7ff);
@@ -605,6 +641,13 @@ static uint32_t smc91c111_readb(void *opaque, hwaddr offset)
605641
n = s->rx_fifo[0];
606642
else
607643
n = s->packet_num;
644+
if (!packetnum_valid(n)) {
645+
/* Datasheet doesn't document what to do here */
646+
qemu_log_mask(LOG_GUEST_ERROR,
647+
"smc91c111: attempt to read data from invalid packet %d\n",
648+
n);
649+
return 0;
650+
}
608651
p = s->ptr & 0x07ff;
609652
if (s->ptr & 0x4000) {
610653
s->ptr = (s->ptr & 0xf800) | ((s->ptr + 1) & 0x07ff);
@@ -713,6 +756,8 @@ static ssize_t smc91c111_receive(NetClientState *nc, const uint8_t *buf, size_t
713756
return -1;
714757
s->rx_fifo[s->rx_fifo_len++] = packetnum;
715758

759+
/* allocate_packet() will not hand us back an invalid packet number */
760+
assert(packetnum_valid(packetnum));
716761
p = &s->data[packetnum][0];
717762
/* ??? Multicast packets? */
718763
status = 0;

0 commit comments

Comments
 (0)