DPDK patches and discussions
 help / color / mirror / Atom feed
* [RFC 0/8] first steps in fixing buffer overflow
@ 2025-12-02 17:24 Stephen Hemminger
  2025-12-02 17:24 ` [RFC 1/8] eal: use C library to parse filesystem table Stephen Hemminger
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Stephen Hemminger @ 2025-12-02 17:24 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

This is preliminary work to fix the format overflow issues
in EAL and related libraries. The biggest problem area
still needing work is all the cases where the created
path for <runtime_dir>/XXX could overflow the maximum limit
which is only 108 characters due to Unix Domain socket
restrictions.

Stephen Hemminger (8):
  eal: use C library to parse filesystem table
  hash: fix possible ring name overflow
  eal: warn if thread name is truncated
  eal: avoid format overflow when handling addresses
  ethdev: avoid possible overflow in xstat names
  efd: avoid overflowing ring name
  eal: add check for sysfs path overflow
  eal: limit maximum runtime directory and socket paths

 lib/eal/common/eal_common_config.c |  6 ++-
 lib/eal/common/eal_common_memory.c |  2 +-
 lib/eal/common/eal_common_proc.c   | 18 ++++-----
 lib/eal/common/eal_filesystem.h    |  6 ++-
 lib/eal/linux/eal.c                |  6 ++-
 lib/eal/linux/eal_hugepage_info.c  | 64 +++++++++++-------------------
 lib/efd/rte_efd.c                  | 20 +++++++++-
 lib/ethdev/rte_ethdev.c            | 27 +++++++++----
 lib/hash/rte_cuckoo_hash.c         | 33 +++++++++++----
 9 files changed, 110 insertions(+), 72 deletions(-)

-- 
2.51.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC 1/8] eal: use C library to parse filesystem table
  2025-12-02 17:24 [RFC 0/8] first steps in fixing buffer overflow Stephen Hemminger
@ 2025-12-02 17:24 ` Stephen Hemminger
  2025-12-02 17:24 ` [RFC 2/8] hash: fix possible ring name overflow Stephen Hemminger
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2025-12-02 17:24 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Bruce Richardson

Rather than doing parsing of /proc/mounts with open coded string
handling, use the standard C library routines.
These exist in BSD and Linux.

It also avoids any possible issues with escaped strings etc
which the library handles. See getmntent(3) man page.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
---
 lib/eal/linux/eal_hugepage_info.c | 58 ++++++++++---------------------
 1 file changed, 18 insertions(+), 40 deletions(-)

diff --git a/lib/eal/linux/eal_hugepage_info.c b/lib/eal/linux/eal_hugepage_info.c
index d47a19c56a..7161b1a2fb 100644
--- a/lib/eal/linux/eal_hugepage_info.c
+++ b/lib/eal/linux/eal_hugepage_info.c
@@ -13,6 +13,7 @@
 #include <inttypes.h>
 #include <unistd.h>
 #include <errno.h>
+#include <mntent.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 
@@ -195,23 +196,13 @@ get_default_hp_size(void)
 static int
 get_hugepage_dir(uint64_t hugepage_sz, char *hugedir, int len)
 {
-	enum proc_mount_fieldnames {
-		DEVICE = 0,
-		MOUNTPT,
-		FSTYPE,
-		OPTIONS,
-		_FIELDNAME_MAX
-	};
 	static uint64_t default_size = 0;
 	const char proc_mounts[] = "/proc/mounts";
-	const char hugetlbfs_str[] = "hugetlbfs";
-	const size_t htlbfs_str_len = sizeof(hugetlbfs_str) - 1;
 	const char pagesize_opt[] = "pagesize=";
 	const size_t pagesize_opt_len = sizeof(pagesize_opt) - 1;
-	const char split_tok = ' ';
-	char *splitstr[_FIELDNAME_MAX];
 	char found[PATH_MAX] = "";
 	char buf[BUFSIZ];
+	struct mntent entry;
 	const struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 	const size_t hugepage_dir_len = (internal_conf->hugepage_dir != NULL) ?
@@ -226,56 +217,43 @@ get_hugepage_dir(uint64_t hugepage_sz, char *hugedir, int len)
 		return -1;
 	}
 
-	FILE *fd = fopen(proc_mounts, "r");
-	if (fd == NULL)
+	FILE *mounts = setmntent(proc_mounts, "r");
+	if (mounts == NULL)
 		rte_panic("Cannot open %s\n", proc_mounts);
 
 	if (default_size == 0)
 		default_size = get_default_hp_size();
 
-	while (fgets(buf, sizeof(buf), fd)){
+	while (getmntent_r(mounts, &entry, buf, sizeof(buf))) {
 		const char *pagesz_str;
-		size_t mountpt_len = 0;
-
-		if (rte_strsplit(buf, sizeof(buf), splitstr, _FIELDNAME_MAX,
-				split_tok) != _FIELDNAME_MAX) {
-			EAL_LOG(ERR, "Error parsing %s", proc_mounts);
-			break; /* return NULL */
-		}
+		uint64_t pagesz = default_size;
+		size_t mountpt_len;
 
-		if (strncmp(splitstr[FSTYPE], hugetlbfs_str, htlbfs_str_len) != 0)
+		if (strcmp(entry.mnt_type, "hugetlbfs") != 0)
 			continue;
 
-		pagesz_str = strstr(splitstr[OPTIONS], pagesize_opt);
+		pagesz_str = strstr(entry.mnt_opts, pagesize_opt);
+		if (pagesz_str)
+			pagesz = rte_str_to_size(&pagesz_str[pagesize_opt_len]);
 
-		/* if no explicit page size, the default page size is compared */
-		if (pagesz_str == NULL) {
-			if (hugepage_sz != default_size)
-				continue;
-		}
-		/* there is an explicit page size, so check it */
-		else {
-			uint64_t pagesz = rte_str_to_size(&pagesz_str[pagesize_opt_len]);
-			if (pagesz != hugepage_sz)
-				continue;
-		}
+		if (pagesz != hugepage_sz)
+			continue;
 
 		/*
 		 * If no --huge-dir option has been given, we're done.
 		 */
 		if (internal_conf->hugepage_dir == NULL) {
-			strlcpy(found, splitstr[MOUNTPT], len);
+			strlcpy(found, entry.mnt_dir, len);
 			break;
 		}
 
-		mountpt_len = strlen(splitstr[MOUNTPT]);
+		mountpt_len = strlen(entry.mnt_dir);
 
 		/*
 		 * Ignore any mount that doesn't contain the --huge-dir directory
 		 * or where mount point is not a parent path of --huge-dir
 		 */
-		if (strncmp(internal_conf->hugepage_dir, splitstr[MOUNTPT],
-				mountpt_len) != 0 ||
+		if (strncmp(internal_conf->hugepage_dir, entry.mnt_dir, mountpt_len) != 0 ||
 			(hugepage_dir_len > mountpt_len &&
 				internal_conf->hugepage_dir[mountpt_len] != '/')) {
 			continue;
@@ -286,10 +264,10 @@ get_hugepage_dir(uint64_t hugepage_sz, char *hugedir, int len)
 		 * (so /mnt/1 is preferred over /mnt for matching /mnt/1/2)).
 		 */
 		if (mountpt_len > strlen(found))
-			strlcpy(found, splitstr[MOUNTPT], len);
+			strlcpy(found, entry.mnt_dir, len);
 	} /* end while fgets */
 
-	fclose(fd);
+	endmntent(mounts);
 
 	if (found[0] != '\0') {
 		/* If needed, return the requested dir, not the mount point. */
-- 
2.51.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC 2/8] hash: fix possible ring name overflow
  2025-12-02 17:24 [RFC 0/8] first steps in fixing buffer overflow Stephen Hemminger
  2025-12-02 17:24 ` [RFC 1/8] eal: use C library to parse filesystem table Stephen Hemminger
