版本

faccessat()在内核2.6.16中添加到Linux;库支持已添加到版本2.4中的glibc。

语法

#include <unistd.h>

int access(const char *pathname, int mode);

#include <fcntl.h>           /* Definition of AT_* constants */
#include <unistd.h>

int faccessat(int dirfd, const char *pathname, int mode, int flags);

glibc的功能测试宏要求(请参阅feature_test_macros(7)):

faccessat():

Since glibc 2.10:
_POSIX_C_SOURCE>= 200809L
Before glibc 2.10:
_ATFILE_SOURCE

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/

ACCESS - Linux手册页

Linux程序员手册 第2部分
更新日期: 2016-03-15

错误说明

在以下情况下,access()和faccessat()将失败:

EACCES
请求的访问将被拒绝,或者路径名路径前缀中的目录之一的搜索权限被拒绝。 (另请参见path_resolution(7)。)
ELOOP
解析路径名时遇到太多符号链接。
ENAMETOOLONG
路径名太长。
ENOENT
路径名的组件不存在或是悬挂的符号链接。
ENOTDIR
实际上,在路径名中用作目录的组件不是目录。
EROFS
请求了只读文件系统上文件的写许可权。

在以下情况下,access()和faccessat()可能会失败:

EFAULT
路径名指向您可访问的地址空间之外。
EINVAL
模式指定不正确。
EIO
发生I / O错误。
ENOMEM
内核内存不足。
ETXTBSY
已请求对正在执行的可执行文件进行写访问。

faccessat()可能会发生以下其他错误:

EBADF
dirfd不是有效的文件描述符。
EINVAL
标志中指定的标志无效。
ENOTDIR
pathname是相对的,dirfd是引用目录以外的文件的文件描述符。

返回值

成功(授予所有请求的权限,或者模式为F_OK且文件存在)时,返回零。发生错误时(模式中的至少一位请求被拒绝权限,或者模式为F_OK并且文件不存在,或者发生了其他错误),返回-1,并正确设置了errno。

遵循规范

access():SVr4、4.3BSD,POSIX.1-2001,POSIX.1-2008。

faccessat():POSIX.1-2008。

BUGS

在内核2.4(及更早版本)中,对于超级用户的X_OK测试处理有些奇怪。如果为非目录文件禁用了所有类别的执行权限,则唯一将模式指定为X_OK时返回-1的access()测试。如果还在mode中指定了R_OK或W_OK,则access()对于此类文件返回0。早期的2.6内核(直到2.6.3,包括2.6.3)也具有与内核2.4相同的行为。

在2.6.20之前的内核中,如果将MS_NOEXEC标志用于mount(2)基础文件系统,则这些调用将忽略其影响。从内核2.6.20开始,将保留MS_NOEXEC标志。

说明

access()检查调用进程是否可以访问文件路径名。如果路径名是符号链接,则将其取消引用。

该模式指定要执行的可访问性检查,并且为值F_OK或由R_OK,W_OK和X_OK中的一个或多个组成的掩码的掩码。 F_OK测试文件是否存在。 R_OK,W_OK和X_OK测试文件是否存在,并分别授予读取,写入和执行权限。

该检查是使用调用进程的实际UID和GID完成的,而不是像实际在文件上尝试执行操作(例如,open(2))那样执行的有效ID。同样,对于root用户,检查使用的是一组允许的功能,而不是有效的功能。对于非root用户,该检查使用一组空功能。

这允许设置用户ID程序和赋予功能的程序轻松确定调用用户的权限。换句话说,access()无法回答"我可以读取/写入/执行此文件吗?"题。它回答了一个稍有不同的问题:"(假设我是setuid二进制文件)调用我的用户可以读取/写入/执行此文件吗?",这使set-user-ID程序可以防止恶意用户导致它们出现。读取用户不应该读取的文件。

如果调用过程具有特权(即,其实际UID为零),则如果为文件所有者,组或其他文件所有者中的任何一个启用了执行权限,则对常规文件的X_OK检查成功。

faccessat()

除了此处描述的差异之外,faccessat()系统调用的操作与access()完全相同。

如果在路径名中给定的路径名​​是相对的,则它相对于文件描述符dirfd所引用的目录进行解释(而不是相对于调用进程的当前工作目录,如相对路径名的access()所做的那样) 。

如果路径名是相对的并且dirfd是特殊值AT_FDCWD,则路径名是相对于调用进程的当前工作目录(如access())解释的。

如果路径名是绝对的,则dirfd被忽略。

标志是通过对以下零个或多个值进行"或"运算来构造的:

AT_EACCESS
使用有效的用户和组ID执行访问检查。默认情况下,faccessat()使用真实ID(如access())。
AT_SYMLINK_NOFOLLOW
如果路径名是符号链接,请不要取消引用它:而是返回有关链接本身的信息。

有关对faccessat()的需求的说明,请参见openat(2)。

名称

access,faccessat-检查文件的用户权限

另外参见

chmod(2),chown(2),open(2),setgid(2),setuid(2),stat(2),euidaccess(3),凭据(7),path_resolution(7),symlink(7)

备注

警告:例如,在实际使用open(2)进行操作之前,使用这些调用检查用户是否被授权打开文件会创建安全漏洞,因为用户可能会利用检查和打开文件之间的较短时间间隔操纵它。因此,应避免使用该系统调用。 (在刚刚描述的示例中,一个更安全的选择是将进程的有效用户ID临时切换为真实ID,然后调用open(2)。)

access()始终取消引用符号链接。如果需要检查符号链接的权限,请使用带有标志AT_SYMLINK_NOFOLLOW的faccessat()。

如果拒绝任何模式下的访问类型,即使允许某些其他模式下的访问,这些调用也会返回错误。

如果调用进程具有适当的特权(即,是超级用户),则即使未设置任何执行文件许可权,POSIX.1-2001仍允许实现指示X_OK检查成功。 Linux不这样做。

仅当路径名的路径前缀中的每个目录的权限都授予搜索(即执行)访问权限时,文件才可访问。如果无法访问任何目录,则无论文件本身的权限如何,access()调用都会失败。

仅检查访问位,不检查文件类型或内容。因此,如果发现目录可写,则可能意味着可以在目录中创建文件,而不是可以将目录写为文件。类似地,可能会发现DOS文件是"可执行的",但是execve(2)调用仍将失败。

这些调用在启用了UID映射的NFSv2文件系统上可能无法正常工作,因为UID映射是在服务器上完成的,并从客户机中隐藏,这会检查权限。 (NFS版本3和更高版本在服务器上执行检查。)FUSE挂载也会发生类似的问题。

C library/kernel differences

原始faccessat()系统调用仅采用前三个参数。 AT_EACCESS和AT_SYMLINK_NOFOLLOW标志实际上是在faccessat()的glibc包装函数中实现的。如果指定了这些标志之一,则包装器函数将使用fstatat(2)确定访问权限。

Glibc notes

在不可用faccessat()的较旧内核上(并且当未指定AT_EACCESS和AT_SYMLINK_NOFOLLOW标志时),glibc包装器函数将转而使用access()。如果路径名是相对路径名,则glibc将基于/ proc / self / fd中与dirfd参数相对应的符号链接构造路径名。

日期:2019-08-20 17:58:34 来源:oir作者:oir