[PATCH 6/8] eventdev/eth_rx: fix thread-unsafe telemetry parsing
Stephen Hemminger
stephen at networkplumber.org
Fri Jun 5 22:51:03 CEST 2026
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 at dpdk.org
Signed-off-by: Stephen Hemminger <stephen at 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
More information about the dev
mailing list