From: Stephen Hemminger <stephen@networkplumber.org>
To: dev@dpdk.org
Cc: Stephen Hemminger <stephen@networkplumber.org>,
stable@dpdk.org, Naga Harish K S V <s.v.naga.harish.k@intel.com>,
Jerin Jacob <jerinj@marvell.com>,
Ganapati Kundapura <ganapati.kundapura@intel.com>,
Jay Jayatheerthan <jay.jayatheerthan@intel.com>
Subject: [PATCH 6/8] eventdev/eth_rx: fix thread-unsafe telemetry parsing
Date: Fri, 5 Jun 2026 13:51:03 -0700 [thread overview]
Message-ID: <20260605205253.520196-7-stephen@networkplumber.org> (raw)
In-Reply-To: <20260605205253.520196-1-stephen@networkplumber.org>
The eth Rx adapter telemetry handlers parse multi-field parameter
strings with a strtok()/strtok(NULL, ...) continuation chain.
Since strtok() holds its parser state in a process-global static,
and telemetry callbacks run in a separate thread per client connection.
With concurrent clients the continuation calls read another thread's
state - and since each handler strdup()s and frees its own buffer,
a stale continuation can dereference freed memory.
Thread the parse through a local save pointer with strtok_r().
Also passing was passing a char to isdigit(), which is undefined
in C standard for high-bit input.
Fixes: 814d01709328 ("eventdev/eth_rx: support telemetry")
Cc: stable@dpdk.org
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
lib/eventdev/rte_event_eth_rx_adapter.c | 52 ++++++++++++-------------
1 file changed, 26 insertions(+), 26 deletions(-)
diff --git a/lib/eventdev/rte_event_eth_rx_adapter.c b/lib/eventdev/rte_event_eth_rx_adapter.c
index 2183adce6f..96a4a0d926 100644
--- a/lib/eventdev/rte_event_eth_rx_adapter.c
+++ b/lib/eventdev/rte_event_eth_rx_adapter.c
@@ -308,7 +308,7 @@ rxa_event_buf_get(struct event_eth_rx_adapter *rx_adapter, uint16_t eth_dev_id,
} while (0)
#define RTE_EVENT_ETH_RX_ADAPTER_TOKEN_VALID_OR_GOTO_ERR_RET(token, retval) do { \
- if ((token) == NULL || strlen(token) == 0 || !isdigit(*token)) { \
+ if ((token) == NULL || strlen(token) == 0 || !isdigit((unsigned char)*token)) { \
RTE_EDEV_LOG_ERR("Invalid eth Rx adapter token"); \
ret = retval; \
goto error; \
@@ -3764,7 +3764,7 @@ handle_rxa_stats(const char *cmd __rte_unused,
uint8_t rx_adapter_id;
struct rte_event_eth_rx_adapter_stats rx_adptr_stats;
- if (params == NULL || strlen(params) == 0 || !isdigit(*params))
+ if (params == NULL || strlen(params) == 0 || !isdigit((unsigned char)*params))
return -1;
/* Get Rx adapter ID from parameter string */
@@ -3804,7 +3804,7 @@ handle_rxa_stats_reset(const char *cmd __rte_unused,
{
uint8_t rx_adapter_id;
- if (params == NULL || strlen(params) == 0 || !isdigit(*params))
+ if (params == NULL || strlen(params) == 0 || !isdigit((unsigned char)*params))
return -1;
/* Get Rx adapter ID from parameter string */
@@ -3829,29 +3829,29 @@ handle_rxa_get_queue_conf(const char *cmd __rte_unused,
uint16_t rx_queue_id;
uint16_t eth_dev_id;
int ret = -1;
- char *token, *l_params;
+ char *token, *l_params, *saveptr = NULL;
struct rte_event_eth_rx_adapter_queue_conf queue_conf;
- if (params == NULL || strlen(params) == 0 || !isdigit(*params))
+ if (params == NULL || strlen(params) == 0 || !isdigit((unsigned char)*params))
return -1;
/* Get Rx adapter ID from parameter string */
l_params = strdup(params);
if (l_params == NULL)
return -ENOMEM;
- token = strtok(l_params, ",");
+ token = strtok_r(l_params, ",", &saveptr);
RTE_EVENT_ETH_RX_ADAPTER_TOKEN_VALID_OR_GOTO_ERR_RET(token, -1);
rx_adapter_id = strtoul(token, NULL, 10);
RTE_EVENT_ETH_RX_ADAPTER_ID_VALID_OR_GOTO_ERR_RET(rx_adapter_id, -EINVAL);
- token = strtok(NULL, ",");
+ token = strtok_r(NULL, ",", &saveptr);
RTE_EVENT_ETH_RX_ADAPTER_TOKEN_VALID_OR_GOTO_ERR_RET(token, -1);
/* Get device ID from parameter string */
eth_dev_id = strtoul(token, NULL, 10);
RTE_EVENT_ETH_RX_ADAPTER_PORTID_VALID_OR_GOTO_ERR_RET(eth_dev_id, -EINVAL);
- token = strtok(NULL, ",");
+ token = strtok_r(NULL, ",", &saveptr);
RTE_EVENT_ETH_RX_ADAPTER_TOKEN_VALID_OR_GOTO_ERR_RET(token, -1);
/* Get Rx queue ID from parameter string */
@@ -3862,7 +3862,7 @@ handle_rxa_get_queue_conf(const char *cmd __rte_unused,
goto error;
}
- token = strtok(NULL, "\0");
+ token = strtok_r(NULL, "\0", &saveptr);
if (token != NULL)
RTE_EDEV_LOG_ERR("Extra parameters passed to eventdev"
" telemetry command, ignoring");
@@ -3902,29 +3902,29 @@ handle_rxa_get_queue_stats(const char *cmd __rte_unused,
uint16_t rx_queue_id;
uint16_t eth_dev_id;
int ret = -1;
- char *token, *l_params;
+ char *token, *l_params, *saveptr = NULL;
struct rte_event_eth_rx_adapter_queue_stats q_stats;
- if (params == NULL || strlen(params) == 0 || !isdigit(*params))
+ if (params == NULL || strlen(params) == 0 || !isdigit((unsigned char)*params))
return -1;
/* Get Rx adapter ID from parameter string */
l_params = strdup(params);
if (l_params == NULL)
return -ENOMEM;
- token = strtok(l_params, ",");
+ token = strtok_r(l_params, ",", &saveptr);
RTE_EVENT_ETH_RX_ADAPTER_TOKEN_VALID_OR_GOTO_ERR_RET(token, -1);
rx_adapter_id = strtoul(token, NULL, 10);
RTE_EVENT_ETH_RX_ADAPTER_ID_VALID_OR_GOTO_ERR_RET(rx_adapter_id, -EINVAL);
- token = strtok(NULL, ",");
+ token = strtok_r(NULL, ",", &saveptr);
RTE_EVENT_ETH_RX_ADAPTER_TOKEN_VALID_OR_GOTO_ERR_RET(token, -1);
/* Get device ID from parameter string */
eth_dev_id = strtoul(token, NULL, 10);
RTE_EVENT_ETH_RX_ADAPTER_PORTID_VALID_OR_GOTO_ERR_RET(eth_dev_id, -EINVAL);
- token = strtok(NULL, ",");
+ token = strtok_r(NULL, ",", &saveptr);
RTE_EVENT_ETH_RX_ADAPTER_TOKEN_VALID_OR_GOTO_ERR_RET(token, -1);
/* Get Rx queue ID from parameter string */
@@ -3935,7 +3935,7 @@ handle_rxa_get_queue_stats(const char *cmd __rte_unused,
goto error;
}
- token = strtok(NULL, "\0");
+ token = strtok_r(NULL, "\0", &saveptr);
if (token != NULL)
RTE_EDEV_LOG_ERR("Extra parameters passed to eventdev"
" telemetry command, ignoring");
@@ -3974,28 +3974,28 @@ handle_rxa_queue_stats_reset(const char *cmd __rte_unused,
uint16_t rx_queue_id;
uint16_t eth_dev_id;
int ret = -1;
- char *token, *l_params;
+ char *token, *l_params, *saveptr = NULL;
- if (params == NULL || strlen(params) == 0 || !isdigit(*params))
+ if (params == NULL || strlen(params) == 0 || !isdigit((unsigned char)*params))
return -1;
/* Get Rx adapter ID from parameter string */
l_params = strdup(params);
if (l_params == NULL)
return -ENOMEM;
- token = strtok(l_params, ",");
+ token = strtok_r(l_params, ",", &saveptr);
RTE_EVENT_ETH_RX_ADAPTER_TOKEN_VALID_OR_GOTO_ERR_RET(token, -1);
rx_adapter_id = strtoul(token, NULL, 10);
RTE_EVENT_ETH_RX_ADAPTER_ID_VALID_OR_GOTO_ERR_RET(rx_adapter_id, -EINVAL);
- token = strtok(NULL, ",");
+ token = strtok_r(NULL, ",", &saveptr);
RTE_EVENT_ETH_RX_ADAPTER_TOKEN_VALID_OR_GOTO_ERR_RET(token, -1);
/* Get device ID from parameter string */
eth_dev_id = strtoul(token, NULL, 10);
RTE_EVENT_ETH_RX_ADAPTER_PORTID_VALID_OR_GOTO_ERR_RET(eth_dev_id, -EINVAL);
- token = strtok(NULL, ",");
+ token = strtok_r(NULL, ",", &saveptr);
RTE_EVENT_ETH_RX_ADAPTER_TOKEN_VALID_OR_GOTO_ERR_RET(token, -1);
/* Get Rx queue ID from parameter string */
@@ -4006,7 +4006,7 @@ handle_rxa_queue_stats_reset(const char *cmd __rte_unused,
goto error;
}
- token = strtok(NULL, "\0");
+ token = strtok_r(NULL, "\0", &saveptr);
if (token != NULL)
RTE_EDEV_LOG_ERR("Extra parameters passed to eventdev"
" telemetry command, ignoring");
@@ -4036,22 +4036,22 @@ handle_rxa_instance_get(const char *cmd __rte_unused,
uint16_t rx_queue_id;
uint16_t eth_dev_id;
int ret = -1;
- char *token, *l_params;
+ char *token, *l_params, *saveptr = NULL;
- if (params == NULL || strlen(params) == 0 || !isdigit(*params))
+ if (params == NULL || strlen(params) == 0 || !isdigit((unsigned char)*params))
return -1;
l_params = strdup(params);
if (l_params == NULL)
return -ENOMEM;
- token = strtok(l_params, ",");
+ token = strtok_r(l_params, ",", &saveptr);
RTE_EVENT_ETH_RX_ADAPTER_TOKEN_VALID_OR_GOTO_ERR_RET(token, -1);
/* Get device ID from parameter string */
eth_dev_id = strtoul(token, NULL, 10);
RTE_EVENT_ETH_RX_ADAPTER_PORTID_VALID_OR_GOTO_ERR_RET(eth_dev_id, -EINVAL);
- token = strtok(NULL, ",");
+ token = strtok_r(NULL, ",", &saveptr);
RTE_EVENT_ETH_RX_ADAPTER_TOKEN_VALID_OR_GOTO_ERR_RET(token, -1);
/* Get Rx queue ID from parameter string */
@@ -4062,7 +4062,7 @@ handle_rxa_instance_get(const char *cmd __rte_unused,
goto error;
}
- token = strtok(NULL, "\0");
+ token = strtok_r(NULL, "\0", &saveptr);
if (token != NULL)
RTE_EDEV_LOG_ERR("Extra parameters passed to eventdev"
" telemetry command, ignoring");
--
2.53.0
next prev parent reply other threads:[~2026-06-05 20:53 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-05 20:50 [PATCH 0/8] telemetry: thread-safe and bounded parameter parsing Stephen Hemminger
2026-06-05 20:50 ` [PATCH 1/8] telemetry: fix thread-unsafe command parsing Stephen Hemminger
2026-06-05 20:50 ` [PATCH 2/8] ethdev: make telemetry parameter parsing thread-safe Stephen Hemminger
2026-06-05 20:51 ` [PATCH 3/8] dmadev: validate telemetry parameters Stephen Hemminger
2026-06-05 20:51 ` [PATCH 4/8] security: harden telemetry parameter parsing Stephen Hemminger
2026-06-05 20:51 ` [PATCH 5/8] eventdev: remove strtok from telemetry handlers Stephen Hemminger
2026-06-05 20:51 ` Stephen Hemminger [this message]
2026-06-05 20:51 ` [PATCH 7/8] eventdev/eth_rx: reject out-of-range telemetry adapter ID Stephen Hemminger
2026-06-05 20:51 ` [PATCH 8/8] eventdev/timer: reject out-of-range ID Stephen Hemminger
2026-06-06 6:08 ` [PATCH 0/8] telemetry: thread-safe and bounded parameter parsing Stephen Hemminger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260605205253.520196-7-stephen@networkplumber.org \
--to=stephen@networkplumber.org \
--cc=dev@dpdk.org \
--cc=ganapati.kundapura@intel.com \
--cc=jay.jayatheerthan@intel.com \
--cc=jerinj@marvell.com \
--cc=s.v.naga.harish.k@intel.com \
--cc=stable@dpdk.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox