c - 模拟O_NOFOLLOW (2) : Is this other approach safe?

标签 c security race-condition symlink

作为 this one 的后续问题,我想到了另一种方法,该方法基于@caf的答案,针对我想要附加到文件name并创建它(如果它不存在)的情况。

这是我的想法:

  1. 在与文件name相同的文件系统上的系统临时目录中创建模式为0700的临时目录。
  2. 以只读方式打开文件nameO_CREAT。如果是符号链接(symbolic link),操作系统可能会遵循 name

    使用 mkstemp 在临时目录并尝试将 mkstemp 创建的临时文件重命名为文件name

    以只读方式打开文件 nameO_CREAT | O_EXCL
  3. 反复尝试在临时目录中的临时名称处建立到 name 的硬链接(hard link)。如果有link由于“链接目标存在”(errno EEXIST) 之外的错误,调用失败,然后退出。 (也许有人已经删除了 name 处的文件,谁知道呢?)
  4. 使用lstattemp_name (硬链接(hard link))上。如果S_ISLNK(lst.st_mode),则退出。
  5. open temp_name 用于写入和附加 (O_WRONLY | O_APPEND)。
  6. 写下所有内容。关闭文件描述符。
  7. unlink硬链接(hard link)。
  8. 删除临时目录。

(顺便说一下,所有这些都是针对我正在开发的 open source project 的。您可以查看我实现此方法的源代码 here 。)

此过程可以安全地抵御符号链接(symbolic link)攻击吗?例如,恶意进程是否有可能确保 name 的 inode 代表 lstat 持续时间内的常规文件。检查,然后使 inode 成为符号链接(symbolic link),其中 temp_name 硬链接(hard link)现在指向新的符号链接(symbolic link)?

我假设恶意进程无法影响 temp_name

编辑: link不会覆盖目标,因此创建“占位符”临时文件不是我想要做的。我已经更新了我的代码并更新了上述步骤。

编辑2:我现在正在使用第2步的替代过程来创建文件name(如果它不存在),我认为这不会受到 this problem 的影响。 .

EDIT3: 甚至比将临时的、空的常规文件重命名为 name 更好,这也具有取消链接 name 的效果,< em>然后重命名,我可以打开文件O_RDONLY | O_CREAT | O_EXCL

open 的 POSIX 标准规定:

If O_EXCL and O_CREAT are set, and path names a symbolic link, open() shall fail and set errno to EEXIST, regardless of the contents of the symbolic link.

最佳答案

好吧,第 2 步有一个问题(“打开文件 name 仅供读取和 O_CREAT。操作系统可能会遵循 name,如果它是一个符号链接(symbolic link)。”)如果完全可利用,它可能允许非特权进程实质上触摸文件系统中的任何路径。这样做的后果包括在下次重新启动时强制进行磁盘检查(通过触摸 /forcefsck),以及其他更具破坏性的事情。例如,在从 Debian Lenny 升级到 Squeeze 时,dbus 和内核镜像都必须同时升级,因为每个相应的软件包都依赖于另一个软件包(新的 dbus 不能与旧内核一起工作,而旧的内核镜像则不能使用)。 dbus 不适用于新内核)。管理员解决此循环依赖关系的方法是通过touch特定路径,该路径通知新的 dbus 包内核镜像将在下次重新启动之前升级。但是,如果恶意进程在首次升级之前触及该路径,并在从 Lenny 升级到 Squeeze 期间重新启动,则系统可能无法启动。如果我没记错的话,第一次升级会安装新的 dbus,但是您必须再次显式升级才能安装新的内核镜像。 一次升级后重新启动可能会导致系统瘫痪。

浏览 source of GNU Coreutils' touch ,看起来他们只设置文件时间戳,但当 touch 传递 --no-dereference 选项时,如果文件不存在,则不会创建文件。他们使用实用函数 lutimens 来做到这一点。来自 gnulib,它包装了 Linux 的 utimensat ,允许符号链接(symbolic link)文件本身的时间戳(如果是这种情况)在 Linux >= 2.6.22 时更新。

关于c - 模拟O_NOFOLLOW (2) : Is this other approach safe?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2938563/

相关文章:

c - 链接列表的冒泡排序 请帮忙

c++ - 我们可以在 C++ 中使用 "FILE"吗?

c - 将字符串的 ASCII 值写入文件 C

security - ASP.NET MVC : Simple SQL Injection security

c# - 我怎样才能用监视器替换这个信号量?

java - 在单个后台线程定期修改 map 的同时读取 map

c - 如何在不交换数据的情况下交换两个节点

php - 简单安全问题: PHP Includes

c# - Windows 加密容器有多安全?

c++ - 将相同的值写入相同的内存位置会导致数据竞争吗?