@ 2025-12-02 17:24 ` Stephen Hemminger
  2025-12-02 17:24 ` [RFC 3/8] eal: warn if thread name is truncated Stephen Hemminger
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2025-12-02 17:24 UTC (permalink / raw)
  To: dev
  Cc: Stephen Hemminger, Yipeng Wang, Sameh Gobriel, Bruce Richardson,
	Vladimir Medvedkin

The maximum possible hash parameter name will cause the generated
ring names to overlow in snprintf(). Potentially causing conflicting
ring names and trouble.

For reference:
   RTE_MEMPOOL_NAMESIZE = 32
   RTE_RING_NAMESIZE  =  29
   RTE_HASH_NAMESIZE = 32
The hash name is concatenated with a prefix like "HT_RCU_"
the hash name string needs to be enforced as having space
for the resulting string (ie 22).

Since the NAMESIZE's are part of ABI they can't change.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/hash/rte_cuckoo_hash.c | 33 ++++++++++++++++++++++++++-------
 1 file changed, 26 insertions(+), 7 deletions(-)

diff --git a/lib/hash/rte_cuckoo_hash.c b/lib/hash/rte_cuckoo_hash.c
index 2c92c51624..3a521a1a1e 100644
--- a/lib/hash/rte_cuckoo_hash.c
+++ b/lib/hash/rte_cuckoo_hash.c
@@ -77,6 +77,11 @@ struct __rte_hash_rcu_dq_entry {
 	uint32_t ext_bkt_idx;
 };
 
