From e751b3236c7ed2544e49f377bb6356872b313c31 Mon Sep 17 00:00:00 2001 From: Kamalesh Babulal Date: Wed, 8 Feb 2023 12:25:10 +0530 Subject: [PATCH] api.c: cg_build_path_locked() - work around snprintf() warnings Recent gcc are unhappy when sizeof(dest) <= sizeof(src) with snprintf()'s. We could need too many strncpy()'s and strcat()'s for constructing file path, so let's workaround it by allocating long enough space for keeping snprintf() happy and then use the temporarily allocated array and use it as src for strncpy() with limit of FILENAME_MAX. Signed-off-by: Kamalesh Babulal Signed-off-by: Tom Hromatka --- src/api.c | 72 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/src/api.c b/src/api.c index f304d2f4..984bab96 100644 --- a/src/api.c +++ b/src/api.c @@ -1680,7 +1680,24 @@ static char *cg_concat_path(const char *pref, const char *suf, char *path) /* path value have to have size at least FILENAME_MAX */ char *cg_build_path_locked(const char *name, char *path, const char *type) { - int i, ret; + /* + * len is the allocation size for path, that stores: + * cg_mount_table[i].mount.path + '/' + cg_namespace_table[i] + '/' + */ + int i, ret, len = (FILENAME_MAX * 2) + 2; + char *_path; + + /* + * Recent gcc are unhappy when sizeof(dest) <= sizeof(src) with + * snprintf()'s. Alternative is to use multiple strncpy()/strcat(), + * work around it by allocating large temporary buffer _path and + * copying the constructed _path into path. + */ + _path = malloc(len); + if (!_path) { + cgroup_err("Failed to allocate memory for _path\n"); + return NULL; + } /* * If no type is specified, and there's a valid cgroup v2 mount, then @@ -1689,21 +1706,26 @@ char *cg_build_path_locked(const char *name, char *path, const char *type) * any controller. */ if (!type && strlen(cg_cgroup_v2_mount_path) > 0) { - ret = snprintf(path, FILENAME_MAX, "%s/", cg_cgroup_v2_mount_path); + ret = snprintf(_path, len, "%s/", cg_cgroup_v2_mount_path); if (ret >= FILENAME_MAX) - cgroup_dbg("filename too long: %s/", cg_cgroup_v2_mount_path); + cgroup_dbg("filename too long: %s", _path); + + strncpy(path, _path, FILENAME_MAX - 1); + path[FILENAME_MAX - 1] = '\0'; if (name) { char *tmp; tmp = strdup(path); - if (tmp == NULL) - return NULL; + if (tmp == NULL) { + path = NULL; + goto out; + } cg_concat_path(tmp, name, path); free(tmp); } - return path; + goto out; } for (i = 0; cg_mount_table[i].name[0] != '\0'; i++) { @@ -1717,23 +1739,17 @@ char *cg_build_path_locked(const char *name, char *path, const char *type) (type && strcmp(type, CGROUP_FILE_PREFIX) == 0 && cg_mount_table[i].version == CGROUP_V2)) { - if (cg_namespace_table[i]) { - ret = snprintf(path, FILENAME_MAX, "%s/%s/", - cg_mount_table[i].mount.path, - cg_namespace_table[i]); - if (ret >= FILENAME_MAX) { - cgroup_dbg("filename too long:%s/%s/", - cg_mount_table[i].mount.path, - cg_namespace_table[i]); - } - } else { - ret = snprintf(path, FILENAME_MAX, "%s/", - cg_mount_table[i].mount.path); - if (ret >= FILENAME_MAX) { - cgroup_dbg("filename too long:%s/", - cg_mount_table[i].mount.path); - } - } + if (cg_namespace_table[i]) + ret = snprintf(_path, len, "%s/%s/", cg_mount_table[i].mount.path, + cg_namespace_table[i]); + else + ret = snprintf(_path, len, "%s/", cg_mount_table[i].mount.path); + + if (ret >= FILENAME_MAX) + cgroup_dbg("filename too long: %s", _path); + + strncpy(path, _path, FILENAME_MAX - 1); + path[FILENAME_MAX - 1] = '\0'; if (name) { char *tmp; @@ -1745,10 +1761,16 @@ char *cg_build_path_locked(const char *name, char *path, const char *type) cg_concat_path(tmp, name, path); free(tmp); } - return path; + goto out; } } - return NULL; + path = NULL; + +out: + if (_path) + free(_path); + + return path; } char *cg_build_path(const char *name, char *path, const char *type) -- 2.47.2