[PATCH 1/6] net/bnxt: fix use after free when freeing filters

Stephen Hemminger stephen at networkplumber.org
Thu Sep 17 19:19:39 CEST 2026


bnxt_free_filter_mem() freed each filter and then passed the freed
pointer to STAILQ_REMOVE, which walks the list to unlink it.
STAILQ_FOREACH also read the next pointer out of the freed element.

Remove the entry from the list before freeing it, and use
STAILQ_FOREACH_SAFE so that the iteration does not depend on the
element that was just freed. glibc does not provide the _SAFE
variants, so define it locally the same way several other drivers
already do.

Found while moving the list macros into a DPDK header, where the
compiler could see them and report -Wuse-after-free. The fix does
not depend on that work.

Fixes: f11fd694a84a ("net/bnxt: free memory allocated for VF filters")
Cc: stable at dpdk.org

Signed-off-by: Stephen Hemminger <stephen at networkplumber.org>
---
 drivers/net/bnxt/bnxt_filter.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/net/bnxt/bnxt_filter.c b/drivers/net/bnxt/bnxt_filter.c
index 7b90ba651f..0225215dae 100644
--- a/drivers/net/bnxt/bnxt_filter.c
+++ b/drivers/net/bnxt/bnxt_filter.c
@@ -18,6 +18,13 @@
 #include "bnxt_vnic.h"
 #include "hsi_struct_def_dpdk.h"
 
+#ifndef STAILQ_FOREACH_SAFE
+#define	STAILQ_FOREACH_SAFE(var, head, field, tvar)			\
+	for ((var) = STAILQ_FIRST((head));				\
+	    (var) && ((tvar) = STAILQ_NEXT((var), field), 1);		\
+	    (var) = (tvar))
+#endif
+
 /*
  * Filter Functions
  */
@@ -110,7 +117,7 @@ void bnxt_free_all_filters(struct bnxt *bp)
 
 void bnxt_free_filter_mem(struct bnxt *bp)
 {
-	struct bnxt_filter_info *filter;
+	struct bnxt_filter_info *filter, *temp_filter;
 	uint16_t max_filters, i;
 	int rc = 0;
 
@@ -151,10 +158,11 @@ void bnxt_free_filter_mem(struct bnxt *bp)
 	bp->filter_info = NULL;
 
 	for (i = 0; i < bp->pf->max_vfs; i++) {
-		STAILQ_FOREACH(filter, &bp->pf->vf_info[i].filter, next) {
-			rte_free(filter);
+		STAILQ_FOREACH_SAFE(filter, &bp->pf->vf_info[i].filter, next,
+				    temp_filter) {
 			STAILQ_REMOVE(&bp->pf->vf_info[i].filter, filter,
 				      bnxt_filter_info, next);
+			rte_free(filter);
 		}
 	}
 }
-- 
2.53.0



More information about the stable mailing list