1,文件的9个访问权限
st_mode的1到9位分别代表着一个文件的9个访问权限,分别如下:
- 用户相关:
- S_IRUSR 用户读(0x400,第11位位1)
- S_IWUSR 用户写
- S_IXUSR 用户执行
- 组相关
- S_IRGRP 组读
- S_IWGRP 组写
- S_IXGRP 组执行
- 其他相关
- S_IROTH 其他读
- S_IWOTH 其他写
- S_IXOTH 其他执行
每个文件都有一个用户(所有者)和组,默认为创建文件时的用户和该用户从属的组。文件的所有者和组可以通过chown命令改变。具体用法如下:
chown someone:some_groupfile_name
当然,前提是你有足够的权限。
上面的9个权限就是分别表示文件的所有者(用户)是否有权读、写和执行该文件,文件所属的组是否有权读、写和执行,以及其他人(除了root用户和文件所有者之外的人)是否有权读、写和执行。
一个文件的权限信息可以用ls命令显示,具体如下:
这些打印出来的权限3个3个一组,分别表示用户、组合其他人的权限。
2,文件的访问规则
- 要想访问一个文件当然必须先能访问那个目录;要想访问一个目录当然必须先能访问他的上一级目录。造成的结果就是:我们用带路径的文件名打开一个任意类型的文件时,对文件名中包含的每一个目录都必须具有执行权限,包括隐含的当前目录。请注意,是目录的执行权限,而不是读写权限。例如,为了打开 /home/hy/code/APUE/Chapter3/snow.txt这个文件,就必须对目录/、/home、/home/code、/home/code/APUE、/home/hy/code/APUE/Chapter3都有执行权限,然后还必须对snow.txt这个文件本身有恰当的读写权限,才能打开该文件。如果该用户对snow.txt文件本身有权限,但是却对code目录没有执行权限,则其仍然无法打开snow.txt文件;
- 目录的读权限表明你可以搜索该目录里的文件名,不代表你可以打开该目录;
- 要想在一个目录里创建文件,你必须具有该目录的写与执行权限;
- 要想在一个目录里删除文件,你必须具有该目录的写与执行权限,而对该文件本身则不必有读写权限;
3,内核测试进程对资源的权限的流程
- 若进程的有效用户ID是0(root用户),则允许访问(有效用户的含义,自己去翻上一节);
- 若进程的有效用户即为文件的所有者(称为进程拥有该文件),则如果所有者对自己的文件有适当的访问权限则允许;
- 若进程的有效组或附属组为文件的所属组,则如果组有适当的权限,则允许;
- 若其他用户有适当的访问权限,则允许,否则拒绝
注意,以上4步是依次执行的,只有前一步判断没有权限才会执行下一步继续判断。
4,例子
我们在当前目录下新建一个snow.txt文件,写入一些无关紧要的内容,然后尝试修改其权限,看在C语言中,用open函数是否能打开它。
- 创建文件并写入内容:
- 读取文件的C代码实现:
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
void err_sys(char *);
void err_sys(char *err_txt)
{
printf("%s\n",err_txt);
exit(1);
}
int main(int argc, char* argv[])
{
//4.5 文件访问权限
int fd = 0;
char buf[100];
memset(buf,0,100);
printf("euid = %d, egid = %d\n", geteuid(), getegid());
if((fd = open("snow.txt",O_RDWR))< 0)
err_sys("open error!");
else
printf("fd = %d\n",fd);
if(read(fd,buf,90) == -1)
err_sys("read error!");
else
printf("%s\n",buf);
exit (0);
}
- 当前权限下的执行结果:
- 去掉用户和组对该文件的读权限后:
由于有效用户和有效组都对文件没有 读权限,访问失败
- 以超级用户运行
root用户总是能够获取权限,执行成功。
- 将文件所有者改为root,去掉root对snow.txt的读权限,运行
哪怕是去掉了root用户的读权限,root还是能获取资源。可以这么理解:root用户总是可以提升自己的权限的。能去掉自己的读权限就能加回自己的读权限,所以索性就全部开放给他们了。
- 将进程文件与要读的文件的所有者都改为root,再以hy的身份运行:
第一次执行失败,因为进程的有效用户是hy,而hy对snow.txt没有读权限;
第二次,给进程文件加上了“设置用户ID位”,进程的有效用户变成了root,执行成功。
千万注意:“设置进程ID位”的作用是将进程的有效用户ID改成进程的所有者ID(可执行文件的所有者ID),而不是将进程的有效用户ID改成要读写的文件的所有者ID。进程属于root,所以它的权限大,但不能是“因为文本文件属于root,所以它应该被所有人读写”,这个逻辑说不通。需要设置的是进程文件(即可执行文件)的S权限而不是进程要读取的文件的权限。