From fe9df82ec5eee1da774d0dbe589df2aac0f73e0c Mon Sep 17 00:00:00 2001 From: Sebastian Kloska Date: Tue, 10 Dec 2019 13:34:54 +0100 Subject: BugFix: SEGFAULT when using AppArmor (#192) * Symptome: If access to the trace directory is not granted by AppArmor access(...) still reports otherwise. dlt_offline_trace_get_total_size(...) tries to open the dir via opendir(...) and tries a readdir without any further check, which results in an SEGFAULT * Solution: (1) Make dlt_offline_trace_get_total_size return ssize_t instead of unsigned long, which gives us a chance to return an error state (2) Check the return value from opendir(...) and bail out on error. Use this to return DLT_RETURN_ERROR in dlt_offline_trace_check_size. * ToDo: (1) Error state is not yet checked and reported back. On Error we just don't generate any offline log files without any further complain. (2) Find a replacement for access(...) which reports properly under AppArmor. (3) Report the confusing behaviour of access(...) to the AppArmor team. Signed-off-by: Sebastian Kloska --- src/shared/dlt_offline_trace.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'src/shared') diff --git a/src/shared/dlt_offline_trace.c b/src/shared/dlt_offline_trace.c index 8ab917b..303d6b3 100644 --- a/src/shared/dlt_offline_trace.c +++ b/src/shared/dlt_offline_trace.c @@ -99,19 +99,16 @@ unsigned int dlt_offline_trace_storage_dir_info(char *path, char *file_name, cha else if (strlen(tmp_old) > strlen(files[i]->d_name)) tmp_old = files[i]->d_name; else /* filename is equal, do a string compare */ - if (strcmp(tmp_old, files[i]->d_name) > 0) - tmp_old = files[i]->d_name; + if (strcmp(tmp_old, files[i]->d_name) > 0) + tmp_old = files[i]->d_name; } if ((tmp_new == NULL) || (strlen(tmp_new) <= strlen(files[i]->d_name))) { - if (tmp_new == NULL) { + if (tmp_new == NULL) tmp_new = files[i]->d_name; - } /* when file name is longer, it is younger */ else if (strlen(tmp_new) < strlen(files[i]->d_name)) - { tmp_new = files[i]->d_name; - } else if (strcmp(tmp_new, files[i]->d_name) < 0) tmp_new = files[i]->d_name; } @@ -119,15 +116,13 @@ unsigned int dlt_offline_trace_storage_dir_info(char *path, char *file_name, cha } if (num > 0) { - if (tmp_old != NULL) { + if (tmp_old != NULL) if (strlen(tmp_old) < NAME_MAX) strncpy(oldest, tmp_old, NAME_MAX); - } - if (tmp_new != NULL) { + if (tmp_new != NULL) if (strlen(tmp_old) < NAME_MAX) strncpy(newest, tmp_new, NAME_MAX); - } } /* free scandir result */ @@ -218,7 +213,7 @@ DltReturnValue dlt_offline_trace_create_new_file(DltOfflineTrace *trace) char oldest[NAME_MAX + 1] = { 0 }; /* targeting newest file, ignoring number of files in dir returned */ dlt_offline_trace_storage_dir_info(trace->directory, - DLT_OFFLINETRACE_FILENAME_BASE, newest, oldest); + DLT_OFFLINETRACE_FILENAME_BASE, newest, oldest); idx = dlt_offline_trace_get_idx_of_log_file(newest) + 1; dlt_offline_trace_file_name(trace->filename, sizeof(trace->filename), @@ -245,16 +240,19 @@ DltReturnValue dlt_offline_trace_create_new_file(DltOfflineTrace *trace) return DLT_RETURN_OK; /* OK */ } -unsigned long dlt_offline_trace_get_total_size(DltOfflineTrace *trace) +ssize_t dlt_offline_trace_get_total_size(DltOfflineTrace *trace) { struct dirent *dp; char filename[PATH_MAX + 1]; - unsigned long size = 0; + ssize_t size = 0; struct stat status; /* go through all dlt files in directory */ DIR *dir = opendir(trace->directory); + if (!dir) + return -1; + while ((dp = readdir(dir)) != NULL) if (strstr(dp->d_name, DLT_OFFLINETRACE_FILENAME_BASE)) { int res = snprintf(filename, sizeof(filename), "%s/%s", trace->directory, dp->d_name); @@ -354,12 +352,17 @@ DltReturnValue dlt_offline_trace_check_size(DltOfflineTrace *trace) return DLT_RETURN_ERROR; } + ssize_t s = 0; + /* check size of complete offline trace */ - while ((int)dlt_offline_trace_get_total_size(trace) > (trace->maxSize - trace->fileSize)) + while ((s = dlt_offline_trace_get_total_size(trace)) > (trace->maxSize - trace->fileSize)) /* remove oldest files as long as new file will not fit in completely into complete offline trace */ if (dlt_offline_trace_delete_oldest_file(trace) < 0) return DLT_RETURN_ERROR; + if (s == -1) + return DLT_RETURN_ERROR; + return DLT_RETURN_OK; /* OK */ } -- cgit v1.2.1