模拟O_NOFOLLOW(2):这种方法安全吗?

时间:2010-05-30 12:17:24

标签: c security race-condition symlink

作为this one的后续问题,我想到了另一种方法,该方法建立在@cac的答案之后,我希望将追加添加到文件name并且如果它不存在则创建它。

以下是我提出的建议:

  1. 在与文件name相同的文件系统上的系统临时目录中创建模式为0700的临时目录。
  2. 打开文件name仅供阅读和O_CREAT。如果操作系统是符号链接,则操作系统可以跟name

    使用mkstemp在临时目录中创建临时文件并尝试{ {1}} rename创建的mkstemp文件的临时文件。

    打开文件name仅供阅读{{1 }}。
  3. 迭代尝试在临时目录中以临时名称与name建立硬链接。如果link调用由于“链接目标存在”(错误O_CREAT | O_EXCL)之外的错误而失败,则退出。 (也许有人出现并删除name的文件,谁知道?)
  4. EEXIST(硬链接)上使用lstat。如果是name,请退出。
  5. open temp_name用于写作&追加(S_ISLNK(lst.st_mode))。
  6. 写出一切。关闭文件描述符。
  7. unlink硬链接。
  8. 删除临时目录。
  9. (顺便说一句,所有这些都适用于我正在处理的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标准:

      

    如果设置了nameO_RDONLY | O_CREAT | O_EXCL,并且open指定了符号链接,则O_EXCL将失败并将O_CREAT设置为path,无论符号链接的内容如何。

1 个答案:

答案 0 :(得分:1)

嗯,第2步有一个问题(“只读取打开文件nameO_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。