欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于Linux文件访问权限与设置用户id位

程序员文章站 2022-06-10 12:37:15
...

      最近在学习《Unix 高级环境编程》这边书,之前对Unix中的文件访问还有和文件访问相关的设置用户id(set_user_ID)位以及设置组id(set-group-ID)位一直没有弄清楚,今天跟他人讨论一个问题,终于有些明白了,记录以供温故。

       首先说说文件的权限控制位,每一个文件都有文件模式字st_mode,ls -l一个文件前面10位就是文件的类型和权限说明了。具体可分为用户读写可执行,组读写执行,其他读写执行位。当一个进程要访问某个文件的时候,会以进程的有效用户ID来进行权限检测,看改用户ID具体属于文件的哪个部分,是文件用户本身,还是属于用户组还是属于其他用户的。与每个进程相关联的用户ID和组ID包括实际用户(实际上是谁),ID实际组ID;有效用户ID(用于文件访问权限检查),有效组ID,附加组ID(有时候一个用户可能属于多个组);保存的设置用户ID(由exec函数保存),保存的设置组ID。所有者ID是文件的性质,而有效ID和附加组ID是进程的性质。一般内核进行的检测是:

        (1)若进程的有效用户ID是0(超级用户),则允许访问。

        (2)若进程的有效用户ID等于文件的所有者ID(即进程拥有此文件),那么当所有者适当的访问权限位被设置,则允许访问,否则拒绝访问。适当的访问权限位指的是,若进程为读而打开该文件,则用户读位应为1,若进程为写而打开该文件,则用户的写位应为1。。。

        (3)若进程的有效用户ID或进程的附加组ID之一等于文件的组ID,那么:若组的适当的访问权限位被设置,则允许访问,否则拒绝访问。

        (4)若其他用户适当的访问权限位被设置,则允许访问,否则拒绝访问。

        按顺序执行这四步,若进程拥有此文件(第2步),则按用户访问权限批准或拒绝该进程对文件的访问,不查看组访问权限。类似地,若进程并不拥有该文件,但进程属于某一个适当的组,则按组访问权限批准或者拒绝该进程对文件的访问,不查看其他用户的访问权限。当进程既不拥有该文件,进程也不属于某个组,就只能查看其他用户的访问权限了。

        当执行一个程序文件时,进程的有效用户ID通常就是实际用户ID,有效组ID通常就是实际组ID。但是当文件设置了用户ID位后,当执行此文件时,将进程的有效用户ID设置为文件所有者的用户ID(st_uid),设置组ID类似。下面将以一个例子来具体说明,其中access函数是按照实际用户ID和实际组ID进行访问权限测试的,open函数打开一个文件事,内核以进城的有效用户ID和有效组ID为基础进行权限测试。

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);
}

 编译生成可执行文件a.out并执行:

chardliu@ubuntu:~/apue.2e/file$ cc access.c

chardliu@ubuntu:~/apue.2e/file$ ls -l a.out
-rwxrwxr-x 1 chardliu chardliu 7839 Jun 26 21:01 a.out
chardliu@ubuntu:~/apue.2e/file$ ./a.out a.out
read access OK
open for reading OK

root@ubuntu:/home/chardliu/apue.2e/file# ll /etc/shadow
-r-------- 1 root shadow 1235 Apr 11 18:50 /etc/shadow

chardliu@ubuntu:~/apue.2e/file$ ./a.out /etc/shadow
access error for /etc/shadow: Permission denied
open error for /etc/shadow: Permission denied

此时之所以access和open都出错,是因为进程的实际用户ID和有效用户ID都为chardliu,而shadow文件的用户所有者是root,所以当进程以chardliu身份来对shadow文件进行访问权限检测时,是根据shadow的其他用户读写执行位来检测的,由上可知,shadow文件只有所有者root本身可读,没有其他任何权限。

按理,那么当给shadow文件增加其他用户读权限后access和open都应该成功,测试一下果真如此:

chardliu@ubuntu:~/apue.2e/file$ su  //以root用户对shadow文件进行权限设置
Password:
root@ubuntu:/home/chardliu/apue.2e/file# chmod o+r /etc/shadow        //给shadow增加其他用户可读权限
root@ubuntu:/home/chardliu/apue.2e/file# exit
exit
chardliu@ubuntu:~/apue.2e/file$ ll /etc/shadow
-r-----r-- 1 root shadow 1235 Apr 11 18:50 /etc/shadow
chardliu@ubuntu:~/apue.2e/file$ ./a.out /etc/shadow         //再次访问shadow文件,OK
read access OK
open for reading OK

 

下面说明一下设置用户ID的作用。

在此之前还是将shadow的文件访问控制位置为原来的,即清除其他用户可读权限,同时将a.out可执行文件的所有者改为root,并且设置其用户ID位:

chardliu@ubuntu:~/apue.2e/file$ su
Password:
root@ubuntu:/home/chardliu/apue.2e/file# chmod o-r /etc/shadow
root@ubuntu:/home/chardliu/apue.2e/file# ll /etc/shadow
-r-------- 1 root shadow 1235 Apr 11 18:50 /etc/shadow

root@ubuntu:/home/chardliu/apue.2e/file# chown root a.out
root@ubuntu:/home/chardliu/apue.2e/file# chmod u+s a.out
root@ubuntu:/home/chardliu/apue.2e/file# ll a.out
-rwsrwxr-x 1 root chardliu 7839 Jun 26 21:01 a.out*

退出超级用户,以正常用户运行:

root@ubuntu:/home/chardliu/apue.2e/file# exit
exit
chardliu@ubuntu:~/apue.2e/file$ ./a.out /etc/shadow
access error for /etc/shadow: Permission denied
open for reading OK
会发现运行结果access失败,而打开文件成功。access是以实际用户IDchardliu对shadow进行访问权限检测的,发现其他用户读没有设置权限,所以失败;a.out设置了用户ID,所以当进程执行a.out时,进程的有效用户ID由chardliu设置为了a.out所有者的用户ID root了,所以可以成功打开文件,open是以进程的有效用户ID进行访问权限检测的。

通过这个过程,相信会对文件的访问权限控制有一个比较清晰的理解。

参考资料:W.Richard Stevens, Stephen A.Rago《UNIX环境高级编程》