[PATCH v13 01/17] lpm: reject names that exceed maximum length

Stephen Hemminger
2026-01-27T16:33:12Z

Previously, rte_lpm_create() would silently truncate names longer than
RTE_LPM_NAMESIZE via snprintf(). This could lead to unexpected behavior
such as name collisions or failed lookups when the caller assumes the
full name was used.

Add an explicit length check that returns ENAMETOOLONG when the name
is too long, allowing the caller to handle the error appropriately.

Also fix the mem_name buffer size to account for the "LPM_" prefix,
add a truncation warning for the RCU defer queue name, and improve
the defer queue creation error message to include the actual error.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
doc/guides/rel_notes/release_26_03.rst | 7 +++++++
lib/lpm/rte_lpm.c | 17 +++++++++++++----
lib/lpm/rte_lpm.h | 1 +
3 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/doc/guides/rel_notes/release_26_03.rst b/doc/guides/rel_notes/release_26_03.rst
index 15dabee7a1..13f753abe8 100644
--- a/doc/guides/rel_notes/release_26_03.rst
+++ b/doc/guides/rel_notes/release_26_03.rst
@@ -84,6 +84,13 @@ API Changes
Also, make sure to start the actual text at the margin.
=======================================================

+* **Added additional length checks for name parameter lengths.**
+
+ Several library functions now have additional name length checks
+ instead of silently truncating.
+
+ * lpm: name must be less than RTE_LPM_NAMESIZE.
+

ABI Changes
-----------
diff --git a/lib/lpm/rte_lpm.c b/lib/lpm/rte_lpm.c
index 6dab86a05e..0ae8479481 100644
--- a/lib/lpm/rte_lpm.c
+++ b/lib/lpm/rte_lpm.c
@@ -152,7 +152,7 @@ struct rte_lpm *
rte_lpm_create(const char *name, int socket_id,
const struct rte_lpm_config *config)
{
- char mem_name[RTE_LPM_NAMESIZE];
+ char mem_name[RTE_LPM_NAMESIZE + sizeof("LPM_")];
struct __rte_lpm *i_lpm;
struct rte_lpm *lpm = NULL;
struct rte_tailq_entry *te;
@@ -170,6 +170,11 @@ rte_lpm_create(const char *name, int socket_id,
return NULL;
}

+ if (strlen(name) >= RTE_LPM_NAMESIZE) {
+ rte_errno = ENAMETOOLONG;
+ return NULL;
+ }
+
snprintf(mem_name, sizeof(mem_name), "LPM_%s", name);

rte_mcfg_tailq_write_lock();
@@ -327,8 +332,11 @@ rte_lpm_rcu_qsbr_add(struct rte_lpm *lpm, struct rte_lpm_rcu_config *cfg)
/* No other things to do. */
} else if (cfg->mode == RTE_LPM_QSBR_MODE_DQ) {
/* Init QSBR defer queue. */
- snprintf(rcu_dq_name, sizeof(rcu_dq_name),
- "LPM_RCU_%s", i_lpm->name);
+ if (snprintf(rcu_dq_name, sizeof(rcu_dq_name), "LPM_RCU_%s", i_lpm->name)
+ >= (int)sizeof(rcu_dq_name))
+ LPM_LOG(NOTICE, "LPM rcu defer queue name truncated to '%s'",
+ rcu_dq_name);
+
params.name = rcu_dq_name;
params.size = cfg->dq_size;
if (params.size == 0)
@@ -343,7 +351,8 @@ rte_lpm_rcu_qsbr_add(struct rte_lpm *lpm, struct rte_lpm_rcu_config *cfg)
params.v = cfg->v;
i_lpm->dq = rte_rcu_qsbr_dq_create(&params);
if (i_lpm->dq == NULL) {
- LPM_LOG(ERR, "LPM defer queue creation failed");
+ LPM_LOG(ERR, "LPM defer queue creation failed: %s",
+ rte_strerror(rte_errno));
return 1;
}
} else {
diff --git a/lib/lpm/rte_lpm.h b/lib/lpm/rte_lpm.h
index edfe77b458..38a061513f 100644
--- a/lib/lpm/rte_lpm.h
+++ b/lib/lpm/rte_lpm.h
@@ -180,6 +180,7 @@ rte_lpm_free(struct rte_lpm *lpm);
* - ENOSPC - the maximum number of memzones has already been allocated
* - EEXIST - a memzone with the same name already exists
* - ENOMEM - no appropriate memory area found in which to create memzone
+ * - ENAMETOOLONG - LPM object name greater than RTE_LPM_NAMESIZE
*/
struct rte_lpm *
rte_lpm_create(const char *name, int socket_id,
--
2.51.0