From 0e30964ac3e9d1163225961936e91f81aec2c9a7 Mon Sep 17 00:00:00 2001 From: Juergen Repp Date: Mon, 16 Dec 2024 22:35:20 +0100 Subject: [PATCH] FAPI: Fix file io if d_type of dirent is not supported. It is not guaranteed that d-type of the structure dirent contains the type of a file entry. It is possible that d_type has the value DT_UNKNOWN or d_type is not supported at all. To fix this problem, the functions is_regular_file and is_directory are defined. Fixes #2927 Signed-off-by: Juergen Repp --- src/tss2-fapi/ifapi_io.c | 86 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 3 deletions(-) diff --git a/src/tss2-fapi/ifapi_io.c b/src/tss2-fapi/ifapi_io.c index d1058f394..2cb3c844c 100644 --- a/src/tss2-fapi/ifapi_io.c +++ b/src/tss2-fapi/ifapi_io.c @@ -29,6 +29,73 @@ #define LOGMODULE fapi #include "util/log.h" // for LOG_ERROR, SAFE_FREE, LOG_TRACE, goto_error +static TSS2_RC +is_directory(const char* dir_name, struct dirent *entry, bool *isdir) { + TSS2_RC r; + char *path; + +#ifdef _DIRENT_HAVE_D_TYPE + if (entry->d_type == DT_DIR) { + *isdir = true; + return TSS2_RC_SUCCESS; + } else if (entry->d_type == DT_UNKNOWN) { + } else { + *isdir = false; + return TSS2_RC_SUCCESS; + } +#endif + struct stat file_stat; + r = ifapi_asprintf(&path, "%s/%s", dir_name, entry->d_name); + return_if_error(r, "Out of memory"); + + if (stat(path, &file_stat) == -1) { + free(path); + return_error(TSS2_FAPI_RC_IO_ERROR, "stat failed."); + } + if (S_ISDIR(file_stat.st_mode)) { + *isdir = true; + } else { + *isdir = false; + } + free(path); + return TSS2_RC_SUCCESS; +} + +static TSS2_RC +is_regular_file(const char* dir_name, struct dirent *entry, bool *isreg) { + TSS2_RC r; + char *path; + +#ifdef _DIRENT_HAVE_D_TYPE + if (entry->d_type == DT_REG) { + *isreg = true; + return TSS2_RC_SUCCESS; + } else if (entry->d_type == DT_UNKNOWN) { + } else { + *isreg = false; + return TSS2_RC_SUCCESS; + } +#endif + struct stat file_stat; + r = ifapi_asprintf(&path, "%s/%s", dir_name, entry->d_name); + return_if_error(r, "Out of memory"); + + if (stat(path, &file_stat) == -1) { + free(path); + return_error(TSS2_FAPI_RC_IO_ERROR, "stat failed."); + } + if (S_ISREG(file_stat.st_mode)) { + *isreg = true; + } else { + *isreg = false; + } + free(path); + return TSS2_RC_SUCCESS; +} + + + + /** Start reading a file's complete content into memory in an asynchronous way. * * @param[in,out] io The input/output context being used for file I/O. @@ -390,6 +457,7 @@ ifapi_io_remove_directories( TSS2_RC r; char *path; size_t len_kstore_path, len_dir_path, diff_len, pos; + bool is_dir; LOG_TRACE("Removing directory: %s", dirname); @@ -407,7 +475,10 @@ ifapi_io_remove_directories( continue; /* If an entry is a directory then we call ourself recursively to remove those */ - if (entry->d_type == DT_DIR) { + r = is_directory(dirname, entry, &is_dir); + if (r) goto error_cleanup; + + if (is_dir) { r = ifapi_asprintf(&path, "%s/%s", dirname, entry->d_name); goto_if_error(r, "Out of memory", error_cleanup); @@ -480,6 +551,8 @@ ifapi_io_dirfiles( int numentries = 0; struct dirent **namelist; size_t numpaths = 0; + bool is_reg_file; + TSS2_RC r; check_not_null(dirname); check_not_null(files); check_not_null(numfiles); @@ -498,7 +571,10 @@ ifapi_io_dirfiles( /* Iterating through the list of entries inside the directory. */ for (size_t i = 0; i < (size_t) numentries; i++) { LOG_TRACE("Looking at %s", namelist[i]->d_name); - if (namelist[i]->d_type != DT_REG) + + r = is_regular_file(dirname, namelist[i], &is_reg_file); + if (r) goto error_oom; + if (!is_reg_file) continue; paths[numpaths] = strdup(namelist[i]->d_name); @@ -549,6 +625,7 @@ dirfiles_all(const char *dir_name, NODE_OBJECT_T **list, size_t *n) TSS2_RC r; char *path; NODE_OBJECT_T *second; + bool is_dir; if (!(dir = opendir(dir_name))) { return TSS2_RC_SUCCESS; @@ -557,7 +634,10 @@ dirfiles_all(const char *dir_name, NODE_OBJECT_T **list, size_t *n) /* Iterating through the list of entries inside the directory. */ while ((entry = readdir(dir)) != NULL) { path = NULL; - if (entry->d_type == DT_DIR) { + r = is_directory(dir_name, entry, &is_dir); + return_if_error(r, "directory check failed"); + + if (is_dir) { /* Recursive call for sub directories */ if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue;