...
| Code Block | ||
|---|---|---|
| ||
char *filename;
char *userbuf;
unsigned int userlen;
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 */
}
}
if (write(fd, userbuf, userlen) < userlen); {
/* Handle Error */
}
|
This code contains a TOCTOU race condition 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).
...
| Code Block | ||
|---|---|---|
| ||
char *filename;
char *userbuf;
unsigned int userlen;
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) {
if (write(fd, userbuf, userlen); < userlen) {
/* Handle Error */
}
}
|
This eliminates the TOCTOU condition because fstat() is applied to file descriptors, not file names, so the file passed to fstat() must be identical to the file that was opened. The lstat() function does not follow symbolic links, but open() does. Comparing modes using the st_mode field is sufficient to check for a symbolic link.
...