我们知道内核校验文件的访问权限使用的是进程的有效用户 ID 和有效组 ID。但有时我们需要知道当前登录用户对某个文件访问权限。虽然说进程的有效用户 ID 和有效组 ID 通常分别等于当前登录用户 ID 和用户所在组 ID。例如,一个进程可能因设置用户 ID 以另一个用户权限运行,它仍可能想验证当前实际登录的用户是否能否访问一个给定的文件。
access与faccessat 函数提供了按照实际用户 ID 和实际组 ID 进行访问权限测试的功能。
#include <unistd.h> int access(const char *pathname, int mode); int faccessat(int fd, const char *pathname, int mode, int flag); //Both return: 0 if OK, −1 on error
access 函数的 mode 常量,取自 <unistd.h>
mode | 说明 |
R_OK | 测试读权限 |
W_OK | 测试写权限 |
X_OK | 测试执行权限 |
F_OK | 测试文件是否存在 |
举个例子来展示access函数的使用方法:
#include "apue.h" #include <fcntl.h> int main(int argc, char **argv) { if(argc != 2) err_quit("usage: a.out <pathname>"); if(access(argv[1], R_OK) < 0) err_ret("access error for %s", argv[1]); else printf("read access OK\n"); if(open(argv[1], O_RDONLY) < 0) err_ret("open error for %s", argv[1]); else printf("open for reading OK\n"); exit(0); }
运行结果如下:
u@ubuntu:~/opt/Cproject/apue/cp1$ gcc error.c accessfun.c -o a.out
wu@ubuntu:~/opt/Cproject/apue/cp1$ ls -l a.out
-rwxrwxr-x 1 wu wu 8106 Mar 7 23:39 a.out
wu@ubuntu:~/opt/Cproject/apue/cp1$ ./a.out a.out
read access OK
open for reading OK
wu@ubuntu:~/opt/Cproject/apue/cp1$ ls -l /etc/shadow
-rw-r—– 1 root shadow 1057 Nov 6 03:03 /etc/shadow
wu@ubuntu:~/opt/Cproject/apue/cp1$ ./a.out /etc/shadow
access error for /etc/shadow: Permission denied
open error for /etc/shadow: Permission denied
wu@ubuntu:~/opt/Cproject/apue/cp1$ sudo su
[sudo] password for wu:
root@ubuntu:/home/wu/opt/Cproject/apue/cp1# chown root a.out
root@ubuntu:/home/wu/opt/Cproject/apue/cp1# chmod u+s a.out
root@ubuntu:/home/wu/opt/Cproject/apue/cp1# ls -l a.out
-rwsrwxr-x 1 root wu 8106 Mar 7 23:39 a.out
root@ubuntu:/home/wu/opt/Cproject/apue/cp1# exit
exit
wu@ubuntu:~/opt/Cproject/apue/cp1$ ./a.out /etc/shadow
access error for /etc/shadow: Permission denied
open for reading OK
对运行结果解释如下:
1. 起先,文件 a.out 的所有者是 wu(当前登录用户),运行./a.out a.out时,进程的实际用户和有效用户都是wu,则 access 函数和 open 函数都能够成功。
2. 文件/etc/shadow 的所有者是 root,且其只允许 root 用户读取。此时运行./a.out /etc/shadow,进程的实际用户的有效用户都是 wu,则 access 函数和 open 函数都失败了。
3. 切换后超级用户 root,将文件 a.out 的所有者修改为超级用户root(运行命令chown root a.out ,并设置文件 a.out 的设置用户 ID 位(运行命令chmod u+s a.out )。
4. 切换后当前登录用户 wu,此时运行./a.out /etc/shadow,进程的实际用户为 wu,但有效用户为超级用户 root(因文件a.out 的所有者为 root 且设置了设置用户 ID 位)。此时 access函数校验当前登录用户 wu 对文件/etc/shadow 读权限失败,但open 函数却能够打开文件/etc/shadow(内核用进程的有效用户 ID进行访问权限校验)。
Comments