...
If not properly performed, checking for the existence of symbolic links can lead to time-of-creation-to-time-of-use (TOCTOU) race conditions.
...
| Code Block | ||
|---|---|---|
| ||
char *filename;
struct stat lstat_info;
int fd;
/* ... */
if (lstat(filename, &lstat_info) == -1) {
/* handle error */
}
if (!S_ISLNK(lstat_info.st_mode)) {
fd = open(filename, O_RDWR);
if (fd == -1) {
/* handle error */
}
}
write(fd, userbuf, userlen);
|
This code contains a time of creation to time of use ( TOCTOU ) race condition betwen between the call to lstat() and the subsequent call to open() because both functions operate on a file name that can be manipulated asynchronously to the execution of the program (see FIO01-A. Be careful using functions that use file names for identification).
...
This compliant solution eliminates the race condition by:
- calling
lstat()on the file name. - calling
open()to open the file. - calling
fstat()on the file descriptor returned byopen(). - comparing the file information returned by the calls to
lstat()andfstat()to ensure that the files are the same.
| Code Block | ||
|---|---|---|
| ||
char *filename;
struct stat lstat_info
struct stat fstat_info;
int fd;
/* ... */
if (lstat(filename, &lstat_info) == -1) {
/* handle error */
}
fd = open(filename, O_RDWR);
if (fd == -1) {
/* handle error */
}
if (fstat(fd, &fstat_info) == -1) {
/* handle error */
}
if (lstat_info.st_mode == fstat_info.st_mode &&
lstat_info.st_ino == fstat_info.st_ino &&
lstat_info.st_dev == fstat_info.st_dev) {
write(fd, userbuf, userlen);
}
|
...
Comparing i-nodes using the st_ino fields and devices using the st_dev fields ensures that the file passed to lstat() is the same as the file passed to fstat() (see FIO05-A. Identify files using multiple file attributes).
Risk Assessment
Time-of-creation-to-time-of-use (TOCTOU) race condition vulnerabilities can be exploited to gain elevated privileges.
...