Rules / C/C++
SHIELD-CPP-018
TOCTOU race with access then open
What it detects
Checking permissions with access before open creates a time-of-check to time-of-use race.
How to fix
Open the file first and check permissions on the resulting descriptor with fstat.
Vulnerable — Shield flags thisspool.c
#include <unistd.h>
#include <fcntl.h>
int open_spool(void) {
if (access("/var/spool/report.out", W_OK) != 0) /* check */
return -1;
/* window here: the file can be swapped for a symlink */
return open("/var/spool/report.out", O_WRONLY); /* use */
}
Fixed — scans cleanspool.c
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
int open_spool(void) {
int fd = open("/var/spool/report.out", O_WRONLY | O_NOFOLLOW);
if (fd < 0)
return -1;
struct stat st; /* check the opened descriptor */
if (fstat(fd, &st) != 0 || !S_ISREG(st.st_mode)) {
close(fd);
return -1;
}
return fd;
}
Both snippets are verified against the shipped scanner: the vulnerable one triggers SHIELD-CPP-018, the fixed one does not.