文件权限
Posted songdechiu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了文件权限相关的知识,希望对你有一定的参考价值。
一、文件信息结构
图1 文件信息结构stat
与文件有关的信息结构,如图1所示,结构的实际定义可能随具体实现会有所不同,但这是基本形式。本节中主要涉及的有st_mode、st_uid和st_gid成员。
图2 获取stat函数
获取文件信息结构stat,有4个stat函数。
stat通过pathname来获得文件相关信息结构stat;
fstat通过文件描述符fd来获得文件相关信息结构stat;
lstat类似于stat,但当命名文件是一个符号链接时,lstat返回该符号链接的有关信息,不是符号链接引用的文件信息【NOFOLLOW】。
fstatat中,fd控制相对路径的起始目录,flag控制是否跟随符号链接【AT_SYMLINK_NOFOLLOW】。
-
文件类型
(1)普通文件(2)目录文件(3)块特殊文件(4)字符特殊文件(5)FIFO(6)套接字(7)符号链接
文件类型信息包含在stat结构中的st_mode成员中,可用图3的文件类型宏判断,输入为st_mode,如S_ISREG(stat.st_mode)。
图3 文件类型宏
二、与进程相关的ID
与进程相关联的ID有6个或更多,如图4
图4 与进程相关的ID
1、实际用户ID和实际组ID,标识实际上我们是谁,这两个字段在登录时取自口令文件中的登录项。
2、有效用户ID、有效组ID及附属组ID,这3个ID决定了进程的文件访问权限。
即判断文件访问权限是根据进程有效ID与文件的ID进行判断的。具体规则后续再展开。
3、保存设置用户ID、保存设置组ID,分别是有效用户ID、有效组ID的副本。这个字段的用处,后续再展开。
注意:一般情况下,有效用户ID=实际用户ID,有效组ID=实际组ID
特殊情况下:st_mode中set-user-ID位(设置用户位)和set-group-ID位(设置组位), 会改变这种情况。
如果文件的设置用户位被设置,那么执行该文件(exec)时,有效用户ID=文件用户ID,而不是有效用户ID=实际用户ID;
如果文件的设置组位被设置,那么执行该文件(exec)时,有效组ID=文件组ID,而不是有效用户ID=实际用户ID。
例1:passwd是一个设置用户ID程序,当普通用户进程执行passwd时,有效用户ID更改为文件的用户ID(root),这样就拥有了root特限,可以更改口令文件。
-
保存设置ID的作用
以用户ID为例,组ID效果类似,可推广。
更改用户ID的方法,如图5所示。
图5 更改用户ID的方法
实际的用户ID在登录时获取,有效用户ID=实际用户ID;
除非exec一个文件时,该文件设置了设置用户ID位,有效用户ID=文件的用户ID;
保存设置用户ID从有效用户ID中复制。
这些在前边都介绍过了。
当程序需要增加特权或者降低特权时,需要对用户ID或组ID进行更改,以获取合适的访问权限。
这里以用户ID为例,更改用户ID,可以用setuid进行。
(1)若进程具有超级特权,setuid则会更改实际用户ID、有效用户ID、以及保存的设置用户ID为uid。
(2)若没有超级特权,setuid只能更改有效用户ID,而且uid要么为实际用户ID,要么为设置用户ID。
例2:at程序,可用于调度在哪个时刻运行特定的命令。at文件是root用户所拥有的,且设置用户ID位被设置了。
运行at程序,过程:
(1)运行at程序,用户ID状态如下
实际用户 ID = 我们的用户ID(未改变)
有效用户ID = root(从at程序文件得来)
保存的设置用户 ID = root(复制有效用户ID)
(2)at先降低自己的特权,调用setuid更改为实际用户ID
实际用户 ID = 我们的用户ID(未改变)
有效用户ID = 我们的用户ID(uid=实际用户ID)
保存的设置用户 ID = root(未改变)
(3)直到需要特权时(更改命令何时的运行配置文件),调用setuid更改为root(uid = 保存的设置用户ID,这也是保存设置用户ID作用的体现)
实际用户 ID = 我们的用户ID(未改变)
有效用户ID = root(uid=保存的设置用户ID)
保存的设置用户 ID = root(未改变)
(4)降低特权,防止对特权的误用
实际用户 ID = 我们的用户ID(未改变)
有效用户ID = 我们的用户ID(uid=实际用户ID)
保存的设置用户 ID = root(未改变)
(5)时间到,守护进程开始用root特权运行,代表用户运行命令(用setuid,将所有用户ID设置为我们的用户ID)
实际用户 ID = 我们的用户ID(root,setuid更改所有)
有效用户ID = 我们的用户ID(root,setuid更改所有)
保存的设置用户 ID = 我们的用户ID(root,setuid更改所有)
总结:保存设置用户ID,很多部分是为了实现最小特权。
三、文件访问权限
每个文件有9个访问权限位,可分为3类,用户读写执行、组读写执行、其它读写执行,如图6所示(存储在st_mode)。
图5 文件访问权限
根据前边,知道访问权限测试,是根据进程有效ID(有效用户ID和有效组ID)和文件的ID进行判断的。
(1)进程的有效用户ID是0(超级用户),具有所有访问权限;
(2)进程的有效用户ID等于文件用户ID(stat.st_uid),且文件中用户适当的访问权限位(读写执行)被设置,则允许访问;
(3)进程的有效组ID或附属组ID之一等于文件组ID(stat.st_gid),且文件中组适当的访问权限位(读写执行)被设置,则允许访问;
(4)其它情况,若文件中其它用户适当的访问权限(读写执行)被设置,则允许访问;
-
access和faccessat
access和faccessat函数,可根据进程实际ID来测试访问权限,而不是有效ID。
图6 access和faccessat函数
四、新文件的所有权和权限
所有权:
新文件的用户ID设置为进程有效用户ID;
新文件的组ID,可以是进程有效组ID;也可以是所在目录的组ID;
注意:Linux3.2.0和Solaris 10,新文件的组ID取决于目录的设置组ID位是否被设置。若被设置,则新文件的组ID是所在目录的组ID。
新文件的权限:
umask为文件模式创建屏蔽字,在文件模式创建屏蔽字中位1的位,在文件mode中的相应位一定被关闭。
还有,普通文件文件被创建时,不能拥有执行权限。
常用值有002,022和027。
002屏蔽其它用户的写权限,022屏蔽组成员和其它用户的写权限,027屏蔽组成员的写权限以及其它用户的所有权限。
五、更改文件的权限位
图7 chmod、fchmod和fchmodat函数
只有进程的有效用户ID等于文件所有者ID,或者进程具有超级用户权限,才可以更改文件的权限位。
参数mode是一下的常量按位或:
图8 权限位总览
粘着位作用:
(1)可执行文件,第一次被执行后,程序正文部分还保留在交换区
(2)扩展了使用范围,如果一个目录设置了粘着位,那么改目录下的文件删除有限制条件
拥有此文件 or 拥有此目录 or 是超级用户才能删除。
六、更改文件的用户ID和组ID
图9 更改文件用户ID和组ID函数
_POSIX_CHOWN_RESTRICTED限制生效:
(1)只有超级用户可更改用户ID
(2)非超级用户可以更改自己拥有文件的组ID,但只能更改到自己所属的组
七、文件权限位总结
图10 文件权限位总结
以上是关于文件权限的主要内容,如果未能解决你的问题,请参考以下文章