patch 'net/bnxt/tf_ulp: enforce bounds in bitstream extraction' has been queued to stable release 24.11.9

luca.boccassi at gmail.com luca.boccassi at gmail.com
Tue Oct 27 12:51:07 CET 2026


Hi,

FYI, your patch has been queued to stable release 24.11.9

Note it hasn't been pushed to http://dpdk.org/browse/dpdk-stable yet.
It will be pushed if I get no objections before 10/29/26. So please
shout if anyone has objections.

Also note that after the patch there's a diff of the upstream commit vs the
patch applied to the branch. This will indicate if there was any rebasing
needed to apply to the stable branch. If there were code changes for rebasing
(ie: not only metadata diffs), please double check that the rebase was
correctly done.

Queued patches are on a temporary branch at:
https://github.com/bluca/dpdk-stable

This queued commit can be viewed at:
https://github.com/bluca/dpdk-stable/commit/0975c18d8c11dca4db875b10228f5386dfd47d2d

Thanks.

Luca Boccassi

---
>From 0975c18d8c11dca4db875b10228f5386dfd47d2d Mon Sep 17 00:00:00 2001
From: Joey Zhong <xiaozhen.zhong at broadcom.com>
Date: Mon, 5 Oct 2026 15:25:26 -0500
Subject: [PATCH] net/bnxt/tf_ulp: enforce bounds in bitstream extraction

[ upstream commit dcd7cc960b8ab5cc6b1b0b8d7392606dee5548ca ]

GCC inlines ulp_bs_pull_lsb() and flags the remainder branch:
  if (len)
      ulp_bs_get_lsb(src, offset, len, &dst[size - 1 - idx]);
After the full-byte loop exits, idx == cnt. When cnt == size with a
non-zero bit remainder (e.g., len = 33 with size = 4), the subscript
size - 1 - idx underflows to UINT32_MAX, producing a -Warray-bounds
false positive (and a genuine out-of-bounds write if len/size are
ever miscalculated upstream of the check that normally prevents
this). ulp_blob_pull() rejects this state via its
ULP_BYTE_2_BITS(data_size) < len check, but GCC cannot carry that
constraint through the inlined call chain.

Changes:
- ulp_bs_pull_lsb / ulp_bs_pull_msb: add unlikely(cnt > size) entry
  guard and an explicit likely(idx < size) check on the remainder
  branch so GCC can prove all subscripts are in range.
- ulp_bs_pull_msb: add the missing uint32_t size parameter (matching
  ulp_bs_pull_lsb) and update its three call sites to pass the
  destination buffer size.
- ulp_bs_get_lsb / ulp_bs_get_msb: add unlikely(!bitlen) early exit
  to make the zero-length contract explicit.

Fixes: f634204b7ad8 ("net/bnxt: support generic table processing")

Signed-off-by: Joey Zhong <xiaozhen.zhong at broadcom.com>
Signed-off-by: Manish Kurup <manish.kurup at broadcom.com>
---
 .mailmap                              |  1 +
 drivers/net/bnxt/tf_ulp/ulp_gen_tbl.c |  2 +-
 drivers/net/bnxt/tf_ulp/ulp_mapper.c  |  1 +
 drivers/net/bnxt/tf_ulp/ulp_utils.h   | 44 +++++++++++++++++++++++----
 4 files changed, 41 insertions(+), 7 deletions(-)

diff --git a/.mailmap b/.mailmap
index 43e685a94ba..ba40649399d 100644
--- a/.mailmap
+++ b/.mailmap
@@ -749,6 +749,7 @@ Job Abraham <job.abraham at intel.com>
 Jochen Behrens <jochen.behrens at broadcom.com> <jbehrens at vmware.com>
 Joel Kavanagh <joel.kavanagh at intel.com>
 Joey Xing <joey.xing at jaguarmicro.com>
+Joey Zhong <xiaozhen.zhong at broadcom.com>
 Johan Faltstrom <johan.faltstrom at netinsight.net>
 Johan Källström <johan.kallstrom at ericsson.com>
 Johan Samuelsson <johan.xb.samuelsson at ericsson.com>
