patch 'cfgfile: prevent overflow on resize' has been queued to stable release 24.11.7
luca.boccassi at gmail.com
luca.boccassi at gmail.com
Thu Jun 11 15:19:13 CEST 2026
Hi,
FYI, your patch has been queued to stable release 24.11.7
Note it hasn't been pushed to http://dpdk.org/browse/dpdk-stable yet.
It will be pushed if I get no objections before 06/13/26. So please
shout if anyone has objections.
Also note that after the patch there's a diff of the upstream commit vs the
patch applied to the branch. This will indicate if there was any rebasing
needed to apply to the stable branch. If there were code changes for rebasing
(ie: not only metadata diffs), please double check that the rebase was
correctly done.
Queued patches are on a temporary branch at:
https://github.com/bluca/dpdk-stable
This queued commit can be viewed at:
https://github.com/bluca/dpdk-stable/commit/1c185b30c7b508646ea7e4529f3a16deb3538ebe
Thanks.
Luca Boccassi
---
>From 1c185b30c7b508646ea7e4529f3a16deb3538ebe Mon Sep 17 00:00:00 2001
From: Bruce Richardson <bruce.richardson at intel.com>
Date: Thu, 7 May 2026 15:59:45 +0100
Subject: [PATCH] cfgfile: prevent overflow on resize
[ upstream commit 458ed82bef455d76138a62ff15ab7c380fa637f4 ]
When resizing a cfgfile object to store more sections or entries, the
multiplication in the realloc call could lead to overflow and hence an
incorrect/smaller size being allocated. Prevent this by tightening up
sizing in the library:
- use size_t for sizes rather than int, avoiding negative values
- explicitly limit the number of entries to INT_MAX < SIZE_MAX, ensuring
that all int indexes from the API will work.
- add range checks on allocation before multiplication, to avoid
overflow.
- This means a lower max entry count on 32-bit to avoid 32-bit
allocation overflow.
Fixes: eaafbad419bf ("cfgfile: library to interpret config files")
Signed-off-by: Bruce Richardson <bruce.richardson at intel.com>
---
lib/cfgfile/rte_cfgfile.c | 90 +++++++++++++++++++++++----------------
1 file changed, 54 insertions(+), 36 deletions(-)
diff --git a/lib/cfgfile/rte_cfgfile.c b/lib/cfgfile/rte_cfgfile.c
index 13ba3957bc..b657157096 100644
--- a/lib/cfgfile/rte_cfgfile.c
+++ b/lib/cfgfile/rte_cfgfile.c
@@ -7,6 +7,7 @@
#include <string.h>
#include <ctype.h>
#include <errno.h>
+#include <stdint.h>
#include <rte_string_fns.h>
#include <rte_common.h>
#include <rte_log.h>
@@ -15,15 +16,15 @@
struct rte_cfgfile_section {
char name[CFG_NAME_LEN];
- int num_entries;
- int allocated_entries;
+ size_t num_entries;
+ size_t allocated_entries;
struct rte_cfgfile_entry *entries;
};
struct rte_cfgfile {
int flags;
- int num_sections;
- int allocated_sections;
+ size_t num_sections;
+ size_t allocated_sections;
struct rte_cfgfile_section *sections;
};
@@ -35,13 +36,33 @@ RTE_LOG_REGISTER_DEFAULT(cfgfile_logtype, INFO);
RTE_LOG_LINE_PREFIX(level, CFGFILE, "%s(): ", __func__, __VA_ARGS__)
/* >8 End of setting up dynamic logging */
+/* Define a max allocation limit for entry and section types.
+ * For 64-bit systems, this is based on INT_MAX since API work on int values.
+ * For 32-bit systems, this is based on SIZE_MAX / sizeof(type) to prevent overflow on allocation.
+ */
+#define CFG_ALLOC_MAX(type) \
+ (sizeof(int) == sizeof(size_t) ? (SIZE_MAX / sizeof(type)) : ((size_t)INT_MAX))
+
/** when we resize a file structure, how many extra entries
* for new sections do we add in */
#define CFG_ALLOC_SECTION_BATCH 8
+
+/* Max number of section entries we can possibly have.
+ * Used to prevent overflow on allocation.
+ * Based on INT_MAX since API work on int values.
+ */
+#define CFG_ALLOC_SECTION_MAX CFG_ALLOC_MAX(struct rte_cfgfile_section)
+
/** when we resize a section structure, how many extra entries
* for new entries do we add in */
#define CFG_ALLOC_ENTRY_BATCH 16
+/* Max number of data entries we can possibly have.
+ * Used to prevent overflow on allocation.
+ * Based on INT_MAX since API work on int values.
+ */
+#define CFG_ALLOC_ENTRY_MAX CFG_ALLOC_MAX(struct rte_cfgfile_entry)
+
/**
* Default cfgfile load parameters.
*/
@@ -91,9 +112,7 @@ _strip(char *str, unsigned len)
static struct rte_cfgfile_section *
_get_section(struct rte_cfgfile *cfg, const char *sectionname)
{
- int i;
-
- for (i = 0; i < cfg->num_sections; i++) {
+ for (size_t i = 0; i < cfg->num_sections; i++) {
if (strncmp(cfg->sections[i].name, sectionname,
sizeof(cfg->sections[0].name)) == 0)
return &cfg->sections[i];
@@ -107,6 +126,9 @@ _add_entry(struct rte_cfgfile_section *section, const char *entryname,
{
/* resize entry structure if we don't have room for more entries */
if (section->num_entries == section->allocated_entries) {
+ if (section->allocated_entries > CFG_ALLOC_ENTRY_MAX - CFG_ALLOC_ENTRY_BATCH)
+ return -ENOMEM;
+
struct rte_cfgfile_entry *n_entries = realloc(
section->entries,
sizeof(struct rte_cfgfile_entry) *
@@ -272,7 +294,6 @@ error1:
struct rte_cfgfile *
rte_cfgfile_create(int flags)
{
- int i;
struct rte_cfgfile *cfg;
/* future proof flags usage */
@@ -295,7 +316,7 @@ rte_cfgfile_create(int flags)
cfg->allocated_sections = CFG_ALLOC_SECTION_BATCH;
- for (i = 0; i < CFG_ALLOC_SECTION_BATCH; i++) {
+ for (size_t i = 0; i < CFG_ALLOC_SECTION_BATCH; i++) {
cfg->sections[i].entries = calloc(CFG_ALLOC_ENTRY_BATCH,
sizeof(struct rte_cfgfile_entry));
@@ -312,7 +333,7 @@ rte_cfgfile_create(int flags)
return cfg;
error1:
if (cfg->sections != NULL) {
- for (i = 0; i < cfg->allocated_sections; i++) {
+ for (size_t i = 0; i < cfg->allocated_sections; i++) {
if (cfg->sections[i].entries != NULL) {
free(cfg->sections[i].entries);
cfg->sections[i].entries = NULL;
@@ -328,8 +349,6 @@ error1:
int
rte_cfgfile_add_section(struct rte_cfgfile *cfg, const char *sectionname)
{
- int i;
-
if (cfg == NULL)
return -EINVAL;
@@ -338,6 +357,8 @@ rte_cfgfile_add_section(struct rte_cfgfile *cfg, const char *sectionname)
/* resize overall struct if we don't have room for more sections */
if (cfg->num_sections == cfg->allocated_sections) {
+ if (cfg->allocated_sections > CFG_ALLOC_SECTION_MAX - CFG_ALLOC_SECTION_BATCH)
+ return -ENOMEM;
struct rte_cfgfile_section *n_sections =
realloc(cfg->sections,
@@ -348,7 +369,7 @@ rte_cfgfile_add_section(struct rte_cfgfile *cfg, const char *sectionname)
if (n_sections == NULL)
return -ENOMEM;
- for (i = 0; i < CFG_ALLOC_SECTION_BATCH; i++) {
+ for (size_t i = 0; i < CFG_ALLOC_SECTION_BATCH; i++) {
n_sections[i + cfg->allocated_sections].num_entries = 0;
n_sections[i +
cfg->allocated_sections].allocated_entries = 0;
@@ -393,8 +414,6 @@ int rte_cfgfile_add_entry(struct rte_cfgfile *cfg,
int rte_cfgfile_set_entry(struct rte_cfgfile *cfg, const char *sectionname,
const char *entryname, const char *entryvalue)
{
- int i;
-
if ((cfg == NULL) || (sectionname == NULL) || (entryname == NULL))
return -EINVAL;
@@ -407,7 +426,7 @@ int rte_cfgfile_set_entry(struct rte_cfgfile *cfg, const char *sectionname,
if (entryvalue == NULL)
entryvalue = "";
- for (i = 0; i < curr_section->num_entries; i++)
+ for (size_t i = 0; i < curr_section->num_entries; i++)
if (!strcmp(curr_section->entries[i].name, entryname)) {
strlcpy(curr_section->entries[i].value, entryvalue,
sizeof(curr_section->entries[i].value));
@@ -420,8 +439,6 @@ int rte_cfgfile_set_entry(struct rte_cfgfile *cfg, const char *sectionname,
int rte_cfgfile_save(struct rte_cfgfile *cfg, const char *filename)
{
- int i, j;
-
if ((cfg == NULL) || (filename == NULL))
return -EINVAL;
@@ -430,10 +447,10 @@ int rte_cfgfile_save(struct rte_cfgfile *cfg, const char *filename)
if (f == NULL)
return -EINVAL;
- for (i = 0; i < cfg->num_sections; i++) {
+ for (size_t i = 0; i < cfg->num_sections; i++) {
fprintf(f, "[%s]\n", cfg->sections[i].name);
- for (j = 0; j < cfg->sections[i].num_entries; j++) {
+ for (size_t j = 0; j < cfg->sections[i].num_entries; j++) {
fprintf(f, "%s=%s\n",
cfg->sections[i].entries[j].name,
cfg->sections[i].entries[j].value);
@@ -444,13 +461,11 @@ int rte_cfgfile_save(struct rte_cfgfile *cfg, const char *filename)
int rte_cfgfile_close(struct rte_cfgfile *cfg)
{
- int i;
-
if (cfg == NULL)
return -1;
if (cfg->sections != NULL) {
- for (i = 0; i < cfg->allocated_sections; i++) {
+ for (size_t i = 0; i < cfg->allocated_sections; i++) {
if (cfg->sections[i].entries != NULL) {
free(cfg->sections[i].entries);
cfg->sections[i].entries = NULL;
@@ -469,13 +484,13 @@ int
rte_cfgfile_num_sections(struct rte_cfgfile *cfg, const char *sectionname,
size_t length)
{
- int i;
- int num_sections = 0;
- for (i = 0; i < cfg->num_sections; i++) {
+ size_t num_sections = 0;
+ for (size_t i = 0; i < cfg->num_sections; i++) {
if (strncmp(cfg->sections[i].name, sectionname, length) == 0)
num_sections++;
}
- return num_sections;
+
+ return (int)num_sections;
}
int
@@ -484,7 +499,7 @@ rte_cfgfile_sections(struct rte_cfgfile *cfg, char *sections[],
{
int i;
- for (i = 0; i < cfg->num_sections && i < max_sections; i++)
+ for (i = 0; (size_t)i < cfg->num_sections && i < max_sections; i++)
strlcpy(sections[i], cfg->sections[i].name, CFG_NAME_LEN);
return i;
@@ -503,20 +518,21 @@ rte_cfgfile_section_num_entries(struct rte_cfgfile *cfg,
const struct rte_cfgfile_section *s = _get_section(cfg, sectionname);
if (s == NULL)
return -1;
- return s->num_entries;
+
+ return (int)s->num_entries;
}
int
rte_cfgfile_section_num_entries_by_index(struct rte_cfgfile *cfg,
char *sectionname, int index)
{
- if (index < 0 || index >= cfg->num_sections)
+ if (index < 0 || (size_t)index >= cfg->num_sections)
return -1;
const struct rte_cfgfile_section *sect = &(cfg->sections[index]);
strlcpy(sectionname, sect->name, CFG_NAME_LEN);
- return sect->num_entries;
+ return (int)sect->num_entries;
}
int
rte_cfgfile_section_entries(struct rte_cfgfile *cfg, const char *sectionname,
@@ -526,7 +542,7 @@ rte_cfgfile_section_entries(struct rte_cfgfile *cfg, const char *sectionname,
const struct rte_cfgfile_section *sect = _get_section(cfg, sectionname);
if (sect == NULL)
return -1;
- for (i = 0; i < max_entries && i < sect->num_entries; i++)
+ for (i = 0; i < max_entries && (size_t)i < sect->num_entries; i++)
entries[i] = sect->entries[i];
return i;
}
@@ -539,11 +555,14 @@ rte_cfgfile_section_entries_by_index(struct rte_cfgfile *cfg, int index,
int i;
const struct rte_cfgfile_section *sect;
- if (index < 0 || index >= cfg->num_sections)
+ if (max_entries < 0)
+ return -1;
+
+ if (index < 0 || (size_t)index >= cfg->num_sections)
return -1;
sect = &cfg->sections[index];
strlcpy(sectionname, sect->name, CFG_NAME_LEN);
- for (i = 0; i < max_entries && i < sect->num_entries; i++)
+ for (i = 0; i < max_entries && (size_t)i < sect->num_entries; i++)
entries[i] = sect->entries[i];
return i;
}
@@ -552,11 +571,10 @@ const char *
rte_cfgfile_get_entry(struct rte_cfgfile *cfg, const char *sectionname,
const char *entryname)
{
- int i;
const struct rte_cfgfile_section *sect = _get_section(cfg, sectionname);
if (sect == NULL)
return NULL;
- for (i = 0; i < sect->num_entries; i++)
+ for (size_t i = 0; i < sect->num_entries; i++)
if (strncmp(sect->entries[i].name, entryname, CFG_NAME_LEN)
== 0)
return sect->entries[i].value;
--
2.47.3
---
Diff of the applied patch vs upstream commit (please double-check if non-empty:
---
--- - 2026-06-11 14:20:01.551079461 +0100
+++ 0004-cfgfile-prevent-overflow-on-resize.patch 2026-06-11 14:20:01.166744816 +0100
@@ -1 +1 @@
-From 458ed82bef455d76138a62ff15ab7c380fa637f4 Mon Sep 17 00:00:00 2001
+From 1c185b30c7b508646ea7e4529f3a16deb3538ebe Mon Sep 17 00:00:00 2001
@@ -5,0 +6,2 @@
+[ upstream commit 458ed82bef455d76138a62ff15ab7c380fa637f4 ]
+
@@ -20 +21,0 @@
-Cc: stable at dpdk.org
@@ -24,2 +25,2 @@
- lib/cfgfile/rte_cfgfile.c | 92 +++++++++++++++++++++++----------------
- 1 file changed, 54 insertions(+), 38 deletions(-)
+ lib/cfgfile/rte_cfgfile.c | 90 +++++++++++++++++++++++----------------
+ 1 file changed, 54 insertions(+), 36 deletions(-)
@@ -28 +29 @@
-index 25fc792274..6edd83b5b3 100644
+index 13ba3957bc..b657157096 100644
@@ -31 +32,2 @@
-@@ -9,6 +9,7 @@
+@@ -7,6 +7,7 @@
+ #include <string.h>
@@ -34 +35,0 @@
- #include <limits.h>
@@ -36,4 +37,4 @@
-
- #ifndef LINE_MAX
- #define LINE_MAX 2048
-@@ -23,15 +24,15 @@
+ #include <rte_string_fns.h>
+ #include <rte_common.h>
+ #include <rte_log.h>
+@@ -15,15 +16,15 @@
@@ -59 +60 @@
-@@ -43,13 +44,33 @@ RTE_LOG_REGISTER_DEFAULT(cfgfile_logtype, INFO);
+@@ -35,13 +36,33 @@ RTE_LOG_REGISTER_DEFAULT(cfgfile_logtype, INFO);
@@ -93 +94 @@
-@@ -99,9 +120,7 @@ _strip(char *str, unsigned len)
+@@ -91,9 +112,7 @@ _strip(char *str, unsigned len)
@@ -104,2 +105,2 @@
-@@ -118,6 +137,9 @@ _add_entry(struct rte_cfgfile_section *section, const char *entryname,
-
+@@ -107,6 +126,9 @@ _add_entry(struct rte_cfgfile_section *section, const char *entryname,
+ {
@@ -114 +115 @@
-@@ -305,7 +327,6 @@ RTE_EXPORT_SYMBOL(rte_cfgfile_create)
+@@ -272,7 +294,6 @@ error1:
@@ -122 +123 @@
-@@ -328,7 +349,7 @@ rte_cfgfile_create(int flags)
+@@ -295,7 +316,7 @@ rte_cfgfile_create(int flags)
@@ -131 +132 @@
-@@ -345,7 +366,7 @@ rte_cfgfile_create(int flags)
+@@ -312,7 +333,7 @@ rte_cfgfile_create(int flags)
@@ -140 +141 @@
-@@ -362,8 +383,6 @@ RTE_EXPORT_SYMBOL(rte_cfgfile_add_section)
+@@ -328,8 +349,6 @@ error1:
@@ -149 +150 @@
-@@ -375,6 +394,8 @@ rte_cfgfile_add_section(struct rte_cfgfile *cfg, const char *sectionname)
+@@ -338,6 +357,8 @@ rte_cfgfile_add_section(struct rte_cfgfile *cfg, const char *sectionname)
@@ -158 +159 @@
-@@ -385,7 +406,7 @@ rte_cfgfile_add_section(struct rte_cfgfile *cfg, const char *sectionname)
+@@ -348,7 +369,7 @@ rte_cfgfile_add_section(struct rte_cfgfile *cfg, const char *sectionname)
@@ -167 +168 @@
-@@ -428,8 +449,6 @@ RTE_EXPORT_SYMBOL(rte_cfgfile_set_entry)
+@@ -393,8 +414,6 @@ int rte_cfgfile_add_entry(struct rte_cfgfile *cfg,
@@ -176 +177 @@
-@@ -442,7 +461,7 @@ int rte_cfgfile_set_entry(struct rte_cfgfile *cfg, const char *sectionname,
+@@ -407,7 +426,7 @@ int rte_cfgfile_set_entry(struct rte_cfgfile *cfg, const char *sectionname,
@@ -185,2 +186,2 @@
-@@ -456,8 +475,6 @@ int rte_cfgfile_set_entry(struct rte_cfgfile *cfg, const char *sectionname,
- RTE_EXPORT_SYMBOL(rte_cfgfile_save)
+@@ -420,8 +439,6 @@ int rte_cfgfile_set_entry(struct rte_cfgfile *cfg, const char *sectionname,
+
@@ -194 +195 @@
-@@ -466,10 +483,10 @@ int rte_cfgfile_save(struct rte_cfgfile *cfg, const char *filename)
+@@ -430,10 +447,10 @@ int rte_cfgfile_save(struct rte_cfgfile *cfg, const char *filename)
@@ -207,2 +208,2 @@
-@@ -481,13 +498,11 @@ int rte_cfgfile_save(struct rte_cfgfile *cfg, const char *filename)
- RTE_EXPORT_SYMBOL(rte_cfgfile_close)
+@@ -444,13 +461,11 @@ int rte_cfgfile_save(struct rte_cfgfile *cfg, const char *filename)
+
@@ -222 +223 @@
-@@ -507,20 +522,20 @@ int
+@@ -469,13 +484,13 @@ int
@@ -224 +225 @@
- size_t length)
+ size_t length)
@@ -226 +226,0 @@
-- int num_sections = 0;
@@ -228,9 +228 @@
-+ size_t num_sections = 0;
-
- if (cfg == NULL)
- return -1;
-
- if (sectionname == NULL)
-- return cfg->num_sections;
-+ return (int)cfg->num_sections;
-
+- int num_sections = 0;
@@ -237,0 +230 @@
++ size_t num_sections = 0;
@@ -247,4 +240,4 @@
- RTE_EXPORT_SYMBOL(rte_cfgfile_sections)
-@@ -533,7 +548,7 @@ rte_cfgfile_sections(struct rte_cfgfile *cfg, char *sections[],
- if (cfg == NULL || sections == NULL || max_sections < 0)
- return -1;
+ int
+@@ -484,7 +499,7 @@ rte_cfgfile_sections(struct rte_cfgfile *cfg, char *sections[],
+ {
+ int i;
@@ -252,4 +245,2 @@
-- for (i = 0; i < cfg->num_sections && i < max_sections; i++) {
-+ for (i = 0; (size_t)i < cfg->num_sections && i < max_sections; i++) {
- if (sections[i] == NULL)
- return -1;
+- for (i = 0; i < cfg->num_sections && i < max_sections; i++)
++ for (i = 0; (size_t)i < cfg->num_sections && i < max_sections; i++)
@@ -257 +248,3 @@
-@@ -563,7 +578,8 @@ rte_cfgfile_section_num_entries(struct rte_cfgfile *cfg,
+
+ return i;
+@@ -503,20 +518,21 @@ rte_cfgfile_section_num_entries(struct rte_cfgfile *cfg,
@@ -266,5 +259,4 @@
- RTE_EXPORT_SYMBOL(rte_cfgfile_section_num_entries_by_index)
-@@ -574,13 +590,13 @@ rte_cfgfile_section_num_entries_by_index(struct rte_cfgfile *cfg,
- if (cfg == NULL || sectionname == NULL)
- return -1;
-
+ int
+ rte_cfgfile_section_num_entries_by_index(struct rte_cfgfile *cfg,
+ char *sectionname, int index)
+ {
@@ -281 +272,0 @@
- RTE_EXPORT_SYMBOL(rte_cfgfile_section_entries)
@@ -283 +274,2 @@
-@@ -595,7 +611,7 @@ rte_cfgfile_section_entries(struct rte_cfgfile *cfg, const char *sectionname,
+ rte_cfgfile_section_entries(struct rte_cfgfile *cfg, const char *sectionname,
+@@ -526,7 +542,7 @@ rte_cfgfile_section_entries(struct rte_cfgfile *cfg, const char *sectionname,
@@ -292 +284,3 @@
-@@ -611,12 +627,14 @@ rte_cfgfile_section_entries_by_index(struct rte_cfgfile *cfg, int index,
+@@ -539,11 +555,14 @@ rte_cfgfile_section_entries_by_index(struct rte_cfgfile *cfg, int index,
+ int i;
+ const struct rte_cfgfile_section *sect;
@@ -294,2 +288 @@
- if (cfg == NULL || sectionname == NULL || entries == NULL)
- return -1;
+- if (index < 0 || index >= cfg->num_sections)
@@ -298,2 +291 @@
-
-- if (index < 0 || index >= cfg->num_sections)
++
@@ -309 +301 @@
-@@ -626,15 +644,13 @@ const char *
+@@ -552,11 +571,10 @@ const char *
@@ -314,4 +305,0 @@
--
- if (cfg == NULL || sectionname == NULL || entryname == NULL)
- return NULL;
-
More information about the stable
mailing list