A static-analysis tool (Coverity) flags the unlink()
statement in the following code as having a time-of-check/time-of-use (TOCTOU) problem between the access()
and unlink()
:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
void del(const char* file) {
if (! file) { return; }
{
struct stat ss;
if (stat(file, &ss)) { return; }
if (! S_ISREG(ss.st_mode)) { return; }
if (ss.st_uid != getuid()) { return; }
if (access(file, W_OK)) { return; }
unlink(file);
}
}
int main(int argc, char* argv[]) {
const char* file = "./foo.txt";
int fd = open(file, O_WRONLY | O_CREAT);
close(fd);
del(file);
return 0;
}
Is it flagging the possibility that between the call to access()
and unlink()
, any other process on the device can come along and change the target file's permissions, so that the unlink()
fails?
Is there a way that this situation can be handled to avoid the TOCTOU?
I'm at a loss how to "lock" the file for exclusive deletion-privilege by the current process.
TBH, I don't think I've seen code before that goes to these lengths to check if it's "okay" to delete a file -- most code of this sort that I've encountered just unconditionally call unlink()
and move on. :)