2010-05-30 91 views
2

作为this one的后续问题,我想到了另一种方法,它构建了@ caf的答案,用于我想要附加到文件name的情况,并在不存在的情况下创建它。模拟O_NOFOLLOW(2):这种其他方法安全吗?

这里是我想出了:

  1. 在系统临时目录在同一文件系统的文件name创建模式0700的临时目录。
  2. 打开文件name只读和O_CREAT。如果它是符号链接,则操作系统可能会遵循name

    使用mkstemp在临时目录中创建一个临时文件,并尝试renamemkstemp创建的临时文件到name

    打开文件name仅供阅读和O_CREAT | O_EXCL
  3. 以临时目录中的临时名称迭代尝试建立到name的硬链接。如果由于除“链接目标存在”(错误号码EEXIST)之外的错误导致link呼叫失败,请退出。 (也许有人来过并删除了文件name,谁知道?)
  4. 使用lstattemp_name(硬链接)。如果S_ISLNK(lst.st_mode),则退出。
  5. opentemp_name写作&附加(O_WRONLY | O_APPEND)。
  6. 把一切写出来。关闭文件描述符。
  7. unlink硬链接。
  8. 删除临时目录。

(所有这一切,顺便说一下,是一个open source project是我的工作。你可以查看我的实现这种方法here的来源。)

这是程序安全对符号链接攻击?例如,是否有可能恶意进程确保name的inode代表lstat检查期间的常规文件,然后使inode成为指向新的符号链接的硬链接的符号链接?

我假设恶意进程不会影响temp_name

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

EDIT2:我现在使用的是备用程序步骤2中,如果不存在的话,我不认为是易受this problem创建文件name

EDIT3:比重命名一个临时的,空的,常规文件name,其中也有取消链接name然后重命名的效果更妙的是,我可以打开该文件O_RDONLY | O_CREAT | O_EXCL

open状态POSIX标准:

如果O_EXCLO_CREAT设置,并path名的符号链接,open()失败,将设置errnoEEXIST,不管符号链接的内容。

+0

您的最终POSIX引用看起来像一个答案。如果是这样,为什么不把它作为答案并接受它,所以这个问题不再显示为“未答复”? – 2010-08-08 04:59:38

+0

@ R。抱歉。我已经接受了我的回答。 – 2010-08-08 17:50:47

回答

0

那么,有一个问题,第2步(“打开文件name仅作O_CREAT读书。操作系统可以跟随name,如果它是一个符号链接。”),如果充分利用,可以允许非特权处理到基本touch文件系统中的任何路径。其后果包括强制磁盘检查下次重新启动(通过触摸/forcefsck)以及其他更具破坏性的事情。例如,在从Debian Lenny升级到Squeeze时,dbus和内核映像必须同时升级,因为每个相应的软件包都依赖于其他软件包(新的dbus不适用于旧的内核和旧的dbus不适用于新内核)。管理员绕过这种循环依赖的方式是通过touch指定一个特定路径,该路径通知新的dbus软件包在下次重新启动之前内核映像将被升级。但是,如果在从Lenny升级到Squeeze期间,第一次升级&重新启动之前恶意进程管理到touch该路径,则系统可能无法启动。如果我记得正确的话,第一次升级会安装新的dbus,但您必须重新升级才能安装新的内核映像。 其中一个升级,然后重新启动可能会导致系统崩溃。

通过source of GNU Coreutils' touch来看,似乎他们只设置文件的时间戳,但不创建文件,如果它不存在,当touch传递的--no-dereference选项。他们使用gnulib中的效用函数lutimens进行此操作,该函数包装Linux的utimensat,允许符号链接文件本身的时间戳(如果是这种情况)在Linux> = 2.6.22时更新。