diff --git a/drivers/net/bnxt/tf_ulp/ulp_gen_tbl.c b/drivers/net/bnxt/tf_ulp/ulp_gen_tbl.c
index c2ae3dc3a2a..de58368a907 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_gen_tbl.c
+++ b/drivers/net/bnxt/tf_ulp/ulp_gen_tbl.c
@@ -309,7 +309,7 @@ ulp_mapper_gen_tbl_entry_data_get(struct ulp_mapper_gen_tbl_entry *entry,
 	if (entry->byte_order == BNXT_ULP_BYTE_ORDER_LE)
 		ulp_bs_pull_lsb(entry->byte_data, data, data_size, offset, len);
 	else
-		ulp_bs_pull_msb(entry->byte_data, data, offset, len);
+		ulp_bs_pull_msb(entry->byte_data, data, data_size, offset, len);
 
 	return 0;
 }
diff --git a/drivers/net/bnxt/tf_ulp/ulp_mapper.c b/drivers/net/bnxt/tf_ulp/ulp_mapper.c
index 70294b35c28..d24c0540c8e 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_mapper.c
+++ b/drivers/net/bnxt/tf_ulp/ulp_mapper.c
@@ -716,6 +716,7 @@ ulp_mapper_tbl_ident_scan_ext(struct bnxt_ulp_mapper_parms *parms,
 					idents[i].ident_bit_size);
 		else
 			ulp_bs_pull_msb(byte_data, (uint8_t *)&val64,
+					sizeof(val64),
 					idents[i].ident_bit_pos,
 					idents[i].ident_bit_size);
 
diff --git a/drivers/net/bnxt/tf_ulp/ulp_utils.h b/drivers/net/bnxt/tf_ulp/ulp_utils.h
index ce20f1916f0..5cb6e48b37e 100644
--- a/drivers/net/bnxt/tf_ulp/ulp_utils.h
+++ b/drivers/net/bnxt/tf_ulp/ulp_utils.h
@@ -663,6 +663,11 @@ ulp_bs_get_lsb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst)
 	uint16_t index  = ULP_BITS_2_BYTE_NR(bitpos);
 	uint8_t mask, partial, shift;
 
