(/home/sate/Testcases/c/cve/dovecot-1.2.0/src/lib/unlink-directory.c) |
| |
| 44 | | | static int unlink_directory_r(const char *dir) |
| 45 | | | { |
| 46 | | | DIR *dirp; |
| 47 | | | struct dirent *d; |
| 48 | | | struct stat st; |
| 49 | | | int dir_fd, old_errno; |
| 50 | | | |
| 51 | | | #ifdef O_NOFOLLOW
x /usr/include/bits/fcntl.h |
| |
51 | # define O_NOFOLLOW 0400000 /* Do not follow links. */ |
| |
|
| 52 | | | dir_fd = open(dir, O_RDONLY | O_NOFOLLOW);
x /usr/include/bits/fcntl.h |
| |
51 | # define O_NOFOLLOW 0400000 /* Do not follow links. */ |
| |
|
| 53 | | | if (dir_fd == -1) |
Event 2:
Skipping " if". dir_fd == -1 evaluates to false.
hide
|
|
| 54 | | | return -1; |
| 55 | | | #else |
| 56 | | | struct stat st2; |
| 57 | | | |
| 58 | | | if (lstat(dir, &st) < 0) |
| 59 | | | return -1; |
| 60 | | | |
| 61 | | | if (!S_ISDIR(st.st_mode)) { |
| 62 | | | errno = ENOTDIR; |
| 63 | | | return -1; |
| 64 | | | } |
| 65 | | | |
| 66 | | | dir_fd = open(dir, O_RDONLY); |
| 67 | | | if (dir_fd == -1) |
| 68 | | | return -1; |
| 69 | | | |
| 70 | | | if (fstat(dir_fd, &st2) < 0) { |
| 71 | | | close_keep_errno(dir_fd); |
| 72 | | | return -1; |
| 73 | | | } |
| 74 | | | |
| 75 | | | if (st.st_ino != st2.st_ino || |
| 76 | | | !CMP_DEV_T(st.st_dev, st2.st_dev)) { |
| 77 | | | |
| 78 | | | (void)close(dir_fd); |
| 79 | | | errno = ENOTDIR; |
| 80 | | | return -1; |
| 81 | | | } |
| 82 | | | #endif |
| 83 | | | if (fchdir(dir_fd) < 0) { |
Event 3:
Skipping " if". fchdir(dir_fd) < 0 evaluates to false.
hide
|
|
| 84 | | | close_keep_errno(dir_fd); |
| 85 | | | return -1; |
| 86 | | | } |
| 87 | | | |
| 88 | | | dirp = opendir("."); |
| 89 | | | if (dirp == NULL) { |
Event 4:
Skipping " if". dirp == (void *)0 evaluates to false.
hide
|
|
| 90 | | | close_keep_errno(dir_fd); |
| 91 | | | return -1; |
| 92 | | | } |
| 93 | | | |
| 94 | | | errno = 0; |
| 95 | | | while ((d = readdir(dirp)) != NULL) { |
Event 6:
readdir64 is an Undefined Function.
hide
Event 7:
d is set to readdir(dirp).
hide
Event 8:
Entering loop body. (d = readdir(...)) != (void *)0 evaluates to true.
hide
|
|
| 96 | | | if (d->d_name[0] == '.' && |
Event 9:
Skipping " if". d->d_name[0] == 46 evaluates to false.
hide
|
|
| 97 | | | (d->d_name[1] == '\0' || |
| 98 | | | (d->d_name[1] == '.' && d->d_name[2] == '\0'))) { |
| 99 | | | |
| 100 | | | continue; |
| 101 | | | } |
| 102 | | | |
| 103 | | | if (unlink(d->d_name) < 0 && errno != ENOENT) {
x /usr/include/asm-generic/errno-base.h |
| |
5 | #define ENOENT 2 /* No such file or directory */ |
| |
|
Event 10:
d->d_name, which evaluates to readdir(dirp)->d_name from unlink-directory.c:95, is passed to unlink(). See related event 7.
hide
Event 11:
unlink() accesses the file named d->d_name, where d->d_name is readdir(dirp)->d_name from unlink-directory.c:95. - 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 10.
hide
|
|
| 104 | | | old_errno = errno; |
| 105 | | | |
| 106 | | | if (lstat(d->d_name, &st) < 0) { |
Event 13:
d->d_name, which evaluates to readdir(dirp)->d_name from unlink-directory.c:95, is passed to lstat64() as the first argument. See related event 7.
hide
File System Race Condition
The file named d->d_name is accessed again. Another process may have changed the file since the access at unlink-directory.c:103. 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 11 and 13. Show: All events | Only primary events |
|
| 107 | | | if (errno != ENOENT)
x /usr/include/asm-generic/errno-base.h |
| |
5 | #define ENOENT 2 /* No such file or directory */ |
| |
|
| 108 | | | break; |
| 109 | | | errno = 0; |
| 110 | | | } else if (S_ISDIR(st.st_mode)) {
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. */ |
| |
|
| 111 | | | if (unlink_directory_r(d->d_name) < 0) { |
| 112 | | | if (errno != ENOENT)
x /usr/include/asm-generic/errno-base.h |
| |
5 | #define ENOENT 2 /* No such file or directory */ |
| |
|
| 113 | | | break; |
| 114 | | | errno = 0; |
| 115 | | | } |
| 116 | | | if (fchdir(dir_fd) < 0) |
| 117 | | | break; |
| 118 | | | |
| 119 | | | if (rmdir(d->d_name) < 0) { |
| 120 | | | if (errno != ENOENT)
x /usr/include/asm-generic/errno-base.h |
| |
5 | #define ENOENT 2 /* No such file or directory */ |
| |
|
| 121 | | | break; |
| 122 | | | errno = 0; |
| |