Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Various minor fixes

...

Code Block
bgColor#FFCCCC
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:

  1. calling the lstat() on the filename.
  2. calling open() to open the file.
  3. calling fstat() on the file descriptor returned by open().
  4. comparing the file information returned by the calls to lstat() and fstat() to ensure that the files are the same.
Code Block
bgColor#ccccff
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]\].

...