标记O_DIRECTORY
可与系统调用open(2)
和openat(2)
一起使用,以避免在打开目录时出现拒绝服务漏洞。但是:如何避免常规文件的相同竞争条件?
一些背景信息:我正在尝试开发某种备份工具。程序遍历目录树,读取所有常规文件,只读取其他文件的统计信息。如果我首先为每个目录条目调用fstatat(2)
,请测试常规文件的结果并使用openat(2)
打开它们,然后系统调用之间存在竞争条件。攻击者可以用FIFO替换常规文件,我的程序将挂在FIFO上。
我怎样才能避免这种竞争条件?对于目录,有O_DIRECTORY
,对于符号链接,可以使用O_PATH
。但是,我找不到常规文件的解决方案。我只需要一个适用于最新Linux版本的解决方案。
答案 0 :(得分:5)
如果您唯一的担心是fifos,O_NONBLOCK
将阻止阻止并允许您打开fifo,即使它没有编写者(请参阅http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html了解指定的位置)。但是,还有一些其他问题:
/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_PATH
和fstat
来“统计”它,并分别获得真实打开文件描述的描述符。但是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标志。