From nobody Mon Aug 10 09:18:57 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hJThl0pb8z6nRlm for ; Mon, 10 Aug 2026 09:19:03 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hJThk4KvLz3nYW for ; Mon, 10 Aug 2026 09:19:02 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1786353542; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=e6oixDyF5XEoJBz6WOI0Jem/F0mF8YpJDNzWlw+mhkk=; b=siYyJlQfSWR2oAdVebpfCVIkyUo2+c4WLD+TMLdh1j+zTrPm5dFqHB4AWXtI5+SH2WhH+p tWgfumQmq9Hjc9jAdrhArqrZujMYellv64bj2d6bYexDFZ6RArJxncvUtBfFUYbmUgWqnT KsJTzmWt4uQnqjqANLQqPKD5HAAvQEhgoK/Z4Wwlc8OuVfRxOgkhsqxPNdIR2KchHJkTrh x/nnWjmPh7bJIp6nOYuKu3fUGTqfo7Y9p8y5F3lFOcWuIs4WgCYBVV1rlQ6YIhm3xcQm44 VEGXYESZM1UEkvWmJshw0vD/5HQu6puCmhVpcwT/Akh5TRPpgbLFFNA99y0Rkg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1786353542; a=rsa-sha256; cv=none; b=cOF3b3X+8zQircyE3Vi2zKCC3f2riRHWlYqBFR1ZCB8QApQaLg7K0vqg4kEENZqo3PzH8K 7ZqyGc3ERO8rGcr6ySghTF/5kSPAy1onPdyi5LO+IjRhNy6NyxuTsJ3fYqpQ/Mm+Q2Lz9i i4I82/Cg4xlJdckL1kGk7wf4l4AUF+v0W9BP/7vZh//RzDqKpuWYrNrSrL2jZ+A5qJyxsj 9LzWgwpd5Oqw0fadDCFdnKJ9aanUKjasNFvzf1oksoyMV2XBoXR6bjAPbai+lLl/yB9WOh ZRTEA1AmGd+FgDlUSDd1hBl4zLMwCL5jccwd8xKy/k2SM/usyp+1+UlDUV4M6A== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1786353542; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=e6oixDyF5XEoJBz6WOI0Jem/F0mF8YpJDNzWlw+mhkk=; b=lB6ZO0YCfWhpFYkgEMj6/pOqDD0sDWxpZbAl5CQip+Byiv3vuifMK08+pmIr3z4VR7cNwX oPJ9E+or2ZX5iETGXSFc3b/a5FmPzDSfuRlpl92b0LDKSEegXLwvUiAdOfWRSuItGHcSbM FCKcvo2Qkyil9yCuaAYsSE5qe16X0rZMJn9j4tLbS+u98mh999t4b/d9yP3iZaBplJJr7G iW3yn8EwhD4+IuUHKkNAaXEEf9pa+Yx9Me3Mhi0luFgqmB42p8ZATRrqR6dHGzeB2veUFU A1Nk7UkMbdvuA4/f/Gj2FRwA1N9ApLFYb4QD4UgijYOxl5FCaeZ0aa8S3Y7rnQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hJThk2fL0z13Gl for ; Mon, 10 Aug 2026 09:19:02 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3100e by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 10 Aug 2026 09:18:57 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kevin Bowling Subject: git: e779914354db - main - ixl: Validate VF virtchnl configuration List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kbowling X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: e779914354db5cb3a20f4ec894d08b0f81d05ba2 Auto-Submitted: auto-generated Date: Mon, 10 Aug 2026 09:18:57 +0000 Message-Id: <6a799781.3100e.142376f8@gitrepo.freebsd.org> The branch main has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=e779914354db5cb3a20f4ec894d08b0f81d05ba2 commit e779914354db5cb3a20f4ec894d08b0f81d05ba2 Author: Kevin Bowling AuthorDate: 2026-08-10 03:15:17 +0000 Commit: Kevin Bowling CommitDate: 2026-08-10 09:17:25 +0000 ixl: Validate VF virtchnl configuration Bound variable-length virtchnl messages before computing their expected length, following the newer Intel virtchnl implementation. Validate VF ring sizes and alignments before programming HMC contexts. DPDK uses 128-byte ring alignment and 64 through 8160 descriptors; the virtchnl ABI further specifies TX multiples of 8 and RX multiples of 32. Preserve the 4096-descriptor limit on X722. Validate queue bitmaps before changing any rings, validate all queue and interrupt contexts before applying a request, and reject invalid RSS table entries. Also avoid sending an ACK after VLAN-strip setup fails and reply to delete-VLAN errors with the correct opcode. These checks prevent malformed or oversized requests from an untrusted VF from partially programming resources outside its allocation. MFC after: 2 weeks --- sys/dev/ixl/ixl_pf_iov.c | 156 ++++++++++++++++++++++++++++++++--------------- sys/dev/ixl/virtchnl.h | 70 +++++++++++++++++---- 2 files changed, 165 insertions(+), 61 deletions(-) diff --git a/sys/dev/ixl/ixl_pf_iov.c b/sys/dev/ixl/ixl_pf_iov.c index e749797fa700..b360955e25b2 100644 --- a/sys/dev/ixl/ixl_pf_iov.c +++ b/sys/dev/ixl/ixl_pf_iov.c @@ -58,6 +58,8 @@ static void ixl_vf_reset_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, ui static void ixl_vf_get_resources_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, uint16_t msg_size); static int ixl_vf_config_tx_queue(struct ixl_pf *pf, struct ixl_vf *vf, struct virtchnl_txq_info *info); static int ixl_vf_config_rx_queue(struct ixl_pf *pf, struct ixl_vf *vf, struct virtchnl_rxq_info *info); +static bool ixl_vf_tx_queue_valid(struct ixl_pf *pf, const struct virtchnl_txq_info *info); +static bool ixl_vf_rx_queue_valid(struct ixl_pf *pf, const struct virtchnl_rxq_info *info); static void ixl_vf_config_vsi_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, uint16_t msg_size); static void ixl_vf_set_qctl(struct ixl_pf *pf, const struct virtchnl_vector_map *vector, enum i40e_queue_type cur_type, uint16_t cur_queue, enum i40e_queue_type *last_type, uint16_t *last_queue); @@ -77,6 +79,8 @@ static int ixl_config_pf_vsi_loopback(struct ixl_pf *pf, bool enable); static int ixl_adminq_err_to_errno(enum i40e_admin_queue_err err); +#define IXL_VF_MAX_RING_XL710 8160 + /* * TODO: Move pieces of this into iflib and call the rest in a handler? * @@ -599,6 +603,33 @@ ixl_vf_config_tx_queue(struct ixl_pf *pf, struct ixl_vf *vf, return (0); } +static uint32_t +ixl_vf_max_ring(const struct i40e_hw *hw) +{ + + if (hw->mac.type == I40E_MAC_XL710) + return (IXL_VF_MAX_RING_XL710); + return (IXL_MAX_RING); +} + +static bool +ixl_vf_tx_queue_valid(struct ixl_pf *pf, + const struct virtchnl_txq_info *info) +{ + + if (info->ring_len < IXL_MIN_RING || + info->ring_len > ixl_vf_max_ring(&pf->hw) || + info->ring_len % 8 != 0 || + info->dma_ring_addr == 0 || + info->dma_ring_addr % IXL_TX_CTX_BASE_UNITS != 0 || + info->headwb_enabled > 1) + return (false); + if (info->headwb_enabled != 0 && + (info->dma_headwb_addr == 0 || info->dma_headwb_addr % 4 != 0)) + return (false); + return (true); +} + static int ixl_vf_config_rx_queue(struct ixl_pf *pf, struct ixl_vf *vf, struct virtchnl_rxq_info *info) @@ -666,6 +697,33 @@ ixl_vf_config_rx_queue(struct ixl_pf *pf, struct ixl_vf *vf, return (0); } +static bool +ixl_vf_rx_queue_valid(struct ixl_pf *pf, + const struct virtchnl_rxq_info *info) +{ + + if (info->ring_len < IXL_MIN_RING || + info->ring_len > ixl_vf_max_ring(&pf->hw) || + info->ring_len % IXL_RING_INCREMENT != 0 || + info->dma_ring_addr == 0 || + info->dma_ring_addr % IXL_RX_CTX_BASE_UNITS != 0) + return (false); + if (info->databuffer_size == 0 || + info->databuffer_size > IXL_VF_MAX_BUFFER || + info->databuffer_size % (1U << I40E_RXQ_CTX_DBUFF_SHIFT) != 0) + return (false); + if (info->max_pkt_size > IXL_VF_MAX_FRAME || + info->max_pkt_size < ETHER_MIN_LEN) + return (false); + if (info->splithdr_enabled > 1) + return (false); + if (info->splithdr_enabled != 0 && + (info->hdr_size == 0 || info->hdr_size > IXL_VF_MAX_HDR_BUFFER || + info->hdr_size % (1U << I40E_RXQ_CTX_HBUFF_SHIFT) != 0)) + return (false); + return (true); +} + static void ixl_vf_config_vsi_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, uint16_t msg_size) @@ -697,12 +755,18 @@ ixl_vf_config_vsi_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, if (pair->txq.vsi_id != vf->vsi.vsi_num || pair->rxq.vsi_id != vf->vsi.vsi_num || pair->txq.queue_id != pair->rxq.queue_id || - pair->txq.queue_id >= vf->vsi.num_tx_queues) { + pair->txq.queue_id >= vf->vsi.num_tx_queues || + !ixl_vf_tx_queue_valid(pf, &pair->txq) || + !ixl_vf_rx_queue_valid(pf, &pair->rxq)) { i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_CONFIG_VSI_QUEUES, I40E_ERR_PARAM); return; } + } + + for (i = 0; i < info->num_queue_pairs; i++) { + pair = &info->qpair[i]; if (ixl_vf_config_tx_queue(pf, vf, &pair->txq) != 0) { i40e_send_vf_nack(pf, vf, @@ -854,9 +918,11 @@ ixl_vf_config_irq_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, return; } - ixl_vf_config_vector(pf, vf, vector); } + for (i = 0; i < map->num_vectors; i++) + ixl_vf_config_vector(pf, vf, &map->vecmap[i]); + ixl_send_vf_ack(pf, vf, VIRTCHNL_OP_CONFIG_IRQ_MAP); } @@ -865,29 +931,33 @@ ixl_vf_enable_queues_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, uint16_t msg_size) { struct virtchnl_queue_select *select; + uint32_t queue_mask; int error = 0; select = msg; + queue_mask = (1U << vf->qtag.num_active) - 1; if (select->vsi_id != vf->vsi.vsi_num || - select->rx_queues == 0 || select->tx_queues == 0) { + (select->rx_queues == 0 && select->tx_queues == 0) || + ((select->rx_queues | select->tx_queues) & ~queue_mask) != 0) { i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_ENABLE_QUEUES, I40E_ERR_PARAM); return; } + for (int i = 0; i < vf->qtag.num_active; i++) { + if (((select->tx_queues & (1U << i)) != 0 && + !ixl_pf_qmgr_is_queue_configured(&vf->qtag, i, true)) || + ((select->rx_queues & (1U << i)) != 0 && + !ixl_pf_qmgr_is_queue_configured(&vf->qtag, i, false))) { + i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_ENABLE_QUEUES, + I40E_ERR_PARAM); + return; + } + } /* Enable TX rings selected by the VF */ - for (int i = 0; i < 32; i++) { - if ((1 << i) & select->tx_queues) { - /* Warn if queue is out of VF allocation range */ - if (i >= vf->vsi.num_tx_queues) { - device_printf(pf->dev, "VF %d: TX ring %d is outside of VF VSI allocation!\n", - vf->vf_num, i); - break; - } - /* Skip this queue if it hasn't been configured */ - if (!ixl_pf_qmgr_is_queue_configured(&vf->qtag, i, true)) - continue; + for (int i = 0; i < vf->qtag.num_active; i++) { + if ((1U << i) & select->tx_queues) { /* Warn if this queue is already marked as enabled */ if (ixl_pf_qmgr_is_queue_enabled(&vf->qtag, i, true)) ixl_dbg_iov(pf, "VF %d: TX ring %d is already enabled!\n", @@ -902,17 +972,8 @@ ixl_vf_enable_queues_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, } /* Enable RX rings selected by the VF */ - for (int i = 0; i < 32; i++) { - if ((1 << i) & select->rx_queues) { - /* Warn if queue is out of VF allocation range */ - if (i >= vf->vsi.num_rx_queues) { - device_printf(pf->dev, "VF %d: RX ring %d is outside of VF VSI allocation!\n", - vf->vf_num, i); - break; - } - /* Skip this queue if it hasn't been configured */ - if (!ixl_pf_qmgr_is_queue_configured(&vf->qtag, i, false)) - continue; + for (int i = 0; i < vf->qtag.num_active; i++) { + if ((1U << i) & select->rx_queues) { /* Warn if this queue is already marked as enabled */ if (ixl_pf_qmgr_is_queue_enabled(&vf->qtag, i, false)) ixl_dbg_iov(pf, "VF %d: RX ring %d is already enabled!\n", @@ -939,26 +1000,23 @@ ixl_vf_disable_queues_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, uint16_t msg_size) { struct virtchnl_queue_select *select; + uint32_t queue_mask; int error = 0; select = msg; + queue_mask = (1U << vf->qtag.num_active) - 1; if (select->vsi_id != vf->vsi.vsi_num || - select->rx_queues == 0 || select->tx_queues == 0) { + (select->rx_queues == 0 && select->tx_queues == 0) || + ((select->rx_queues | select->tx_queues) & ~queue_mask) != 0) { i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_DISABLE_QUEUES, I40E_ERR_PARAM); return; } /* Disable TX rings selected by the VF */ - for (int i = 0; i < 32; i++) { - if ((1 << i) & select->tx_queues) { - /* Warn if queue is out of VF allocation range */ - if (i >= vf->vsi.num_tx_queues) { - device_printf(pf->dev, "VF %d: TX ring %d is outside of VF VSI allocation!\n", - vf->vf_num, i); - break; - } + for (int i = 0; i < vf->qtag.num_active; i++) { + if ((1U << i) & select->tx_queues) { /* Skip this queue if it hasn't been configured */ if (!ixl_pf_qmgr_is_queue_configured(&vf->qtag, i, true)) continue; @@ -977,14 +1035,8 @@ ixl_vf_disable_queues_msg(struct ixl_pf *pf, struct ixl_vf *vf, } /* Enable RX rings selected by the VF */ - for (int i = 0; i < 32; i++) { - if ((1 << i) & select->rx_queues) { - /* Warn if queue is out of VF allocation range */ - if (i >= vf->vsi.num_rx_queues) { - device_printf(pf->dev, "VF %d: RX ring %d is outside of VF VSI allocation!\n", - vf->vf_num, i); - break; - } + for (int i = 0; i < vf->qtag.num_active; i++) { + if ((1U << i) & select->rx_queues) { /* Skip this queue if it hasn't been configured */ if (!ixl_pf_qmgr_is_queue_configured(&vf->qtag, i, false)) continue; @@ -1147,6 +1199,7 @@ ixl_vf_add_vlan_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, if (code != I40E_SUCCESS) { i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_ADD_VLAN, I40E_ERR_PARAM); + return; } for (i = 0; i < filter_list->num_elements; i++) @@ -1172,14 +1225,14 @@ ixl_vf_del_vlan_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, for (i = 0; i < filter_list->num_elements; i++) { if (filter_list->vlan_id[i] > EVL_VLID_MASK) { - i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_ADD_VLAN, + i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_DEL_VLAN, I40E_ERR_PARAM); return; } } if (!(vf->vf_flags & VF_FLAG_VLAN_CAP)) { - i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_ADD_VLAN, + i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_DEL_VLAN, I40E_ERR_PARAM); return; } @@ -1271,8 +1324,8 @@ ixl_vf_config_rss_key_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, key = msg; - if (key->key_len > 52) { - device_printf(pf->dev, "VF %d: Key size in msg (%d) is greater than max key size (%d)\n", + if (key->key_len != 52) { + device_printf(pf->dev, "VF %d: Key size in msg (%d) does not match required size (%d)\n", vf->vf_num, key->key_len, 52); i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_CONFIG_RSS_KEY, I40E_ERR_PARAM); @@ -1327,13 +1380,20 @@ ixl_vf_config_rss_lut_msg(struct ixl_pf *pf, struct ixl_vf *vf, void *msg, lut = msg; - if (lut->lut_entries > 64) { - device_printf(pf->dev, "VF %d: # of LUT entries in msg (%d) is greater than max (%d)\n", + if (lut->lut_entries != 64) { + device_printf(pf->dev, "VF %d: # of LUT entries in msg (%d) does not match required size (%d)\n", vf->vf_num, lut->lut_entries, 64); i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_CONFIG_RSS_LUT, I40E_ERR_PARAM); return; } + for (int i = 0; i < lut->lut_entries; i++) { + if (lut->lut[i] >= vf->vsi.num_rx_queues) { + i40e_send_vf_nack(pf, vf, VIRTCHNL_OP_CONFIG_RSS_LUT, + I40E_ERR_PARAM); + return; + } + } if (lut->vsi_id != vf->vsi.vsi_num) { device_printf(pf->dev, "VF %d: VSI id in recvd message (%d) does not match expected id (%d)\n", diff --git a/sys/dev/ixl/virtchnl.h b/sys/dev/ixl/virtchnl.h index f1b5777fd07b..aa8e5862fee3 100644 --- a/sys/dev/ixl/virtchnl.h +++ b/sys/dev/ixl/virtchnl.h @@ -594,6 +594,28 @@ enum virtchnl_vfr_states { VIRTCHNL_VFR_VFACTIVE, }; +/* + * Since VF messages are limited by u16 size, bound the number of nested + * elements that can be described by a single virtual channel message. + */ +enum virtchnl_vector_limits { + VIRTCHNL_OP_CONFIG_VSI_QUEUES_MAX = + ((u16)(~0) - sizeof(struct virtchnl_vsi_queue_config_info)) / + sizeof(struct virtchnl_queue_pair_info), + VIRTCHNL_OP_CONFIG_IRQ_MAP_MAX = + ((u16)(~0) - sizeof(struct virtchnl_irq_map_info)) / + sizeof(struct virtchnl_vector_map), + VIRTCHNL_OP_ADD_DEL_ETH_ADDR_MAX = + ((u16)(~0) - sizeof(struct virtchnl_ether_addr_list)) / + sizeof(struct virtchnl_ether_addr), + VIRTCHNL_OP_ADD_DEL_VLAN_MAX = + ((u16)(~0) - sizeof(struct virtchnl_vlan_filter_list)) / + sizeof(u16), + VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP_MAX = + ((u16)(~0) - sizeof(struct virtchnl_iwarp_qvlist_info)) / + sizeof(struct virtchnl_iwarp_qv_info), +}; + /** * virtchnl_vc_validate_vf_msg * @ver: Virtchnl version info @@ -608,7 +630,7 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode, u8 *msg, u16 msglen) { bool err_msg_format = FALSE; - int valid_len = 0; + u32 valid_len = 0; /* Validate message length. */ switch (v_opcode) { @@ -632,11 +654,15 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode, if (msglen >= valid_len) { struct virtchnl_vsi_queue_config_info *vqc = (struct virtchnl_vsi_queue_config_info *)msg; - valid_len += (vqc->num_queue_pairs * - sizeof(struct - virtchnl_queue_pair_info)); - if (vqc->num_queue_pairs == 0) + if (vqc->num_queue_pairs == 0 || + vqc->num_queue_pairs > + VIRTCHNL_OP_CONFIG_VSI_QUEUES_MAX) { err_msg_format = TRUE; + break; + } + + valid_len += vqc->num_queue_pairs * + sizeof(struct virtchnl_queue_pair_info); } break; case VIRTCHNL_OP_CONFIG_IRQ_MAP: @@ -644,10 +670,14 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode, if (msglen >= valid_len) { struct virtchnl_irq_map_info *vimi = (struct virtchnl_irq_map_info *)msg; - valid_len += (vimi->num_vectors * - sizeof(struct virtchnl_vector_map)); - if (vimi->num_vectors == 0) + if (vimi->num_vectors == 0 || + vimi->num_vectors > VIRTCHNL_OP_CONFIG_IRQ_MAP_MAX) { err_msg_format = TRUE; + break; + } + + valid_len += vimi->num_vectors * + sizeof(struct virtchnl_vector_map); } break; case VIRTCHNL_OP_ENABLE_QUEUES: @@ -660,10 +690,15 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode, if (msglen >= valid_len) { struct virtchnl_ether_addr_list *veal = (struct virtchnl_ether_addr_list *)msg; + if (veal->num_elements == 0 || + veal->num_elements > + VIRTCHNL_OP_ADD_DEL_ETH_ADDR_MAX) { + err_msg_format = TRUE; + break; + } + valid_len += veal->num_elements * sizeof(struct virtchnl_ether_addr); - if (veal->num_elements == 0) - err_msg_format = TRUE; } break; case VIRTCHNL_OP_ADD_VLAN: @@ -672,9 +707,13 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode, if (msglen >= valid_len) { struct virtchnl_vlan_filter_list *vfl = (struct virtchnl_vlan_filter_list *)msg; - valid_len += vfl->num_elements * sizeof(u16); - if (vfl->num_elements == 0) + if (vfl->num_elements == 0 || + vfl->num_elements > VIRTCHNL_OP_ADD_DEL_VLAN_MAX) { err_msg_format = TRUE; + break; + } + + valid_len += vfl->num_elements * sizeof(u16); } break; case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE: @@ -700,7 +739,8 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode, if (msglen >= valid_len) { struct virtchnl_iwarp_qvlist_info *qv = (struct virtchnl_iwarp_qvlist_info *)msg; - if (qv->num_vectors == 0) { + if (qv->num_vectors == 0 || qv->num_vectors > + VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP_MAX) { err_msg_format = TRUE; break; } @@ -713,6 +753,8 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode, if (msglen >= valid_len) { struct virtchnl_rss_key *vrk = (struct virtchnl_rss_key *)msg; + if (vrk->key_len == 0) + break; valid_len += vrk->key_len - 1; } break; @@ -721,6 +763,8 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode, if (msglen >= valid_len) { struct virtchnl_rss_lut *vrl = (struct virtchnl_rss_lut *)msg; + if (vrl->lut_entries == 0) + break; valid_len += vrl->lut_entries - 1; } break;