В качестве дополнительного вопроса к этому я подумал о другом подходе, основанном на ответе @ caf для случая, когда я хочу добавить в файл name
и создайте его, если он не существует.
Вот что я придумал:
- Создать временный каталог с режимом 0700 во системном временном каталоге в той же файловой системе, что и файл
name
.
- Открыть файл
name
только для чтения и O_CREAT
. ОС может следовать name
, если это символическая ссылка.
Используйте mkstemp
, чтобы создать временный файл во временном каталоге, и попытайтесь rename
временный файл. созданный mkstemp
для файла name
.
Открыть файл name
только для чтения и O_CREAT | O_EXCL
.
- Итеративная попытка сделать жесткую ссылку на
name
во временном имени во временном каталоге. Если когда-либо вызов link
завершится неудачно из-за ошибки, отличной от «цель ссылки существует» (errno EEXIST
), затем завершите работу. (Может быть, кто-то пришел и удалил файл на name
, кто знает?)
- Используйте
lstat
на temp_name
(жесткая ссылка). Если S_ISLNK(lst.st_mode)
, то выйдите.
open
temp_name
для написания и добавления (O_WRONLY | O_APPEND
).
- Выпиши все. Закройте дескриптор файла.
unlink
жесткая ссылка.
- Удалить временный каталог.
(Все это, кстати, относится к проекту с открытым исходным кодом , над которым я работаю. Вы можете посмотреть источник моей реализации этого подхода здесь .)
Безопасна ли эта процедура против атак по символическим ссылкам? Например, может ли злонамеренный процесс обеспечить, чтобы индекс для name
представлял обычный файл на время проверки lstat
, а затем сделать индекс символической ссылкой с temp_name
жесткая ссылка теперь указывает на новую символическую ссылку?
Я предполагаю, что вредоносный процесс не может повлиять на temp_name
.
EDIT: link
не перезаписывает цель, поэтому создание временного файла-заполнителя - это не то, что я хотел сделать. С тех пор я обновил свой код и обновил шаги, описанные выше.
EDIT2: Я сейчас использую альтернативную процедуру для шага 2 для создания файла name
, если он не существует, который, я не думаю, восприимчив к этой проблеме .
EDIT3: Даже лучше, чем переименование временного, пустого, обычного файла в name
, что также приводит к удалению ссылок name
, затем переименование, я могу открыть файл O_RDONLY | O_CREAT | O_EXCL
.
Стандарт POSIX для open
гласит:
Если установлены O_EXCL
и O_CREAT
и path
называет символическую ссылку, open()
завершится ошибкой и установит errno
в EEXIST
, независимо от содержимого символической ссылки.