如何在没有拒绝服务漏洞的情况下安全地打开常规文件?

时间:2013-12-18 19:24:40

标签: c linux filesystems

标记O_DIRECTORY可与系统调用open(2)openat(2)一起使用,以避免在打开目录时出现拒绝服务漏洞。但是:如何避免常规文件的相同竞争条件?

一些背景信息:我正在尝试开发某种备份工具。程序遍历目录树,读取所有常规文件,只读取其他文件的统计信息。如果我首先为每个目录条目调用fstatat(2),请测试常规文件的结果并使用openat(2)打开它们,然后系统调用之间存在竞争条件。攻击者可以用FIFO替换常规文件,我的程序将挂在FIFO上。

我怎样才能避免这种竞争条件?对于目录,有O_DIRECTORY,对于符号链接,可以使用O_PATH。但是,我找不到常规文件的解决方案。我只需要一个适用于最新Linux版本的解决方案。

2 个答案:

答案 0 :(得分:5)

如果您唯一的担心是fifos,O_NONBLOCK将阻止阻止并允许您打开fifo,即使它没有编写者(请参阅http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html了解指定的位置)。但是,还有一些其他问题:

  • 设备节点
  • Linux /proc中的虚假文件
  • ...

由于非root用户通常无法在任意位置创建这些内容,因此O_NOFOLLOW应足以避免对其进行符号链接。

话虽如此,在现代Linux上有一个更安全的解决方案:使用open执行初始O_PATH|O_NOFOLLOW,然后在{{1}上执行stat检查文件类型。然后,您可以打开/proc/self/fd/%d并完全确定它与您/proc/self/fd/%d'的同一文件相对应。

请注意,在足够新的Linux上,您无需使用stat来访问使用/proc/self/fd/%d获取inode句柄的文件。您可以直接使用O_PATHfstat来“统计”它,并分别获得真实打开文件描述的描述符。但是openat文件描述符在2.6.x后期(当它们第一次添加时)的范围内有很多这样的破坏/未实现的角点情况,大概是3.8左右,我找到了O_PATH方法最可靠的。当然,如果失败,你总是可以尝试直接方法并回退到/proc

答案 1 :(得分:2)

使用O_RDONLY | O_NONBLOCK打开,检查结果是否为-1,然后对生成的文件描述符执行fstat(),并将st_mode(可能还有st_dev和st_ino)与预期进行比较。

请记住在fstatat上设置AT_SYMLINK_NOFOLLOW标志。