+#define HASH_QSBR_PREFIX	"HT_RCU_"
+#define HASH_EXT_PREFIX		"HT_EXT_"
+#define HASH_RING_PREFIX	"HT_"
+
+
 RTE_EXPORT_SYMBOL(rte_hash_find_existing)
 struct rte_hash *
 rte_hash_find_existing(const char *name)
@@ -231,6 +236,20 @@ rte_hash_create(const struct rte_hash_parameters *params)
 		return NULL;
 	}
 
+	/*
+	 * The API for hash allows 32 characters but maximimu length
+	 * would overflow ring name which is limited to 29 characters (RTE_RING_NAMESIZE).
+	 * To avoid breaking ABI, enforce limit of 25 characters on
+	 * the hash table name.
+	 */
+	if (strnlen(params->name, RTE_HASH_NAMESIZE)
+	    > RTE_RING_NAMESIZE - sizeof(HASH_QSBR_PREFIX)) {
+		rte_errno = EINVAL;
+		HASH_LOG(ERR, "%s: hash name too long to fit in qsbr ring name",
+			 __func__);
+		return NULL;
+	}
+
 	/* Check extra flags field to check extra options. */
 	if (params->extra_flag & RTE_HASH_EXTRA_FLAGS_TRANS_MEM_SUPPORT)
 		hw_trans_mem_support = 1;
@@ -272,7 +291,7 @@ rte_hash_create(const struct rte_hash_parameters *params)
 	else
 		num_key_slots = params->entries + 1;
 
-	snprintf(ring_name, sizeof(ring_name), "HT_%s", params->name);
+	snprintf(ring_name, sizeof(ring_name), HASH_RING_PREFIX "%s", params->name);
 	/* Create ring (Dummy slot index is not enqueued) */
 	r = rte_ring_create_elem(ring_name, sizeof(uint32_t),
 			rte_align32pow2(num_key_slots), params->socket_id, 0);
@@ -286,8 +305,8 @@ rte_hash_create(const struct rte_hash_parameters *params)
 
 	/* Create ring for extendable buckets. */
 	if (ext_table_support) {
-		snprintf(ext_ring_name, sizeof(ext_ring_name), "HT_EXT_%s",
-								params->name);
+		snprintf(ext_ring_name, sizeof(ext_ring_name),
+			 HASH_EXT_PREFIX "%s", params->name);
 		r_ext = rte_ring_create_elem(ext_ring_name, sizeof(uint32_t),
 				rte_align32pow2(num_buckets + 1),
 				params->socket_id, 0);
@@ -299,7 +318,7 @@ rte_hash_create(const struct rte_hash_parameters *params)
 		}
 	}
 
-	snprintf(hash_name, sizeof(hash_name), "HT_%s", params->name);
+	snprintf(hash_name, sizeof(hash_name), HASH_RING_PREFIX "%s", params->name);
 
 	rte_mcfg_tailq_write_lock();
 
