标志O_DIRECTORY
可以与系统调用open(2)
和openat(2)
以避免打开目录时出现拒绝服务问题。 但是,如何避免常规文件的相同种族条件?
一些背景信息:我正在尝试开发某种备份工具。 程序遍历目录树,读取所有常规文件,只统计其他文件。 如果我首先为每个目录条目调用fstatat(2)
,那么testing一下普通文件的结果并用openat(2)
打开它们,系统调用之间就会出现争用情况。 攻击者可以使用FIFOreplace常规文件,而我的程序将挂在FIFO上。
我怎样才能避免这种竞争条件? 对于目录,有O_DIRECTORY
,对于符号链接,可以使用O_PATH
。 但是,我找不到常规文件的解决scheme。 我只需要一个适用于最新Linux版本的解决scheme。
如果你唯一的担心是fifos, O_NONBLOCK
将阻止阻止,并允许你打开一个前锋,即使它没有作家(见http://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html这是哪里指定)。 但是,还有一些其他的问题:
/proc
假文件具有不良属性 由于这些通常不能由非root用户在任意位置创建, O_NOFOLLOW
应该足以避免跟随它们的符号链接。
因此,在现代Linux上有一个更安全的解决方案:使用O_PATH|O_NOFOLLOW
执行初始open
,然后对/proc/self/fd/%d
执行stat
以检查文件类型。 然后你可以打开/proc/self/fd/%d
并完全确定它对应于你刚才stat
的同一个文件。
请注意,在足够新的Linux上,不需要使用/proc/self/fd/%d
来到达使用O_PATH
获取inode句柄的O_PATH
。 您可以直接使用fstat
和openat
来“stat”它,并分别获得一个描述符到一个真实的打开的文件描述。 然而, O_PATH
文件描述符在2.6.x后期(当它们第一次被添加时)的范围内有很多这样的错误/未实现的角落案例, O_PATH
3.8个,我发现/proc
方法是最可靠的。 当然,如果失败,你总是可以尝试直接的方法,并回退到/proc
。
使用O_RDONLY | O_NONBLOCK打开,检查结果是否为-1,然后在生成的文件描述符上执行fstat(),并将st_mode(以及可能的st_dev和st_ino)与预期值进行比较。
记得在你的fstatat上设置AT_SYMLINK_NOFOLLOW标志。