[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