作为这个问题的后续问题,我想到了另一种方法,它建立在@caf's answer的基础上,用于我想附加到文件name
并在它不存在时创建它的情况。
这是我想出的:
- 在与 file 相同的文件系统上的系统临时目录中创建一个模式为 0700 的临时目录
name
。 name
以只读方式打开文件和O_CREAT
.name
如果它是符号链接,则操作系统可能会跟随。用于在临时目录中创建临时文件,并尝试使用to file创建的临时文件。以只读方式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
在检查期间确保 inode for 代表常规文件lstat
,然后使 inode 成为符号链接,而temp_name
硬链接现在指向新的符号链接?
我假设恶意进程不会影响temp_name
.
编辑: link
不会覆盖目标,因此创建“占位符”临时文件不是我想要做的。我已经更新了我的代码并更新了上述步骤。
EDIT2:我现在使用步骤 2 的替代过程来创建文件name
,如果它不存在,我认为它不会受到这个问题的影响。
EDIT3:甚至比将临时的、空的、常规的文件重命名为name
,这也具有取消链接的效果name
,然后重命名,我可以打开文件O_RDONLY | O_CREAT | O_EXCL
。
状态的 POSIX 标准open
:
如果设置 和 并
O_EXCL
命名符号链接,则无论符号链接的内容如何,都将失败并设置为。O_CREAT
path
open()
errno
EEXIST