@@ -1582,7 +1601,8 @@ rte_hash_rcu_qsbr_add(struct rte_hash *h, struct rte_hash_rcu_config *cfg)
 	char rcu_dq_name[RTE_RCU_QSBR_DQ_NAMESIZE];
 	struct rte_hash_rcu_config *hash_rcu_cfg = NULL;
 
-	if (h == NULL || cfg == NULL || cfg->v == NULL) {
+	if (h == NULL || cfg == NULL || cfg->v == NULL ||
+	    strlen(h->name) > RTE_RCU_QSBR_DQ_NAMESIZE - sizeof(HASH_QSBR_PREFIX)) {
 		rte_errno = EINVAL;
 		return 1;
 	}
@@ -1606,8 +1626,7 @@ rte_hash_rcu_qsbr_add(struct rte_hash *h, struct rte_hash_rcu_config *cfg)
 		/* No other things to do. */
 	} else if (cfg->mode == RTE_HASH_QSBR_MODE_DQ) {
 		/* Init QSBR defer queue. */
-		snprintf(rcu_dq_name, sizeof(rcu_dq_name),
-					"HASH_RCU_%s", h->name);
+		snprintf(rcu_dq_name, sizeof(rcu_dq_name), HASH_QSBR_PREFIX "%s", h->name);
 		params.name = rcu_dq_name;
 		params.size = cfg->dq_size;
 		if (params.size == 0)
-- 
2.51.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC 3/8] eal: warn if thread name is truncated
  2025-12-02 17:24 [RFC 0/8] first steps in fixing buffer overflow Stephen Hemminger
  2025-12-02 17:24 ` [RFC 1/8] eal: use C library to parse filesystem table Stephen Hemminger
  2025-12-02 17:24 ` [RFC 2/8] hash: fix possible ring name overflow Stephen Hemminger
@ 2025-12-02 17:24 ` Stephen Hemminger
  2025-12-02 17:24 ` [RFC 4/8] eal: avoid format overflow when handling addresses Stephen Hemminger
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2025-12-02 17:24 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

Thread name is very short 16 characters and therefore the name
dpdk-worker-%d will overflow with more than 9999 worker cores.
Error should be non-fatal since name only matters for debug.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/eal/linux/eal.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/lib/eal/linux/eal.c b/lib/eal/linux/eal.c
index b12f325ddd..d848de03d8 100644
--- a/lib/eal/linux/eal.c
+++ b/lib/eal/linux/eal.c
@@ -863,8 +863,10 @@ rte_eal_init(int argc, char **argv)
 			rte_panic("Cannot create thread\n");
 
 		/* Set thread_name for aid in debugging. */
-		snprintf(thread_name, sizeof(thread_name),
-			"dpdk-worker%d", i);
+		ret = snprintf(thread_name, sizeof(thread_name), "dpdk-worker%d", i);
+		if (ret >= RTE_THREAD_NAME_SIZE)
+			EAL_LOG(INFO, "Worker thread name %s truncated", thread_name);
+
 		rte_thread_set_name(lcore_config[i].thread_id, thread_name);
 
 		ret = rte_thread_set_affinity_by_id(lcore_config[i].thread_id,
-- 
2.51.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC 4/8] eal: avoid format overflow when handling addresses
  2025-12-02 17:24 [RFC 0/8] first steps in fixing buffer overflow Stephen Hemminger
                   ` (2 preceding siblings ...)
  2025-12-02 17:24 ` [RFC 3/8] eal: warn if thread name is truncated Stephen Hemminger
@ 2025-12-02 17:24 ` Stephen Hemminger
  2025-12-02 17:24 ` [RFC 5/8] ethdev: avoid possible overflow in xstat names Stephen Hemminger
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2025-12-02 17:24 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Anatoly Burakov

The largest possible string in this code 0xFFFFFFFFFFFFFFFF
which will overflow with only 15 character buffer.
Increase to 20.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/eal/common/eal_common_memory.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/eal/common/eal_common_memory.c b/lib/eal/common/eal_common_memory.c
index c62edf5e55..2633857db5 100644
--- a/lib/eal/common/eal_common_memory.c
+++ b/lib/eal/common/eal_common_memory.c
@@ -1153,7 +1153,7 @@ rte_eal_memory_init(void)
 #define EAL_MEMSEG_INFO_REQ		"/eal/memseg_info"
 #define EAL_ELEMENT_LIST_REQ		"/eal/mem_element_list"
 #define EAL_ELEMENT_INFO_REQ		"/eal/mem_element_info"
