(/home/sate/Testcases/c/cve/dovecot-1.2.0/src/lib/unlink-old-files.c) |
| |
| 16 | | | unlink_old_files_real(const char *dir, const char *prefix, time_t min_time) |
| 17 | | | { |
| 18 | | | DIR *dirp; |
| 19 | | | struct dirent *d; |
| 20 | | | struct stat st; |
| 21 | | | string_t *path; |
| 22 | | | unsigned int prefix_len, dir_len; |
| 23 | | | |
| 24 | | | dirp = opendir(dir); |
Event 1:
dir is passed to opendir().
hide
Event 2:
opendir() accesses the file named dir. - The same name is used to access a file later, but it is not safe to assume that it will be the same underlying file.
See related event 1.
hide
|
|
| 25 | | | if (dirp == NULL) { |
Event 3:
Skipping " if". dirp == (void *)0 evaluates to false.
hide
|
|
| 26 | | | if (errno != ENOENT)
x /usr/include/asm-generic/errno-base.h |
| |
5 | #define ENOENT 2 /* No such file or directory */ |
| |
|
| 27 | | | i_error("opendir(%s) failed: %m", dir); |
| 28 | | | return -1; |
| 29 | | | } |
| 30 | | | |
| 31 | | | path = t_str_new(256); |
| 32 | | | str_printfa(path, "%s/", dir); |
| 33 | | | dir_len = str_len(path); |
| 34 | | | |
| 35 | | | prefix_len = strlen(prefix); |
| 36 | | | while ((d = readdir(dirp)) != NULL) { |
| 37 | | | if (d->d_name[0] == '.' && |
| 38 | | | (d->d_name[1] == '\0' || |
| 39 | | | (d->d_name[1] == '.' && d->d_name[2] == '\0'))) { |
| 40 | | | |
| 41 | | | continue; |
| 42 | | | } |
| 43 | | | if (strncmp(d->d_name, prefix, prefix_len) != 0) |
| 44 | | | continue; |
| 45 | | | |
| 46 | | | str_truncate(path, dir_len); |
| 47 | | | str_append(path, d->d_name); |
| 48 | | | if (stat(str_c(path), &st) < 0) { |
| 49 | | | if (errno != ENOENT)
x /usr/include/asm-generic/errno-base.h |
| |
5 | #define ENOENT 2 /* No such file or directory */ |
| |
|
| 50 | | | i_error("stat(%s) failed: %m", str_c(path)); |
| 51 | | | } else if (!S_ISDIR(st.st_mode) && st.st_ctime < min_time) {
x /usr/include/sys/stat.h |
| |
131 | #define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR) |
| |
x /usr/include/sys/stat.h |
| |
129 | #define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask)) |
| |
x /usr/include/bits/stat.h |
| |
182 | #define __S_IFMT 0170000 /* These bits determine file type. */ |
| |
x /usr/include/bits/stat.h |
| |
185 | #define __S_IFDIR 0040000 /* Directory. */ |
| |
x /usr/include/bits/stat.h |
| |
96 | # define st_ctime st_ctim.tv_sec |
| |
|
| 52 | | | if (unlink(str_c(path)) < 0 && errno != ENOENT)
x /usr/include/asm-generic/errno-base.h |
| |
5 | #define ENOENT 2 /* No such file or directory */ |
| |
|
| 53 | | | i_error("unlink(%s) failed: %m", str_c(path)); |
| 54 | | | } |
| 55 | | | } |
| 56 | | | |
| 57 | | | #ifdef HAVE_DIRFD |
| 58 | | | if (fstat(dirfd(dirp), &st) < 0) |
Event 6:
Taking false branch. fstat(dirfd(dirp), &st) < 0 evaluates to false.
hide
|
|
| 59 | | | i_error("fstat(%s) failed: %m", dir); |
| 60 | | | #else |
| 61 | | | if (stat(dir, &st) < 0) |
| 62 | | | i_error("stat(%s) failed: %m", dir); |
| 63 | | | #endif |
| 64 | | | else if (st.st_atime < ioloop_time) {
x /usr/include/bits/stat.h |
| |
94 | # define st_atime st_atim.tv_sec /* Backward compatibility. */ |
| |
|
Event 7:
Taking true branch. st.st_atim.tv_sec < ioloop_time evaluates to true.
hide
|
|
| 65 | | | |
| 66 | | | if (utime(dir, NULL) < 0 && errno != ENOENT)
x /usr/include/asm-generic/errno-base.h |
| |
5 | #define ENOENT 2 /* No such file or directory */ |
| |
|
Event 8:
dir is passed to utime() as the first argument.
hide
File System Race Condition
The file named dir is accessed again. Another process may have changed the file since the access at unlink-old-files.c:24. For example, an attacker could replace the original file with a link to a file containing important or confidential data. The issue can occur if the highlighted code executes. See related events 2 and 8. Show: All events | Only primary events |
|
| |