[PATCH 2/2] event/cnxk: fix out of bounds access in eventdev

pbhagavatula at marvell.com pbhagavatula at marvell.com
Wed Sep 9 04:00:11 CEST 2026


From: Pavan Nikhilesh <pbhagavatula at marvell.com>

The devargs parsing helpers wrote to the parameter structure for as
long as tokens remained, so supplying more tokens than expected
overflowed the fixed-size structures. Bound each loop to the
structure size and reject input that contains extra tokens.

Likewise, cnxk_sso_xstats_get() and cnxk_sso_xstats_reset() indexed
the xstats array with caller-supplied IDs that were never validated,
so out-of-range IDs could access past the array. Skip any ID that
falls outside the valid range.

cnxk_tim_add_entry_tmo_hwwqe() used cnt as a count of LMT lines, not
timers, when computing the remainder, so nb_timers >= 8 wrote past
the LMT line. Convert cnt to a timer count first.

Fixes: 38c2e3240ba8 ("event/cnxk: add option to control SSO HWGRP QoS")
Fixes: 20345cbda6d3 ("event/cnxk: support WQE stashing")
Fixes: b5a52c9d97e2 ("event/cnxk: add event port and queue xstats")
Fixes: 8a3d58c189fd ("event/cnxk: add option to control timer adapters")
Fixes: 822d4ef519f6 ("event/cnxk: add CN20K timer adapter")
Cc: stable at dpdk.org

Signed-off-by: Pavan Nikhilesh <pbhagavatula at marvell.com>
---
 drivers/event/cnxk/cnxk_eventdev.c       |  8 +--
 drivers/event/cnxk/cnxk_eventdev_stats.c | 64 +++++++++++++++++-------
 drivers/event/cnxk/cnxk_tim_evdev.c      |  4 +-
 drivers/event/cnxk/cnxk_tim_worker.h     |  1 +
 4 files changed, 52 insertions(+), 25 deletions(-)

diff --git a/drivers/event/cnxk/cnxk_eventdev.c b/drivers/event/cnxk/cnxk_eventdev.c
index 41079af2a95c..e3a3134264fe 100644
--- a/drivers/event/cnxk/cnxk_eventdev.c
+++ b/drivers/event/cnxk/cnxk_eventdev.c
@@ -488,13 +488,13 @@ parse_queue_param(char *value, void *opaque)
 	if (!strlen(value))
 		return;
 
