I was reading: https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use
They showed this code to be buggy and I totally understand why it's so:
if (access("file", W_OK) != 0) {
exit(1);
}
// Attacker: symlink("/etc/passwd", "file");
fd = open("file", O_WRONLY);
// Actually writing over /etc/passwd
write(fd, buffer, sizeof(buffer));
But the real question is how to protect against this type of exploits?
CodePudding user response:
You can use the O_NOFOLLOW
flag. It will cause the open
to fail if basename
of the path is a symbolic link. That would solve the described attack.
To cover links along the directory path, you can check whether frealpath(fd, ...)
matches what you would expect.
Another way to prevent a process from overwriting /etc/passwd
is to run it as non-root so that it won't have permission. Or, you can use chroot - or more generally, a container - to prevent the host system's /etc/passwd
being visible to the process.
More generally though, filesystem TOCTOU is unsolvable at the moment on Linux. You would need transaction support either on filesystem or system call level - which are lacking.
CodePudding user response:
There is no failproof solution.
Be also aware of Rice's theorem. It might be relevant.
But you could adopt a system wide convention (and document it) that every program accessing a given file is using locking facilities like flock(2).