ACCESS - Linux手册页
Linux程序员手册 第2部分
更新日期: 2016-03-15
名称
access,faccessat-检查文件的用户权限
语法
#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
说明
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)。
返回值
成功(授予所有请求的权限,或者模式为F_OK且文件存在)时,返回零。发生错误时(模式中的至少一位请求被拒绝权限,或者模式为F_OK并且文件不存在,或者发生了其他错误),返回-1,并正确设置了errno。
错误说明
在以下情况下,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是引用目录以外的文件的文件描述符。
版本
faccessat()在内核2.6.16中添加到Linux;库支持已添加到版本2.4中的glibc。
遵循规范
access():SVr4、4.3BSD,POSIX.1-2001,POSIX.1-2008。
faccessat():POSIX.1-2008。
备注
警告:例如,在实际使用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参数相对应的符号链接构造路径名。
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标志。
另外参见
chmod(2),chown(2),open(2),setgid(2),setuid(2),stat(2),euidaccess(3),凭据(7),path_resolution(7),symlink(7)
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。