...
| 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)) {
if ((fd = open(filename, O_RDWR, 0600)) == -1) {
/* handle error */
}
}
write(fd, userbuf, userlen);
|
...
This compliant solution eliminates the race condition by:
- calling the
lstat() on the filename. - calling
open() to open the file. - calling
fstat() on the file descriptor returned by open(). - comparing the file information returned by the calls to
lstat() and fstat() to ensure that the files are the same.
| Code Block |
|---|
|
char *filename;
struct stat lstat_info, fstat_info;
int fd;
/* ... */
if (lstat(filename, &lstat_info) == -1) {
/* handle error */
}
if ((fd = open(filename, O_RDWR, 0600)) == -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);
}
|
| Wiki Markup |
|---|
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 {{fstatopen()}} does. Comparing modes using the {{st_mode}} field is sufficient to check for a symbolic link.
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()}} \[[FIO05-A. Identify files using multiple file attributes]\]. |
...