3

作为这个问题的后续问题,我想到了另一种方法,它建立在@caf's answer的基础上,用于我想附加到文件name并在它不存在时创建它的情况。

这是我想出的:

  1. 在与 file 相同的文件系统上的系统临时目录中创建一个模式为 0700 的临时目录name
  2. name以只读方式打开文件和O_CREAT. name如果它是符号链接,则操作系统可能会跟随。用于在临时目录中创建临时文件,并尝试

    使用to file创建的临时文件。mkstemprenamemkstempname以只读方式

    打开文件和.nameO_CREAT | O_EXCL
  3. 反复尝试对name临时目录中的临时名称进行硬链接。如果link由于“链接目标存在”(errno)以外的错误而导致调用失败EEXIST,则退出。(也许有人过来并删除了 的文件name,谁知道?)
  4. lstattemp_name(硬链接)上使用。如果S_ISLNK(lst.st_mode),则退出。
  5. open temp_name用于编写和附加 ( O_WRONLY | O_APPEND)。
  6. 把一切都写出来。关闭文件描述符。
  7. unlink硬链接。
  8. 删除临时目录。

(顺便说一下,所有这些都是针对我正在开发的一个开源项目。您可以在此处查看我实施这种方法的源代码。)

这个过程对符号链接攻击安全吗?例如,恶意进程是否有可能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_CREATpathopen()errnoEEXIST

4

1 回答 1

1

好吧,第 2 步存在一个问题(“打开文件name以进行只读和.如果它是符号链接,则O_CREAT操作系统可能会跟随。”)如果完全可利用,则可以允许非特权进程基本上进入文件系统中的任何路径。这样做的后果包括在下次重新启动时强制进行磁盘检查(通过触摸),以及其他更具破坏性的事情。例如,在从 Debian Lenny 升级到 Squeeze 时,dbus 和内核映像都必须同时升级,因为每个相应的包都依赖于另一个(新的 dbus 不适用于旧内核和旧内核) dbus 不适用于新内核)。管理员绕过这种循环依赖的方式是nametouch/forcefscktouch设置一个特定的路径,通知新的 dbus 包内核映像将在下次重新启动之前升级。但是,如果在从 Lenny 升级到 Squeeze 期间第一次升级和重新启动之前,恶意进程设法进入touch该路径,则系统可能无法启动。如果我没记错的话,第一次升级会安装新的 dbus,但您必须再次显式升级才能安装新的内核映像。一次升级然后重新启动可能会使系统变砖。

查看GNU Coreutils' 的源代码touch,他们似乎只设置文件时间戳,但如果文件不存在则不创建文件,何时touch传递--no-dereference选项。他们使用lutimens来自 gnulib 的实用程序函数来执行此操作,该函数包装了 Linux 的utimensat.,允许符号链接文件本身的时间戳(如果是这种情况)在 Linux >= 2.6.22 时更新。

于 2010-05-31T12:17:09.547 回答