Was ist ein guter Weg, O_NOFOLLOW auf Systeme ohne diese Flagge zu simulieren?
-
04-10-2019 - |
Frage
Ich möchte sicher mit open
und O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW
auf Systeme zu simulieren O_CREAT | O_WRONLY | O_APPEND | O_NOFOLLOW
der Lage sein, die keine Unterstützung O_NOFOLLOW
tun. Ich kann etwas erreichen, was ich frage für mit:
struct stat lst;
if (lstat(filename, &lst) != -1 && S_ISLNK(lst.st_mode)) {
errno = ELOOP;
return -1;
}
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW, mode);
aber dann stelle ich eine Race-Bedingung und möglicherweise ein Sicherheitsproblem.
Ich dachte vielleicht eine Dummy-Datei erstellen mit nur dem Benutzer zu schreiben in der Lage, die Art wie touch
filename
ing, tut der lstat
Prüfung und dann chmod
verwenden, nachdem ich fertig zu schreiben (die Datei Modusbits zu korrigieren), aber ich mit Blick auf etwas Großes werden könnte (existiert zB wenn die Datei bei filename
, keine reguläre Datei ist, oder ist bereits ein symbolischer Link).
Was denken Sie?
Lösung
Your proposal still has a race condition:
- Mallory creates the link he wants you to follow;
- You
open()
the link withO_CREAT
; - Mallory replaces the link with a regular file;
- You do your
lstat()
test, which passes (not a link); - Mallory replaces the regular file with the link again.
You can fix this for the non-O_TRUNC
case by calling fstat()
on your open file descriptor as well as lstat()
on the path, and ensuring that the .st_dev
and .st_ino
members are the same.
However, this doesn't work if you're using O_TRUNC
- by the time you've discovered the deception, it's too late - Mallory has already induced you to truncate one of your important files.
I believe the traditional way to eliminate the hole without O_NOFOLLOW
support is:
- Create a temporary directory with mode
700
. Error (or retry) ifmkdir()
fails due to existing directory; - Create your new file within the temporary directory;
- Use
rename()
to atomically move the temporary file to the target name; - Remove the temporary directory.