Skip to content

Commit

Permalink
FAPI: Fix file io if d_type of dirent is not supported.
Browse files Browse the repository at this point in the history
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 tpm2-software#2927

Signed-off-by: Juergen Repp <juergen_repp@web.de>
  • Loading branch information
JuergenReppSIT committed Dec 17, 2024
1 parent 7375e27 commit 0e30964
Showing 1 changed file with 83 additions and 3 deletions.
86 changes: 83 additions & 3 deletions src/tss2-fapi/ifapi_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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);

Expand All @@ -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);

Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down

0 comments on commit 0e30964

Please sign in to comment.