根据UNIX环境中的高级编程,openat()提供了一种避免使用时间检查(TOCTTOU)错误的方法.
我对如何感到困惑.据我所知,openat依赖于文件描述符,所以需要首先打开这个文件描述符 - 这会引入TOCTTOU吗?
POSIX规范openat()说:
int openat(intfd, const char *path, intoflag, ...);[......常规的冗长
open()...]除了指定相对路径的情况外,该
openat()函数应等效于open()函数path.在这种情况下,要打开的文件是相对于与文件描述符相关联的目录fd而不是当前工作目录确定的.如果没有打开文件描述符O_SEARCH,该函数将使用文件描述符下的目录的当前权限检查是否允许目录搜索.如果打开文件描述符O_SEARCH,则该函数不应执行检查.的
oflag参数和可选的第四个参数精确地对应于的参数open().如果在参数中
openat()传递了特殊值AT_FDCWD,fd则应使用当前工作目录,并且行为应与调用相同open().
这意味着,如果要将文件放在特定目录中或相对于特定目录,可以打开该目录的文件描述符(可能带有该O_SEARCH选项),然后在openat()系统调用中指定相对于该目录的路径名.
其他*at()功能如fstatat()工作类似.
首先,请注意文件描述符是目录的文件描述符.在打开目录(用于读取)时,它存在,并且进程有权访问目录及其中的文件.此外,由于此进程打开了目录,因此在该进程关闭目录文件描述符之前,对该目录的最后引用不会消失.如果它位于已安装的文件系统上,则在程序终止之前无法卸载该文件系统(因为该进程已打开目录).如果移动目录(在同一文件系统上),则将继续相对于该目录在文件系统中的当前位置创建文件.
从这里开始,事情变得更加投机 - 我还没有正式测试这些观察结果.
即使删除了目录,您仍然可以创建相对于它的文件.如果名称是简单名称("new_file"或"./new_file"),那应该没问题.如果名称包含更多路径("subdir/new_file"),则如果已删除目录,则创建或打开文件将失败,因为所有子目录也将被删除.
当然,还有mkdirat()创建子目录的方法.
据推测,文件系统必须在所有这些之后进行清理,这可能非常复杂.这意味着实际上您无法在具有打开文件描述符但已删除其名称的目录中创建文件.但是,您会知道这不再可能,而不是假设它是同一个目录.
无论哪种方式,攻击者都很难将您的程序混淆在错误的目录中创建文件,只要您在使用正确的*at()函数时一直小心和一致.
删除了一组TOCTOU攻击; 那些依赖于重命名目录(或可能被删除)并且使用新名称(例如符号链接到某个其他位置)的攻击被挫败,因为文件继续相对于原始目录创建,而不是使用重命名或替换目录.
POSIX规范的基本原理部分openat()说:
该
openat()功能的目的是在不暴露竞争条件的情况下启用当前工作目录以外的目录中的文件.文件路径的任何部分都可以与调用并行更改open(),从而导致未指定的行为.通过打开目标目录的文件描述符并使用该openat()函数,可以保证打开的文件相对于所需目录.一些实现也将该openat()功能用于其他目的.在某些情况下,如果oflag参数O_XATTR设置了位,则返回的文件描述符提供对扩展属性的访问.此功能在此处未标准化.
| 归档时间: |
|
| 查看次数: |
561 次 |
| 最近记录: |