POSIX O_SEARCH与Linux目录O_PATH的语义差异及替代失效场景问询
O_PATH|O_DIRECTORY(Linux)的语义差异场景 权限检查逻辑不一致
POSIX的O_SEARCH要求调用者在open()时就拥有目标目录的搜索权限(即execute位权限),后续基于这个描述符的操作(比如用openat()打开子文件)不会再重复检查该目录的搜索权限。而Linux的O_PATH|O_DIRECTORY在open()时只检查目标是否为目录,不验证搜索权限,后续用该描述符操作时,会重新检查当前进程的权限,要是中途目录权限被修改,操作可能失败——这和O_SEARCH描述符的权限继承逻辑完全不同。子进程继承后的权限行为不同
按照POSIX规则,O_SEARCH描述符被子进程继承后,子进程仍能凭借它执行目录搜索操作,权限以父进程打开时的状态为准,不受子进程自身权限限制。但Linux的O_PATH描述符继承后,子进程用它操作时,会以自己的权限重新检查目录访问权限,不会沿用父进程打开时的权限设定。支持的系统操作范围不同
POSIX里的O_SEARCH描述符可以用于一些依赖目录搜索语义的操作,比如在部分兼容系统中,能结合fcntl()获取目录特定属性,或是用于某些同步类调用。但Linux的O_PATH只是个“位置指示器”,仅支持有限的文件描述符级操作(像fstat()、fchdir()、openat()),像readdir()这类需要目录搜索语义的调用就没法直接用它,必须额外以可读权限打开目录才行。符号链接处理逻辑不同
POSIX中用O_SEARCH打开指向目录的符号链接时,open()会自动跟随链接,验证对最终目录的搜索权限后,返回对应目标目录的描述符。但Linux的O_PATH|O_DIRECTORY如果打开的是符号链接,open()会直接失败——因为O_DIRECTORY要求目标本身是目录,而符号链接不算,必须手动处理符号链接或者加上O_NOFOLLOW,和O_SEARCH的默认行为完全不一样。错误触发时机不同
POSIX里要是调用者对目录没有搜索权限,用O_SEARCH调用open()会直接返回错误。但Linux用O_PATH|O_DIRECTORY打开目录时,哪怕调用者没搜索权限,只要路径存在且是目录,open()就会成功返回描述符,直到后续执行openat()这类操作时才会报错,错误触发时机被延后了。
内容的提问来源于stack exchange,提问作者zwol

