When constructing huge filename path, check for possible overflow of PATH_MAX.
Signed-off-by: Stephen Hemminger <[email protected]> --- lib/eal/common/eal_filesystem.h | 10 +++++---- lib/eal/linux/eal_hugepage_info.c | 34 +++++++++++++++++++++---------- lib/eal/linux/eal_memalloc.c | 11 ++++++++-- lib/eal/linux/eal_memory.c | 9 ++++++-- 4 files changed, 45 insertions(+), 19 deletions(-) diff --git a/lib/eal/common/eal_filesystem.h b/lib/eal/common/eal_filesystem.h index 70ae21b078..c2f2856e27 100644 --- a/lib/eal/common/eal_filesystem.h +++ b/lib/eal/common/eal_filesystem.h @@ -104,12 +104,14 @@ eal_hugepage_data_path(void) /** String format for hugepage map files. */ #define HUGEFILE_FMT "%s/%smap_%d" -static inline const char * +static inline __rte_warn_unused_result const char * eal_get_hugefile_path(char *buffer, size_t buflen, const char *hugedir, int f_id) { - snprintf(buffer, buflen, HUGEFILE_FMT, hugedir, - eal_get_hugefile_prefix(), f_id); - return buffer; + if (snprintf(buffer, buflen, HUGEFILE_FMT, hugedir, + eal_get_hugefile_prefix(), f_id) >= (int)buflen) + return NULL; + else + return buffer; } /** define the default filename prefix for the %s values above */ diff --git a/lib/eal/linux/eal_hugepage_info.c b/lib/eal/linux/eal_hugepage_info.c index f6d7098a07..b3b53fee6b 100644 --- a/lib/eal/linux/eal_hugepage_info.c +++ b/lib/eal/linux/eal_hugepage_info.c @@ -70,11 +70,14 @@ create_shared_memory(const char *filename, const size_t mem_size) static int get_hp_sysfs_value(const char *subdir, const char *file, unsigned long *val) { - char path[PATH_MAX]; + char *path = NULL; + int ret; - snprintf(path, sizeof(path), "%s/%s/%s", - sys_dir_path, subdir, file); - return eal_parse_sysfs_value(path, val); + if (asprintf(&path, "%s/%s/%s", sys_dir_path, subdir, file) < 0) + return -1; + ret = eal_parse_sysfs_value(path, val); + free(path); + return ret; } /* this function is only called from eal_hugepage_info_init which itself @@ -135,13 +138,15 @@ get_num_hugepages(const char *subdir, size_t sz, unsigned int reusable_pages) static uint32_t get_num_hugepages_on_node(const char *subdir, unsigned int socket, size_t sz) { - char path[PATH_MAX], socketpath[PATH_MAX]; + char *path = NULL, *socketpath = NULL; DIR *socketdir; unsigned long num_pages = 0; const char *nr_hp_file = "free_hugepages"; - snprintf(socketpath, sizeof(socketpath), "%s/node%u/hugepages", - sys_pages_numa_dir_path, socket); + if (asprintf(&socketpath, "%s/node%u/hugepages", sys_pages_numa_dir_path, socket) < 0) { + EAL_LOG(ERR, "Can not format node huge page path"); + goto nopages; + } socketdir = opendir(socketpath); if (socketdir) { @@ -149,13 +154,16 @@ get_num_hugepages_on_node(const char *subdir, unsigned int socket, size_t sz) closedir(socketdir); } else { /* Can't find socket dir, so ignore it */ - return 0; + goto nopages; + } + + if (asprintf(&path, "%s/%s/%s", socketpath, subdir, nr_hp_file) < 0) { + EAL_LOG(ERR, "Can not format free hugepages path"); + goto nopages; } - snprintf(path, sizeof(path), "%s/%s/%s", - socketpath, subdir, nr_hp_file); if (eal_parse_sysfs_value(path, &num_pages) < 0) - return 0; + goto nopages; if (num_pages == 0) EAL_LOG(WARNING, "No free %zu kB hugepages reported on node %u", @@ -168,6 +176,10 @@ get_num_hugepages_on_node(const char *subdir, unsigned int socket, size_t sz) if (num_pages > UINT32_MAX) num_pages = UINT32_MAX; +nopages: + free(path); + free(socketpath); + return num_pages; } diff --git a/lib/eal/linux/eal_memalloc.c b/lib/eal/linux/eal_memalloc.c index 1e60e21620..d9e8ea76b9 100644 --- a/lib/eal/linux/eal_memalloc.c +++ b/lib/eal/linux/eal_memalloc.c @@ -260,6 +260,7 @@ get_seg_fd(char *path, int buflen, struct hugepage_info *hi, { int fd; int *out_fd; + const char *huge_path; struct stat st; int ret; const struct internal_config *internal_conf = @@ -276,12 +277,18 @@ get_seg_fd(char *path, int buflen, struct hugepage_info *hi, if (internal_conf->single_file_segments) { out_fd = &fd_list[list_idx].memseg_list_fd; - eal_get_hugefile_path(path, buflen, hi->hugedir, list_idx); + huge_path = eal_get_hugefile_path(path, buflen, hi->hugedir, list_idx); } else { out_fd = &fd_list[list_idx].fds[seg_idx]; - eal_get_hugefile_path(path, buflen, hi->hugedir, + huge_path = eal_get_hugefile_path(path, buflen, hi->hugedir, list_idx * RTE_MAX_MEMSEG_PER_LIST + seg_idx); } + if (huge_path == NULL) { + EAL_LOG(DEBUG, "%s(): hugefile path truncated: '%s'", + __func__, path); + return -1; + } + fd = *out_fd; if (fd >= 0) return fd; diff --git a/lib/eal/linux/eal_memory.c b/lib/eal/linux/eal_memory.c index 8e1763e890..2a0a441398 100644 --- a/lib/eal/linux/eal_memory.c +++ b/lib/eal/linux/eal_memory.c @@ -337,8 +337,13 @@ map_all_hugepages(struct hugepage_file *hugepg_tbl, struct hugepage_info *hpi, hf->file_id = i; hf->size = hugepage_sz; - eal_get_hugefile_path(hf->filepath, sizeof(hf->filepath), - hpi->hugedir, hf->file_id); + if (eal_get_hugefile_path(hf->filepath, sizeof(hf->filepath), + hpi->hugedir, hf->file_id) == NULL) { + EAL_LOG(DEBUG, "%s(): huge file path '%s' truncated", + __func__, hf->filepath); + goto out; + } + hf->filepath[sizeof(hf->filepath) - 1] = '\0'; /* try to create hugepage file */ -- 2.51.0