-#define ADDR_STR			15
+#define ADDR_STR			20	/* 16 bytes 64 bit + 0x */
 
 
 /* Telemetry callback handler to return heap stats for requested heap id. */
-- 
2.51.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC 5/8] ethdev: avoid possible overflow in xstat names
  2025-12-02 17:24 [RFC 0/8] first steps in fixing buffer overflow Stephen Hemminger
                   ` (3 preceding siblings ...)
  2025-12-02 17:24 ` [RFC 4/8] eal: avoid format overflow when handling addresses Stephen Hemminger
@ 2025-12-02 17:24 ` Stephen Hemminger
  2025-12-02 17:24 ` [RFC 6/8] efd: avoid overflowing ring name Stephen Hemminger
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2025-12-02 17:24 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Thomas Monjalon, Andrew Rybchenko

The compiler doesn't know that all the elements in the table
of queue stats are short enough to avoid overflowing the snprintf.
Add a condition that will not happen to warn if it ever does;
maybe some day a new long named queue stat could be added.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/ethdev/rte_ethdev.c | 27 +++++++++++++++++++--------
 1 file changed, 19 insertions(+), 8 deletions(-)

diff --git a/lib/ethdev/rte_ethdev.c b/lib/ethdev/rte_ethdev.c
index c6fe0d5165..5bd3fbc0bc 100644
--- a/lib/ethdev/rte_ethdev.c
+++ b/lib/ethdev/rte_ethdev.c
@@ -3501,10 +3501,16 @@ eth_basic_stats_get_names(struct rte_eth_dev *dev,
 	num_q = RTE_MIN(dev->data->nb_rx_queues, RTE_ETHDEV_QUEUE_STAT_CNTRS);
 	for (id_queue = 0; id_queue < num_q; id_queue++) {
 		for (idx = 0; idx < RTE_NB_RXQ_STATS; idx++) {
-			snprintf(xstats_names[cnt_used_entries].name,
-				sizeof(xstats_names[0].name),
-				"rx_q%u_%s",
-				id_queue, eth_dev_rxq_stats_strings[idx].name);
+			unsigned int cc;
+
+			cc = snprintf(xstats_names[cnt_used_entries].name, sizeof(xstats_names[0].name),
+				      "rx_q%u_%s",
+				      id_queue, eth_dev_rxq_stats_strings[idx].name);
+
+			/* could only happen if a long string was added to eth_dev_rxq_stats_strings */
+			if (cc >= sizeof(xstats_names[0].name))
+				RTE_ETHDEV_LOG_LINE(ERR, "truncated rxq stat string '%s'",
+						    eth_dev_rxq_stats_strings[idx].name);
 			cnt_used_entries++;
 		}
 
@@ -3512,10 +3518,15 @@ eth_basic_stats_get_names(struct rte_eth_dev *dev,
 	num_q = RTE_MIN(dev->data->nb_tx_queues, RTE_ETHDEV_QUEUE_STAT_CNTRS);
 	for (id_queue = 0; id_queue < num_q; id_queue++) {
 		for (idx = 0; idx < RTE_NB_TXQ_STATS; idx++) {
-			snprintf(xstats_names[cnt_used_entries].name,
-				sizeof(xstats_names[0].name),
-				"tx_q%u_%s",
-				id_queue, eth_dev_txq_stats_strings[idx].name);
+			unsigned int cc;
+
+			cc = snprintf(xstats_names[cnt_used_entries].name, sizeof(xstats_names[0].name),
+				      "tx_q%u_%s",
+				      id_queue, eth_dev_txq_stats_strings[idx].name);
+			/* could only happen if a long string was added to eth_dev_rxq_stats_strings */
+			if (cc >= sizeof(xstats_names[0].name))
+				RTE_ETHDEV_LOG_LINE(ERR, "truncated txq stat string '%s'",
+						    eth_dev_txq_stats_strings[idx].name);
 			cnt_used_entries++;
 		}
 	}
-- 
2.51.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC 6/8] efd: avoid overflowing ring name
  2025-12-02 17:24 [RFC 0/8] first steps in fixing buffer overflow Stephen Hemminger
                   ` (4 preceding siblings ...)
  2025-12-02 17:24 ` [RFC 5/8] ethdev: avoid possible overflow in xstat names Stephen Hemminger
@ 2025-12-02 17:24 ` Stephen Hemminger
  2025-12-02 17:24 ` [RFC 7/8] eal: add check for sysfs path overflow Stephen Hemminger
  2025-12-02 17:24 ` [RFC 8/8] eal: limit maximum runtime directory and socket paths Stephen Hemminger
  7 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2025-12-02 17:24 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Byron Marohn, Yipeng Wang

The efd library allowed table name to be longer than would be
safe when prefix was added for a ring name.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/efd/rte_efd.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/lib/efd/rte_efd.c b/lib/efd/rte_efd.c
index ebf1e0655f..61fd6a6646 100644
--- a/lib/efd/rte_efd.c
+++ b/lib/efd/rte_efd.c
@@ -36,6 +36,9 @@ RTE_LOG_REGISTER_DEFAULT(efd_logtype, INFO);
 #define EFD_LOG(level, ...) \
 	RTE_LOG_LINE(level, EFD, "" __VA_ARGS__)
 
+/** Prefix used on ring name for hash */
+#define EFD_HASH_PREFIX "HT_"
+
 #define EFD_KEY(key_idx, table) (table->keys + ((key_idx) * table->key_len))
 /** Hash function used to determine chunk_id and bin_id for a group */
 #define EFD_HASH(key, table) \
@@ -527,6 +530,15 @@ rte_efd_create(const char *name, uint32_t max_num_rules, uint32_t key_len,
 		return NULL;
 	}
 
+	/*
+	 * The name is turned into a ring name which has a limit of
+	 * RTE_RING_NAMESIZE.
+	 */
+	if (name == NULL || strnlen(name, RTE_RING_NAMESIZE) >= RTE_RING_NAMESIZE - sizeof(EFD_HASH_PREFIX)) {
+		EFD_LOG(ERR, "Invalid name '%s'", name);
+		return NULL;
+	}
+
 	/*
 	 * Compute the minimum number of chunks (smallest power of 2)
 	 * that can hold all of the rules
@@ -698,7 +710,13 @@ rte_efd_create(const char *name, uint32_t max_num_rules, uint32_t key_len,
 	TAILQ_INSERT_TAIL(efd_list, te, next);
 	rte_mcfg_tailq_write_unlock();
 
-	snprintf(ring_name, sizeof(ring_name), "HT_%s", table->name);
+	int cc = snprintf(ring_name, sizeof(ring_name),  EFD_HASH_PREFIX "%s", table->name);
+	if (cc >= sizeof(ring_name)) {
+		EFD_LOG(ERR, "ring name '%s%s' overflow", EFD_HASH_PREFIX, table->name);
+		rte_efd_free(table);
+		return NULL;
+	}
+
 	/* Create ring (Dummy slot index is not enqueued) */
 	r = rte_ring_create(ring_name, rte_align32pow2(table->max_num_rules),
 			offline_cpu_socket, 0);
-- 
2.51.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC 7/8] eal: add check for sysfs path overflow
  2025-12-02 17:24 [RFC 0/8] first steps in fixing buffer overflow Stephen Hemminger
                   ` (5 preceding siblings ...)
  2025-12-02 17:24 ` [RFC 6/8] efd: avoid overflowing ring name Stephen Hemminger
@ 2025-12-02 17:24 ` Stephen Hemminger
  2025-12-02 17:24 ` [RFC 8/8] eal: limit maximum runtime directory and socket paths Stephen Hemminger
  7 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2025-12-02 17:24 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

It shouldn't happen but in theory sysfs socket could overflow.
Add a check for it.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/eal/linux/eal_hugepage_info.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/lib/eal/linux/eal_hugepage_info.c b/lib/eal/linux/eal_hugepage_info.c
index 7161b1a2fb..fe3351259e 100644
--- a/lib/eal/linux/eal_hugepage_info.c
+++ b/lib/eal/linux/eal_hugepage_info.c
@@ -150,8 +150,12 @@ get_num_hugepages_on_node(const char *subdir, unsigned int socket, size_t sz)
 		return 0;
 	}
 
-	snprintf(path, sizeof(path), "%s/%s/%s",
+	if (snprintf(path, sizeof(path), "%s/%s/%s", socketpath, subdir, nr_hp_file) >= PATH_MAX) {
+		EAL_LOG(NOTICE, "Socket path %s/%s/%s is truncated",
 			socketpath, subdir, nr_hp_file);
+		return 0;
+	}
+
 	if (eal_parse_sysfs_value(path, &num_pages) < 0)
 		return 0;
 
-- 
2.51.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC 8/8] eal: limit maximum runtime directory and socket paths
  2025-12-02 17:24 [RFC 0/8] first steps in fixing buffer overflow Stephen Hemminger
                   ` (6 preceding siblings ...)
  2025-12-02 17:24 ` [RFC 7/8] eal: add check for sysfs path overflow Stephen Hemminger
@ 2025-12-02 17:24 ` Stephen Hemminger
  7 siblings, 0 replies; 9+ messages in thread
From: Stephen Hemminger @ 2025-12-02 17:24 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Anatoly Burakov

Linux (and FreeBSD) has a limitation of 108 characters for
any unix domain socket path. Therefore DPDK would not work
if a really large runtime directory was used.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/eal/common/eal_common_config.c |  6 ++++--
 lib/eal/common/eal_common_proc.c   | 18 +++++++++---------
 lib/eal/common/eal_filesystem.h    |  6 +++++-
 3 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/lib/eal/common/eal_common_config.c b/lib/eal/common/eal_common_config.c
index 7fc7611a07..e2e69a75fb 100644
--- a/lib/eal/common/eal_common_config.c
+++ b/lib/eal/common/eal_common_config.c
@@ -6,6 +6,7 @@
 
 #include <eal_export.h>
 #include "eal_private.h"
+#include "eal_filesystem.h"
 #include "eal_memcfg.h"
 
 /* early configuration structure, when memory config is not mmapped */
@@ -24,7 +25,7 @@ static struct rte_config rte_config = {
 };
 
 /* platform-specific runtime dir */
-static char runtime_dir[PATH_MAX];
+static char runtime_dir[UNIX_PATH_MAX];
 
 /* internal configuration */
 static struct internal_config internal_config;
@@ -39,7 +40,8 @@ rte_eal_get_runtime_dir(void)
 int
 eal_set_runtime_dir(const char *run_dir)
 {
-	if (strlcpy(runtime_dir, run_dir, PATH_MAX) >= PATH_MAX) {
+	/* runtime directory limited by maximum allowable unix domain socket */
+	if (strlcpy(runtime_dir, run_dir, UNIX_PATH_MAX) >= UNIX_PATH_MAX) {
 		EAL_LOG(ERR, "Runtime directory string too long");
 		return -1;
 	}
diff --git a/lib/eal/common/eal_common_proc.c b/lib/eal/common/eal_common_proc.c
index 62fd4ba88f..3c4a1850ff 100644
--- a/lib/eal/common/eal_common_proc.c
+++ b/lib/eal/common/eal_common_proc.c
@@ -36,10 +36,10 @@
 
 static RTE_ATOMIC(int) mp_fd = -1;
 static rte_thread_t mp_handle_tid;
-static char mp_filter[PATH_MAX];   /* Filter for secondary process sockets */
-static char mp_dir_path[PATH_MAX]; /* The directory path for all mp sockets */
+static char mp_filter[UNIX_PATH_MAX];   /* Filter for secondary process sockets */
+static char mp_dir_path[UNIX_PATH_MAX]; /* The directory path for all mp sockets */
 static pthread_mutex_t mp_mutex_action = PTHREAD_MUTEX_INITIALIZER;
-static char peer_name[PATH_MAX];
+static char peer_name[UNIX_PATH_MAX];
 
 struct action_entry {
 	TAILQ_ENTRY(action_entry) next;
@@ -78,7 +78,7 @@ struct pending_request {
 		REQUEST_TYPE_SYNC,
 		REQUEST_TYPE_ASYNC
 	} type;
-	char dst[PATH_MAX];
+	char dst[UNIX_PATH_MAX];
 	struct rte_mp_msg *request;
 	struct rte_mp_msg *reply;
 	int reply_received;
@@ -599,7 +599,7 @@ open_socket_fd(void)
 static void
 close_socket_fd(int fd)
 {
-	char path[PATH_MAX];
+	char path[UNIX_PATH_MAX];
 
 	close(fd);
 	create_socket_path(peer_name, path, sizeof(path));
@@ -609,7 +609,7 @@ close_socket_fd(int fd)
 int
 rte_mp_channel_init(void)
 {
-	char path[PATH_MAX];
+	char path[UNIX_PATH_MAX];
 	int dir_fd;
 	const struct internal_config *internal_conf =
 		eal_get_internal_configuration();
@@ -779,7 +779,7 @@ mp_send(struct rte_mp_msg *msg, const char *peer, int type)
 	}
 
 	while ((ent = readdir(mp_dir))) {
-		char path[PATH_MAX];
+		char path[UNIX_PATH_MAX];
 
 		if (fnmatch(mp_filter, ent->d_name, 0) != 0)
 			continue;
@@ -1055,7 +1055,7 @@ rte_mp_request_sync(struct rte_mp_msg *req, struct rte_mp_reply *reply,
 
 	pthread_mutex_lock(&pending_requests.lock);
 	while ((ent = readdir(mp_dir))) {
-		char path[PATH_MAX];
+		char path[UNIX_PATH_MAX];
 
 		if (fnmatch(mp_filter, ent->d_name, 0) != 0)
 			continue;
@@ -1200,7 +1200,7 @@ rte_mp_request_async(struct rte_mp_msg *req, const struct timespec *ts,
 	}
 
 	while ((ent = readdir(mp_dir))) {
-		char path[PATH_MAX];
+		char path[UNIX_PATH_MAX];
 
 		if (fnmatch(mp_filter, ent->d_name, 0) != 0)
 			continue;
diff --git a/lib/eal/common/eal_filesystem.h b/lib/eal/common/eal_filesystem.h
index 5d21f07c20..5371d9f1d6 100644
--- a/lib/eal/common/eal_filesystem.h
+++ b/lib/eal/common/eal_filesystem.h
@@ -45,10 +45,14 @@ eal_runtime_config_path(void)
 
 /** Path of primary/secondary communication unix socket file. */
 #define MP_SOCKET_FNAME "mp_socket"
+
+/** Maximum length of unix domain socket path as defined in sys/un.h */
+#define UNIX_PATH_MAX 108
+
 static inline const char *
 eal_mp_socket_path(void)
 {
-	static char buffer[PATH_MAX]; /* static so auto-zeroed */
+	static char buffer[UNIX_PATH_MAX]; /* static so auto-zeroed */
 
 	snprintf(buffer, sizeof(buffer), "%s/%s", rte_eal_get_runtime_dir(),
 			MP_SOCKET_FNAME);
-- 
2.51.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2025-12-02 17:27 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-12-02 17:24 [RFC 0/8] first steps in fixing buffer overflow Stephen Hemminger
2025-12-02 17:24 ` [RFC 1/8] eal: use C library to parse filesystem table Stephen Hemminger
2025-12-02 17:24 ` [RFC 2/8] hash: fix possible ring name overflow Stephen Hemminger
2025-12-02 17:24 ` [RFC 3/8] eal: warn if thread name is truncated Stephen Hemminger
2025-12-02 17:24 ` [RFC 4/8] eal: avoid format overflow when handling addresses Stephen Hemminger
2025-12-02 17:24 ` [RFC 5/8] ethdev: avoid possible overflow in xstat names Stephen Hemminger
2025-12-02 17:24 ` [RFC 6/8] efd: avoid overflowing ring name Stephen Hemminger
2025-12-02 17:24 ` [RFC 7/8] eal: add check for sysfs path overflow Stephen Hemminger
2025-12-02 17:24 ` [RFC 8/8] eal: limit maximum runtime directory and socket paths Stephen Hemminger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).