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

nos*_*sid 4 c linux filesystems

该标志O_DIRECTORY可以与系统调用中使用open(2)openat(2)打开的目录时避免拒绝服务漏洞.但是:如何避免常规文件的相同竞争条件?

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

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

R..*_*R.. 6

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

  • 设备节点
  • Linux中的伪文件/proc具有错误的属性
  • ...

由于这些通常不能由非root用户在任意位置创建,因此O_NOFOLLOW应该足以避免对它们进行符号链接.

随着中说,在现代的Linux有一个更安全的解决方案:执行初始openO_PATH|O_NOFOLLOW,然后执行stat/proc/self/fd/%d检查文件类型.然后/proc/self/fd/%d,您可以打开并完全确定它对应于您刚刚使用的同一文件stat.

请注意,在足够新的Linux上,您无需使用它/proc/self/fd/%d来访问您获得inode句柄的文件O_PATH.你可以用fstatopenat分别,并得到一个描述符,以一个真正的开放文件描述,就可以直接到"STAT".然而,O_PATH文件描述符在2.6.x后期(当它们第一次添加时)的范围内有很多这样的破碎/未实现的角落情况,大概是3.8左右,我觉得这种/proc方法最可靠.当然,/proc如果失败,你总是可以尝试直接方法和回退.