+	if (unlikely(!bitlen)) {
+		*dst = 0;
+		return;
+	}
+
 	shift = bitoffs;
 	partial = ULP_BLOB_BYTE - bitoffs;
 	if (bitoffs + bitlen <= ULP_BLOB_BYTE) {
@@ -700,6 +705,16 @@ ulp_bs_pull_lsb(uint8_t *src, uint8_t *dst, uint32_t size,
 	uint32_t idx;
 	uint32_t cnt = ULP_BITS_2_BYTE_NR(len);
 
+	/*
+	 * cnt > size means len >= (size + 1) * 8; caller should have
+	 * rejected this. It does not catch size*8 < len < (size + 1)*8,
+	 * which also can't fit in dst: there cnt == size, so idx == size
+	 * after the loop below, which makes "idx < size" false and
+	 * silently drops the remainder instead of writing past dst.
+	 */
+	if (unlikely(cnt > size))
+		return;
+
 	/* iterate bytewise to get data */
 	for (idx = 0; idx < cnt; idx++) {
 		ulp_bs_get_lsb(src, offset, ULP_BLOB_BYTE,
@@ -708,8 +723,8 @@ ulp_bs_pull_lsb(uint8_t *src, uint8_t *dst, uint32_t size,
 		len -= ULP_BLOB_BYTE;
 	}
 
-	/* Extract the last reminder data that is not 8 byte boundary */
-	if (len)
+	/* Extract the last remainder data that is not 8 byte boundary */
+	if (len && likely(idx < size))
 		ulp_bs_get_lsb(src, offset, len, &dst[size - 1 - idx]);
 }
 
@@ -735,6 +750,11 @@ ulp_bs_get_msb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst)
 	uint8_t mask;
 	int32_t shift;
 
+	if (unlikely(!bitlen)) {
+		*dst = 0;
+		return;
+	}
+
 	shift = ULP_BLOB_BYTE - bitoffs - bitlen;
 	if (shift >= 0) {
 		mask = 0xFF >> -bitlen;
@@ -752,6 +772,8 @@ ulp_bs_get_msb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst)
  *
  * dst [out] The byte array where data is pulled into
  *
+ * size [in] The size of dst array in bytes
+ *
  * offset [in] The offset where data is pulled
  *
  * len [in] The number of bits to be extracted from the data array
@@ -759,12 +781,22 @@ ulp_bs_get_msb(uint8_t *src, uint16_t bitpos, uint8_t bitlen, uint8_t *dst)
  * returns None.
  */
 static inline void
-ulp_bs_pull_msb(uint8_t *src, uint8_t *dst,
+ulp_bs_pull_msb(uint8_t *src, uint8_t *dst, uint32_t size,
 		uint32_t offset, uint32_t len)
 {
 	uint32_t idx;
 	uint32_t cnt = ULP_BITS_2_BYTE_NR(len);
 
+	/*
+	 * cnt > size means len >= (size + 1) * 8; caller should have
+	 * rejected this. It does not catch size*8 < len < (size + 1)*8,
+	 * which also can't fit in dst: there cnt == size, so idx == size
+	 * after the loop below, which makes "idx < size" false and
+	 * silently drops the remainder instead of writing past dst.
+	 */
+	if (unlikely(cnt > size))
+		return;
+
 	/* iterate bytewise to get data */
 	for (idx = 0; idx < cnt; idx++) {
 		ulp_bs_get_msb(src, offset, ULP_BLOB_BYTE, &dst[idx]);
@@ -772,8 +804,8 @@ ulp_bs_pull_msb(uint8_t *src, uint8_t *dst,
 		len -= ULP_BLOB_BYTE;
 	}
 
-	/* Extract the last reminder data that is not 8 byte boundary */
-	if (len)
+	/* Extract the last remainder data that is not 8 byte boundary */
+	if (len && likely(idx < size))
 		ulp_bs_get_msb(src, offset, len, &dst[idx]);
 }
 
@@ -802,7 +834,7 @@ ulp_blob_pull(struct ulp_blob *blob, uint8_t *data, uint32_t data_size,
 	}
 
 	if (blob->byte_order == BNXT_ULP_BYTE_ORDER_BE)
-		ulp_bs_pull_msb(blob->data, data, offset, len);
+		ulp_bs_pull_msb(blob->data, data, data_size, offset, len);
 	else
 		ulp_bs_pull_lsb(blob->data, data, data_size, offset, len);
 	return 0;
-- 
2.47.3

---
  Diff of the applied patch vs upstream commit (please double-check if non-empty:
---
--- -	2026-10-27 11:44:00.354408957 +0000
+++ 0173-net-bnxt-tf_ulp-enforce-bounds-in-bitstream-extracti.patch	2026-10-27 11:43:53.758067000 +0000
@@ -1 +1 @@
-From dcd7cc960b8ab5cc6b1b0b8d7392606dee5548ca Mon Sep 17 00:00:00 2001
+From 0975c18d8c11dca4db875b10228f5386dfd47d2d Mon Sep 17 00:00:00 2001
@@ -5,0 +6,2 @@
+[ upstream commit dcd7cc960b8ab5cc6b1b0b8d7392606dee5548ca ]
+
@@ -29 +30,0 @@
-Cc: stable at dpdk.org
@@ -41 +42 @@
-index b2fe3166d6..6b81952a55 100644
+index 43e685a94ba..ba40649399d 100644
@@ -44 +45 @@
-@@ -792,6 +792,7 @@ Job Abraham <job.abraham at intel.com>
+@@ -749,6 +749,7 @@ Job Abraham <job.abraham at intel.com>
@@ -53 +54 @@
-index ac0a7e6db1..535849b1f9 100644
+index c2ae3dc3a2a..de58368a907 100644
@@ -66 +67 @@
-index 960cdda311..168f05a5a4 100644
+index 70294b35c28..d24c0540c8e 100644
@@ -69 +70 @@
-@@ -701,6 +701,7 @@ ulp_mapper_tbl_ident_scan_ext(struct bnxt_ulp_mapper_parms *parms,
+@@ -716,6 +716,7 @@ ulp_mapper_tbl_ident_scan_ext(struct bnxt_ulp_mapper_parms *parms,
@@ -78 +79 @@
-index ce20f1916f..5cb6e48b37 100644
+index ce20f1916f0..5cb6e48b37e 100644


More information about the stable mailing list