From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 94A5345E2F for ; Wed, 4 Dec 2024 14:56:43 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 8DA5E40A87; Wed, 4 Dec 2024 14:56:43 +0100 (CET) Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.19]) by mails.dpdk.org (Postfix) with ESMTP id 4F2D440A87 for ; Wed, 4 Dec 2024 14:56:41 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1733320601; x=1764856601; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=W2gaQgJ81A7IgI8Cp9UOU5dNBubrAvtLXNUQIqwZo6I=; b=O/QN+lkFh82UaLi9F72xif1O8qNtXPv5xi53e9UOuG00iackrGQSSXzH 0UBRyBhSHXA33Kas12l6H1sS5NzXW/XRsGEXCHNc/h5FrqJoyRohIcMLI DCsF+bN3hecoOgMjQxcJ6RNd5FjMY/L3qZAqxov3Tux57l0bxYue7vt9N fV4sZ94k1bLFnCTYZN4aPDl+fV7uakvDmc5axE02LgE82Hz696yIp2dNb A6zTH+OdzXaAPnOf7KznHC+Kn9PgVBgseqbruyrGB7+m1/mkjQxwsfQkL CXw4RwknvJmr6emT5oytDtcmm7w7BEbJEb6zK5zAXzWrUMq8bnSkHM0tZ w==; X-CSE-ConnectionGUID: Q1clqBtkTK2fLiEiWivo4A== X-CSE-MsgGUID: YmSOpfsfQ5mXgwWrPNFRtw== X-IronPort-AV: E=McAfee;i="6700,10204,11276"; a="32928771" X-IronPort-AV: E=Sophos;i="6.12,207,1728975600"; d="scan'208";a="32928771" Received: from orviesa004.jf.intel.com ([10.64.159.144]) by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Dec 2024 05:56:40 -0800 X-CSE-ConnectionGUID: 3qO0xTWaTX2GRTCH422KFQ== X-CSE-MsgGUID: BKUYCsBPStyVlRcn7PxSKw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,207,1728975600"; d="scan'208";a="98840778" Received: from silpixa00401197coob.ir.intel.com (HELO silpixa00401385.ir.intel.com) ([10.237.214.45]) by orviesa004.jf.intel.com with ESMTP; 04 Dec 2024 05:56:39 -0800 From: Bruce Richardson To: stable@dpdk.org Cc: ktraynor@redhat.com, Fabio Pricoco , Jacob Keller , Soumyadeep Hore , Bruce Richardson Subject: [PATCH 21.11] net/ice/base: fix iteration of TLVs in Preserved Fields Area Date: Wed, 4 Dec 2024 13:56:25 +0000 Message-ID: <20241204135625.2841607-1-bruce.richardson@intel.com> X-Mailer: git-send-email 2.43.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: stable@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: patches for DPDK stable branches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: stable-bounces@dpdk.org From: Fabio Pricoco Backport of commit dcb760bf0f95 ("net/ice/base: fix iteration of TLVs in Preserved Fields Area"), for 21.11 release, replacing the use of __builtin_add_overflow with an inline function to avoid breaking RHEL/Centos 7. The ice_get_pfa_module_tlv() function iterates over the Preserved Fields Area to read data from the Shadow RAM, including the Part Board Assembly data, among others. If the specific TLV being requested is not found in the current NVM, the code will read past the end of the PFA, misinterpreting the last word of the PFA and the word just after the PFA as another TLV. This typically results in one extra iteration before the length check of the while loop is triggered. Correct the logic for determining the maximum PFA offset to include the extra last word. Additionally, make the driver robust against overflows by using check_add_overflow. This ensures that even if the NVM provides bogus data, the driver will not overflow, and will instead log a useful warning message. The check for whether the TLV length exceeds the PFA length is also removed, in favor of relying on the overflow warning instead. Fixes: 5d0b7b5fc491 ("net/ice/base: add read PBA module function") Cc: stable@dpdk.org Signed-off-by: Fabio Pricoco Signed-off-by: Jacob Keller Signed-off-by: Soumyadeep Hore Signed-off-by: Bruce Richardson --- drivers/net/ice/base/ice_nvm.c | 43 ++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/drivers/net/ice/base/ice_nvm.c b/drivers/net/ice/base/ice_nvm.c index 48e0d418e2..0d160a30a0 100644 --- a/drivers/net/ice/base/ice_nvm.c +++ b/drivers/net/ice/base/ice_nvm.c @@ -426,6 +426,15 @@ enum ice_status ice_read_sr_word(struct ice_hw *hw, u16 offset, u16 *data) return status; } +static inline bool +check_add_overflow(uint16_t a, uint16_t b, uint16_t *out) +{ + uint32_t val = (uint32_t)a + (uint32_t)b; + *out = (uint16_t)val; + + return (val > UINT16_MAX); +} + /** * ice_get_pfa_module_tlv - Reads sub module TLV from NVM PFA * @hw: pointer to hardware structure @@ -442,8 +451,7 @@ ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len, u16 module_type) { enum ice_status status; - u16 pfa_len, pfa_ptr; - u32 next_tlv; + u16 pfa_len, pfa_ptr, next_tlv, max_tlv; status = ice_read_sr_word(hw, ICE_SR_PFA_PTR, &pfa_ptr); if (status != ICE_SUCCESS) { @@ -455,11 +463,23 @@ ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len, ice_debug(hw, ICE_DBG_INIT, "Failed to read PFA length.\n"); return status; } - /* Starting with first TLV after PFA length, iterate through the list + + if (check_add_overflow(pfa_ptr, (u16)(pfa_len - 1), &max_tlv)) { + ice_debug(hw, ICE_DBG_INIT, "PFA starts at offset %u. PFA length of %u caused 16-bit arithmetic overflow.\n", + pfa_ptr, pfa_len); + return ICE_ERR_INVAL_SIZE; + } + + /* The Preserved Fields Area contains a sequence of TLVs which define + * its contents. The PFA length includes all of the TLVs, plus its + * initial length word itself, *and* one final word at the end of all + * of the TLVs. + * + * Starting with first TLV after PFA length, iterate through the list * of TLVs to find the requested one. */ next_tlv = pfa_ptr + 1; - while (next_tlv < ((u32)pfa_ptr + pfa_len)) { + while (next_tlv < max_tlv) { u16 tlv_sub_module_type; u16 tlv_len; @@ -476,10 +496,6 @@ ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len, ice_debug(hw, ICE_DBG_INIT, "Failed to read TLV length.\n"); break; } - if (tlv_len > pfa_len) { - ice_debug(hw, ICE_DBG_INIT, "Invalid TLV length.\n"); - return ICE_ERR_INVAL_SIZE; - } if (tlv_sub_module_type == module_type) { if (tlv_len) { *module_tlv = (u16)next_tlv; @@ -488,10 +504,13 @@ ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len, } return ICE_ERR_INVAL_SIZE; } - /* Check next TLV, i.e. current TLV pointer + length + 2 words - * (for current TLV's type and length) - */ - next_tlv = next_tlv + tlv_len + 2; + + if (check_add_overflow(next_tlv, (u16)2, &next_tlv) || + check_add_overflow(next_tlv, tlv_len, &next_tlv)) { + ice_debug(hw, ICE_DBG_INIT, "TLV of type %u and length 0x%04x caused 16-bit arithmetic overflow. The PFA starts at 0x%04x and has length of 0x%04x\n", + tlv_sub_module_type, tlv_len, pfa_ptr, pfa_len); + return ICE_ERR_INVAL_SIZE; + } } /* Module does not exist */ return ICE_ERR_DOES_NOT_EXIST; -- 2.43.0