-	while (tok != NULL) {
+	while (tok != NULL && val < (&queue_qos.iaq_prcnt + 1)) {
 		*val = atoi(tok);
 		tok = strtok(NULL, "-");
 		val++;
 	}
 
-	if (val != (&queue_qos.iaq_prcnt + 1)) {
+	if (tok != NULL || val != (&queue_qos.iaq_prcnt + 1)) {
 		plt_err("Invalid QoS parameter expected [Qx-TAQ-IAQ]");
 		return;
 	}
@@ -525,13 +525,13 @@ parse_stash_param(char *value, void *opaque)
 		return;
 
 	val = (uint16_t *)&queue_stash;
-	while (tok != NULL) {
+	while (tok != NULL && val < (&queue_stash.stash_length + 1)) {
 		*val = atoi(tok);
 		tok = strtok(NULL, "|");
 		val++;
 	}
 
-	if (val != (&queue_stash.stash_length + 1)) {
+	if (tok != NULL || val != (&queue_stash.stash_length + 1)) {
 		plt_err("Invalid QoS parameter expected [Qx|stash_offset|stash_length]");
 		return;
 	}
diff --git a/drivers/event/cnxk/cnxk_eventdev_stats.c b/drivers/event/cnxk/cnxk_eventdev_stats.c
index 6dea91aedf31..d88e6130b9dd 100644
--- a/drivers/event/cnxk/cnxk_eventdev_stats.c
+++ b/drivers/event/cnxk/cnxk_eventdev_stats.c
@@ -157,6 +157,8 @@ cnxk_sso_xstats_get(const struct rte_eventdev *event_dev,
 	};
 
 	for (i = 0; i < n && i < xstats_mode_count; i++) {
+		if (ids[i] < start_offset || (ids[i] - start_offset) >= xstats_mode_count)
+			goto invalid_value;
 		xstat = &xstats[ids[i] - start_offset];
 		value = *(uint64_t *)((char *)rsp + xstat->offset);
 		value = (value >> xstat->shift) & xstat->mask;
@@ -181,6 +183,7 @@ cnxk_sso_xstats_reset(struct rte_eventdev *event_dev,
 	struct cnxk_sso_xstats_name *xstat;
 	struct roc_sso_hws_stats hws_stats;
 	uint32_t xstats_mode_count = 0;
+	int16_t first_id, last_id, id;
 	uint32_t start_offset = 0;
 	unsigned int i;
 	uint64_t value;
@@ -191,44 +194,67 @@ cnxk_sso_xstats_reset(struct rte_eventdev *event_dev,
 	case RTE_EVENT_DEV_XSTATS_DEVICE:
 		return 0;
 	case RTE_EVENT_DEV_XSTATS_PORT:
-		if (queue_port_id >= (signed int)dev->nb_event_ports)
+		if (queue_port_id >= (int16_t)dev->nb_event_ports)
 			goto invalid_value;
 
 		xstats_mode_count = CNXK_SSO_NUM_HWS_XSTATS;
 		xstats = sso_hws_xstats;
-		rc = roc_sso_hws_stats_get(&dev->sso, queue_port_id,
-					   &hws_stats);
-		if (rc < 0)
-			goto invalid_value;
-		rsp = &hws_stats;
+		/* Negative id requests a reset of all ports. */
+		first_id = (queue_port_id < 0) ? 0 : queue_port_id;
+		last_id = (queue_port_id < 0) ? (int16_t)dev->nb_event_ports - 1 : queue_port_id;
 		break;
 	case RTE_EVENT_DEV_XSTATS_QUEUE:
-		if (queue_port_id >= (signed int)dev->nb_event_queues)
+		if (queue_port_id >= (int16_t)dev->nb_event_queues)
 			goto invalid_value;
 
 		xstats_mode_count = CNXK_SSO_NUM_GRP_XSTATS;
 		start_offset = CNXK_SSO_NUM_HWS_XSTATS;
 		xstats = sso_hwgrp_xstats;
-
-		rc = roc_sso_hwgrp_stats_get(&dev->sso, queue_port_id,
-					     &hwgrp_stats);
-		if (rc < 0)
-			goto invalid_value;
-		rsp = &hwgrp_stats;
+		/* Negative id requests a reset of all queues. */
+		first_id = (queue_port_id < 0) ? 0 : queue_port_id;
+		last_id = (queue_port_id < 0) ? (int16_t)dev->nb_event_queues - 1 : queue_port_id;
 		break;
 	default:
 		plt_err("Invalid mode received");
 		goto invalid_value;
 	};
 
-	for (i = 0; i < n && i < xstats_mode_count; i++) {
-		xstat = &xstats[ids[i] - start_offset];
-		value = *(uint64_t *)((char *)rsp + xstat->offset);
-		value = (value >> xstat->shift) & xstat->mask;
+	for (id = first_id; id <= last_id; id++) {
+		if (mode == RTE_EVENT_DEV_XSTATS_PORT) {
+			rc = roc_sso_hws_stats_get(&dev->sso, id, &hws_stats);
+			if (rc < 0)
+				goto invalid_value;
+			rsp = &hws_stats;
+		} else {
+			rc = roc_sso_hwgrp_stats_get(&dev->sso, id, &hwgrp_stats);
+			if (rc < 0)
+				goto invalid_value;
+			rsp = &hwgrp_stats;
+		}
 
-		xstat->reset_snap[queue_port_id] = value;
+		if (ids == NULL) {
+			for (i = 0; i < xstats_mode_count; i++) {
+				xstat = &xstats[i];
+				value = *(uint64_t *)((char *)rsp + xstat->offset);
+				value = (value >> xstat->shift) & xstat->mask;
+
+				xstat->reset_snap[id] = value;
+			}
+			continue;
+		}
+
+		for (i = 0; i < n; i++) {
+			if (ids[i] < start_offset || (ids[i] - start_offset) >= xstats_mode_count)
+				goto invalid_value;
+			xstat = &xstats[ids[i] - start_offset];
+			value = *(uint64_t *)((char *)rsp + xstat->offset);
+			value = (value >> xstat->shift) & xstat->mask;
+
+			xstat->reset_snap[id] = value;
+		}
 	}
-	return i;
+
+	return 0;
 invalid_value:
 	return -EINVAL;
 }
diff --git a/drivers/event/cnxk/cnxk_tim_evdev.c b/drivers/event/cnxk/cnxk_tim_evdev.c
index 75414408776d..44acd4ef5170 100644
--- a/drivers/event/cnxk/cnxk_tim_evdev.c
+++ b/drivers/event/cnxk/cnxk_tim_evdev.c
@@ -471,13 +471,13 @@ cnxk_tim_parse_ring_param(char *value, void *opaque)
 	if (!strlen(value))
 		return;
 
-	while (tok != NULL) {
+	while (tok != NULL && val < (&ring_ctl.enable_stats + 1)) {
 		*val = atoi(tok);
 		tok = strtok(NULL, "-");
 		val++;
 	}
 
-	if (val != (&ring_ctl.enable_stats + 1)) {
+	if (tok != NULL || val != (&ring_ctl.enable_stats + 1)) {
 		plt_err("Invalid ring param expected [ring-chunk_sz-disable_npa-enable_stats]");
 		return;
 	}
diff --git a/drivers/event/cnxk/cnxk_tim_worker.h b/drivers/event/cnxk/cnxk_tim_worker.h
index 6a9099a23f3a..9e33ff58d683 100644
--- a/drivers/event/cnxk/cnxk_tim_worker.h
+++ b/drivers/event/cnxk/cnxk_tim_worker.h
@@ -726,6 +726,7 @@ cnxk_tim_add_entry_tmo_hwwqe(struct cnxk_tim_ring *const tim_ring,
 		}
 	}
 
+	cnt *= CNXK_TIM_ENT_PER_LMT;
 	/* SIZEM1 is 0 */
 	pa = (tim_ring->tbase & ~0xFF) + TIM_LF_SCHED_TIMER0;
 	pa |= (uint64_t)((nb_timers - cnt) << 4);
-- 
2.50.1 (Apple Git-155)



More information about the stable mailing list