* the old implementation checks only presence of the time file * now we check validity of the time file
Signed-off-by: Jakub Filak jfilak@redhat.com --- src/lib/dump_dir.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 3 deletions(-)
diff --git a/src/lib/dump_dir.c b/src/lib/dump_dir.c index eef01f7..e945bad 100644 --- a/src/lib/dump_dir.c +++ b/src/lib/dump_dir.c @@ -109,6 +109,57 @@ static bool exist_file_dir(const char *path) return false; }
+static bool not_valid_time_file(const char *filename) +{ + /* Open input file, and parse it. */ + int fd = open(filename, O_RDONLY); + if (fd < 0) + { + VERB1 log("Unable to open '%s': %s.\n", filename, strerror(errno)); + return true; + } + + off_t size = lseek(fd, 0, SEEK_END); + if (size == (off_t)-1) /* EOVERFLOW? */ + { + VERB1 log("Unable to seek in '%s': %s.\n", filename, strerror(errno)); + close(fd); + return true; + } + + lseek(fd, 0, SEEK_SET); /* No reason to fail. */ + + static const size_t FILE_SIZE_LIMIT = sizeof(time_t) * 3; /* ~ maximal number of digits */ + if (size > FILE_SIZE_LIMIT) + { + VERB1 log("Input file too big (%lld). Maximum size is %zd.\n", + (long long)size, FILE_SIZE_LIMIT); + close(fd); + return true; + } + + char *time_str = xmalloc(size + 1); + if (size != read(fd, time_str, size)) + { + VERB1 log("Unable to read from '%s'.\n", filename); + close(fd); + free(time_str); + return true; + } + + /* Just reading, so no need to check the returned value. */ + close(fd); + + time_str[size] = '\0'; + + /* range should OK because of file size condition above */ + const bool invalidity = !isdigit_str(time_str); + + free(time_str); + + return invalidity; +} + /* Return values: * -1: error (in this case, errno is 0 if error message is already logged) * 0: failed to lock (someone else has it locked) @@ -203,7 +254,7 @@ static int dd_lock(struct dump_dir *dd, unsigned sleep_usec, int flags) if (sleep_usec == WAIT_FOR_OTHER_PROCESS_USLEEP) /* yes */ { strcpy(lock_buf + dirname_len, "/"FILENAME_TIME); - if (access(lock_buf, F_OK) != 0) + if (not_valid_time_file(lock_buf)) { /* time file doesn't exist. We managed to lock the directory * which was just created by somebody else, or is almost deleted @@ -212,7 +263,7 @@ static int dd_lock(struct dump_dir *dd, unsigned sleep_usec, int flags) */ strcpy(lock_buf + dirname_len, "/.lock"); xunlink(lock_buf); - VERB1 log("Unlocked '%s' (no time file)", lock_buf); + VERB1 log("Unlocked '%s' (no or corrupted time file)", lock_buf); if (--count == 0) { errno = EISDIR; /* "this is an ordinary dir, not dump dir" */ @@ -303,7 +354,7 @@ struct dump_dir *dd_opendir(const char *dir, int flags) && access(dir, R_OK) == 0 ) { char *time_file_name = concat_path_file(dir, FILENAME_TIME); - if (access(time_file_name, R_OK) != 0) + if (not_valid_time_file(time_file_name)) { dd_close(dd); dd = NULL;