作为this one的后续问题,我想到了另一种方法,该方法建立在@cac的答案之后,我希望将追加添加到文件name
并且如果它不存在则创建它。
以下是我提出的建议:
name
相同的文件系统上的系统临时目录中创建模式为0700的临时目录。name
仅供阅读和O_CREAT
。如果操作系统是符号链接,则操作系统可以跟name
。mkstemp
在临时目录中创建临时文件并尝试{ {1}} rename
创建的mkstemp
文件的临时文件。name
仅供阅读{{1 }}。name
建立硬链接。如果link
调用由于“链接目标存在”(错误O_CREAT | O_EXCL
)之外的错误而失败,则退出。 (也许有人出现并删除name
的文件,谁知道?)EEXIST
(硬链接)上使用lstat
。如果是name
,请退出。open
temp_name
用于写作&追加(S_ISLNK(lst.st_mode)
)。unlink
硬链接。(顺便说一句,所有这些都适用于我正在处理的open source project。您可以查看我执行此方法的来源here。)
此程序是否可以安全抵御符号链接攻击?例如,恶意进程是否有可能确保temp_name
的inode在lstat
检查期间表示常规文件,然后使inode成为{{1}的符号链接现在指向新的符号链接的硬链接?
我假设恶意进程不会影响O_WRONLY | O_APPEND
。
编辑: link
不会覆盖目标,因此创建“占位符”临时文件不是我想要做的。我已经更新了我的代码并更新了上述步骤。
EDIT2:我现在正在使用第2步的备用程序来创建文件name
,如果它不存在,我认为不会对this problem敏感。< / p>
EDIT3:甚至比将临时空的常规文件重命名为temp_name
更好,这也会导致取消关联temp_name
,然后重命名,我可以打开文件name
。
name
州的POSIX标准:
如果设置了
name
和O_RDONLY | O_CREAT | O_EXCL
,并且open
指定了符号链接,则O_EXCL
将失败并将O_CREAT
设置为path
,无论符号链接的内容如何。
答案 0 :(得分:1)
嗯,第2步有一个问题(“只读取打开文件name
和O_CREAT
。如果是符号链接,操作系统可能会跟name
。” ,如果完全可利用,可以允许非特权进程基本上touch
文件系统中的任何路径。其后果包括在下次重启(通过触摸/forcefsck
)以及其他更具破坏性的事情时强制执行磁盘检查。例如,在从Debian Lenny升级到Squeeze时,必须同时升级dbus和内核映像,因为每个相应的包依赖于另一个(新的dbus不能与旧内核和旧内核一起使用) dbus不适用于新内核)。管理员绕过此循环依赖关系的方式是touch
一个特定的路径,该路径通知新的dbus包,在下次重新启动之前将升级内核映像。但是,如果恶意进程在第一次升级之前设法touch
该路径,那么从Lenny升级到Squeeze期间重启,系统可能无法启动。第一次升级,如果我没记错的话,安装新的dbus,但你必须再次显式升级才能安装新的内核映像。 一次升级,然后重新启动可能会破坏系统。
查看source of GNU Coreutils' touch
,它们似乎只设置了文件时间戳,但是如果touch
传递--no-dereference
选项,则不创建文件(如果该文件不存在)。他们使用来自gnulib的实用程序函数lutimens
执行此操作,该函数函数包装了Linux的utimensat
,允许符号链接文件本身的时间戳(如果是这种情况)在Linux&gt; = 2.6时更新0.22。