[PATCH 2/2] common/cnxk: fix thread-unsafe NIX telemetry parsing
Stephen Hemminger
stephen at networkplumber.org
Sat Jun 6 00:44:40 CEST 2026
cnxk_nix_tel_handle_info_x() backs the /cnxk/nix/{rq,cq,sq}/{info,ctx}
telemetry commands and parsed its "<pcidev>,<queue_id>" parameter with
strtok(), which keeps non-reentrant state and races when telemetry
callbacks run on per-connection threads.
Split the parameter with strchr() and parse the queue id with strtoul().
While here, copy the full parameter (the length was capped at
PCI_PRI_STR_SIZE + 1, truncating the id for longer device addresses) and
reject non-numeric or out-of-range ids instead of letting strtol() alias
them to queue 0.
Fixes: af75aac78978 ("common/cnxk: support telemetry for NIX")
Cc: stable at dpdk.org
Signed-off-by: Stephen Hemminger <stephen at networkplumber.org>
---
drivers/common/cnxk/cnxk_telemetry_nix.c | 80 +++++++++---------------
1 file changed, 30 insertions(+), 50 deletions(-)
diff --git a/drivers/common/cnxk/cnxk_telemetry_nix.c b/drivers/common/cnxk/cnxk_telemetry_nix.c
index abeefafe1e..82a146c139 100644
--- a/drivers/common/cnxk/cnxk_telemetry_nix.c
+++ b/drivers/common/cnxk/cnxk_telemetry_nix.c
@@ -1015,76 +1015,56 @@ cnxk_nix_tel_handle_info_x(const char *cmd, const char *params,
struct plt_tel_data *d)
{
struct nix_tel_node *node;
- char *name, *param;
char buf[1024];
+ char *comma, *end;
+ unsigned long qid;
int rc = -1;
- if (params == NULL || strlen(params) == 0 || !isdigit(*params))
- goto exit;
+ if (params == NULL || !isdigit((unsigned char)params[0]))
+ return -1;
- plt_strlcpy(buf, params, PCI_PRI_STR_SIZE + 1);
- name = strtok(buf, ",");
- if (name == NULL)
- goto exit;
+ plt_strlcpy(buf, params, sizeof(buf)); /* was PCI_PRI_STR_SIZE + 1 */
- param = strtok(NULL, "\0");
+ /* params is "<pcidev_name>,<queue_id>" */
+ comma = strchr(buf, ',');
+ if (comma == NULL || !isdigit((unsigned char)comma[1]))
+ return -1;
+ *comma = '\0';
- node = nix_tel_node_get_by_pcidev_name(name);
- if (!node)
- goto exit;
+ errno = 0;
+ qid = strtoul(comma + 1, &end, 10);
+ if (errno != 0 || (*end != '\0' && *end != ','))
+ return -1;
+
+ node = nix_tel_node_get_by_pcidev_name(buf);
+ if (node == NULL)
+ return -1;
plt_tel_data_start_dict(d);
if (strstr(cmd, "rq")) {
- char *tok = strtok(param, ",");
- int rq;
-
- if (!tok)
- goto exit;
-
- rq = strtol(tok, NULL, 10);
- if ((node->n_rq <= rq) || (rq < 0))
- goto exit;
-
+ if (qid >= node->n_rq)
+ return -1;
if (strstr(cmd, "ctx"))
- rc = cnxk_tel_nix_rq_ctx(node->nix, rq, d);
+ rc = cnxk_tel_nix_rq_ctx(node->nix, qid, d);
else
- rc = cnxk_tel_nix_rq(node->rqs[rq], d);
-
+ rc = cnxk_tel_nix_rq(node->rqs[qid], d);
} else if (strstr(cmd, "cq")) {
- char *tok = strtok(param, ",");
- int cq;
-
- if (!tok)
- goto exit;
-
- cq = strtol(tok, NULL, 10);
- if ((node->n_cq <= cq) || (cq < 0))
- goto exit;
-
+ if (qid >= node->n_cq)
+ return -1;
if (strstr(cmd, "ctx"))
- rc = cnxk_tel_nix_cq_ctx(node->nix, cq, d);
+ rc = cnxk_tel_nix_cq_ctx(node->nix, qid, d);
else
- rc = cnxk_tel_nix_cq(node->cqs[cq], d);
-
+ rc = cnxk_tel_nix_cq(node->cqs[qid], d);
} else if (strstr(cmd, "sq")) {
- char *tok = strtok(param, ",");
- int sq;
-
- if (!tok)
- goto exit;
-
- sq = strtol(tok, NULL, 10);
- if ((node->n_sq <= sq) || (sq < 0))
- goto exit;
-
+ if (qid >= node->n_sq)
+ return -1;
if (strstr(cmd, "ctx"))
- rc = cnxk_tel_nix_sq_ctx(node->nix, sq, d);
+ rc = cnxk_tel_nix_sq_ctx(node->nix, qid, d);
else
- rc = cnxk_tel_nix_sq(node->sqs[sq], d);
+ rc = cnxk_tel_nix_sq(node->sqs[qid], d);
}
-exit:
return rc;
}
--
2.53.0
More information about the dev
mailing list