git: e70ff92d2431 - main - ice: Add malformed virtchnl injection points

From: Kevin Bowling <kbowling_at_FreeBSD.org>
Date: Thu, 17 Sep 2026 16:40:16 UTC
The branch main has been updated by kbowling:

URL: https://cgit.FreeBSD.org/src/commit/?id=e70ff92d243104834ad40581c3562a55d7525cc8

commit e70ff92d243104834ad40581c3562a55d7525cc8
Author:     Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-08-19 03:18:53 +0000
Commit:     Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-09-17 16:36:36 +0000

    ice: Add malformed virtchnl injection points
    
    Extend the optional ice(4) failure injection facility with semantic
    corruption points for queue configuration, RSS keys and tables, and
    interrupt mappings.
    
    Each point mutates an otherwise valid request after the common
    virtchnl length check.  This exercises the PF semantic validators with a
    real VF while preserving the normal wire format and mailbox path.
    
    The queue point selects unaligned Tx or Rx bases, an unaligned or
    unrepresentable receive buffer, an invalid frame size, duplicate queue
    IDs, or a bad VSI.  The RSS points select short advertised data or an
    out-of-range LUT entry.  The interrupt point selects an invalid ITR,
    traffic on vector zero, duplicate vectors, or a bad VSI.
    
    The points remain absent unless the kernel is built with
    options DRIVER_FAILPOINTS and retain the existing PF and VF selectors.
    
    MFC after:      2 weeks
    Sponsored by:   BBOX.io
    Differential Revision:  https://reviews.freebsd.org/D59021
---
 sys/dev/ice/ice_iov.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/sys/dev/ice/ice_iov.c b/sys/dev/ice/ice_iov.c
index eab735820f8e..0c5d49ebf5b1 100644
--- a/sys/dev/ice/ice_iov.c
+++ b/sys/dev/ice/ice_iov.c
@@ -1421,6 +1421,41 @@ ice_vc_cfg_vsi_qs_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf)
 	int i, error = 0;
 
 	vqci = (struct virtchnl_vsi_queue_config_info *)msg_buf;
+	ICE_FAIL_POINT_CODE_COND(sc, _debug_fail_point_ice_iov,
+	    malformed_queues, ice_iov_fail_vf_matches(vf->vf_num),
+	    FAIL_POINT_NONSLEEPABLE, {
+		switch (RETURN_VALUE) {
+		case 1:
+			vqci->qpair[0].txq.dma_ring_addr |= 1;
+			break;
+		case 2:
+			vqci->qpair[0].rxq.dma_ring_addr |= 1;
+			break;
+		case 3:
+			vqci->qpair[0].rxq.databuffer_size++;
+			break;
+		case 4:
+			vqci->qpair[0].rxq.max_pkt_size = 0;
+			break;
+		case 5:
+			if (vqci->num_queue_pairs > 1) {
+				vqci->qpair[1].txq.queue_id =
+				    vqci->qpair[0].txq.queue_id;
+				vqci->qpair[1].rxq.queue_id =
+				    vqci->qpair[0].rxq.queue_id;
+			} else {
+				vqci->qpair[0].txq.queue_id++;
+			}
+			break;
+		case 6:
+			vqci->qpair[0].rxq.databuffer_size =
+			    ICE_VC_MAX_RX_BUFFER + BIT(ICE_RLAN_CTX_DBUF_S);
+			break;
+		default:
+			vqci->vsi_id++;
+			break;
+		}
+	});
 
 	if (vqci->vsi_id != vsi->idx || vqci->num_queue_pairs == 0 ||
 	    vqci->num_queue_pairs > sizeof(queue_map) * NBBY ||
@@ -1569,6 +1604,11 @@ ice_vc_cfg_rss_key_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf)
 	struct ice_vsi *vsi = vf->vsi;
 
 	vrk = (struct virtchnl_rss_key *)msg_buf;
+	ICE_FAIL_POINT_CODE_COND(sc, _debug_fail_point_ice_iov,
+	    malformed_rss_key, ice_iov_fail_vf_matches(vf->vf_num),
+	    FAIL_POINT_NONSLEEPABLE, {
+		vrk->key_len--;
+	});
 
 	if (vrk->vsi_id != vsi->idx) {
 		device_printf(sc->dev,
@@ -1619,6 +1659,14 @@ ice_vc_cfg_rss_lut_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf)
 	struct ice_vsi *vsi = vf->vsi;
 
 	vrl = (struct virtchnl_rss_lut *)msg_buf;
+	ICE_FAIL_POINT_CODE_COND(sc, _debug_fail_point_ice_iov,
+	    malformed_rss_lut, ice_iov_fail_vf_matches(vf->vf_num),
+	    FAIL_POINT_NONSLEEPABLE, {
+		if (RETURN_VALUE == 1)
+			vrl->lut_entries--;
+		else
+			vrl->lut[0] = vsi->num_rx_queues;
+	});
 
 	if (vrl->vsi_id != vsi->idx) {
 		device_printf(sc->dev,
@@ -1824,6 +1872,30 @@ ice_vc_cfg_irq_map_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf)
 	u16 rxqs_seen, txqs_seen, valid_rxqs, valid_txqs, vector;
 
 	vimi = (struct virtchnl_irq_map_info *)msg_buf;
+	ICE_FAIL_POINT_CODE_COND(sc, _debug_fail_point_ice_iov,
+	    malformed_irq_map, ice_iov_fail_vf_matches(vf->vf_num),
+	    FAIL_POINT_NONSLEEPABLE, {
+		switch (RETURN_VALUE) {
+		case 1:
+			vimi->vecmap[0].rxitr_idx = VIRTCHNL_ITR_IDX_NO_ITR + 1;
+			break;
+		case 2:
+			vimi->vecmap[0].vector_id = 0;
+			vimi->vecmap[0].rxq_map = 1;
+			break;
+		case 3:
+			if (vimi->num_vectors > 1) {
+				vimi->vecmap[1].vector_id =
+				    vimi->vecmap[0].vector_id;
+			} else {
+				vimi->vecmap[0].vsi_id++;
+			}
+			break;
+		default:
+			vimi->vecmap[0].vsi_id++;
+			break;
+		}
+	});
 
 	if (vimi->num_vectors == 0 ||
 	    vimi->num_vectors > vf->num_irq_vectors ||