All of lore.kernel.org
 help / color / mirror / Atom feed
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


  parent reply	other threads:[~2026-06-05 20:53 UTC|newest]

Thread overview: 16+ 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-08  1:25   ` fengchengwen
2026-06-08  7:49   ` Bruce Richardson
2026-06-05 20:50 ` [PATCH 2/8] ethdev: make telemetry parameter parsing thread-safe Stephen Hemminger
2026-06-08  1:26   ` fengchengwen
2026-06-05 20:51 ` [PATCH 3/8] dmadev: validate telemetry parameters Stephen Hemminger
2026-06-08  1:20   ` fengchengwen
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
2026-06-08  7:55 ` Bruce Richardson
2026-06-10 20:42   ` Thomas Monjalon

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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.