DF-1221 / fix.diff
diff --git a/sys/dev/virtual/amazon/ena/ena.c b/sys/dev/virtual/amazon/ena/ena.c --- a/sys/dev/virtual/amazon/ena/ena.c +++ b/sys/dev/virtual/amazon/ena/ena.c @@ -1456,6 +1456,18 @@ len = ena_bufs[buf].len; req_id = ena_bufs[buf].req_id; + /* + * req_id is a 16-bit value supplied by the device/hypervisor. + * rx_buffer_info is sized ring_size (<= 1024); an out-of-range + * req_id indexes up to ~4 MB past the array into kernel heap, + * yielding a garbage mbuf pointer dereferenced below. + * validate_rx_req_id() exists for this (logs, bumps ierrors, + * schedules a device reset) but was not called on the RX-consume + * path unlike TX-consume and RX-refill. NULL return makes the + * caller release the descriptors and abort the packet. + */ + if (unlikely(validate_rx_req_id(rx_ring, req_id))) + return (NULL); rx_info = &rx_ring->rx_buffer_info[req_id]; ena_trace(ENA_DBG | ENA_RXPTH, "rx_info %p, mbuf %p, paddr %jx", @@ -1488,6 +1500,10 @@ ++buf; len = ena_bufs[buf].len; req_id = ena_bufs[buf].req_id; + if (unlikely(validate_rx_req_id(rx_ring, req_id))) { + m_freem(mbuf); + return (NULL); + } rx_info = &rx_ring->rx_buffer_info[req_id]; if (unlikely(rx_info->mbuf == NULL)) { |