Linux文件系统权限详解

1、文件系统的基本概念

Linux文件系统中一切皆文件,文件包含一般文件(有时候也简称文件)和目录

它们都由inode节点和block节点集组成


1)针对一般文件
存在一个inode节点和一个block节点集(多个block节点)

一个inode节点中包含了文件大小,userId,groupId,读取执行权限配置等信息,具体见下图。


block节点集中的每个block节点中包含了该一般文件的具体数据内容


2)针对目录
存在一个inode节点和一个block节点集(多个block节点)
一个inode节点中包含了目录大小,userId,groupId,读取执行权限配置等信息,具体见上图。
block节点集中的每个block节点中包含了很多条记录,每条记录的形式是:
<FileName InodeID>
FileName表示该目录下的一般文件或者目录的名字,InodeID表示相应于名字的一般文件或者目录的Inode节点ID

如下图。





2、一般文件权限

1)读权限
指是否能够读取对应block节点中的内容
比如现在有一个一般文件a.txt,它的权限是"400",当前登录用户就是该一般文件的Owner
那么用vi打开该一般文件,就会在状态栏中看到如下图的提示信息


2)执行权限
指是否能够执行对应block节点中的内容
比如现在有一个一般文件a.txt,它的权限是"100"
那么用"ll a.txt"查看该一般文件,就会得到如下图的结果[呈现绿颜色,右上角有*号,表示该一般文件是可执行文件]


3)写权限
指是否能够修改对应block节点中的内容
比如现在有一个一般文件a.txt,它的权限是"200",当前登录用户就是该一般文件的Owner
那么执行"echo 'hello world!'>a.txt"命令,就能够把"hello world!"字符串写入a.txt文件中


3、目录权限
1)读权限
指是否能够读取对应block节点中的<FileName InodeID>条目,但是不会去加载对应InodeID的数据信息,因而只能得到FileName信息
比如现在有一个authority目录,其下有一个a.txt一般文件,authority目录的权限是"400",当前登录用户就是目录的Owner
执行"ls authority",可以发现只能看到a.txt一般文件的名字,而不能看到该一般文件的权限信息[即没有去加载该一般文件的inode数据],如下图所示


2)执行权限

指是否能够读取对应block节点中的<FileName InodeId>条目中的Inode节点的信息,并对其进行修改,即是否能够读取目录下一般文件和目录的"大小,userId,groupId,读取执行权限配置"等信息,并修改这些信息

能够读取inode节点信息的例子1:

如果将authority目录的权限改为属主可读可执行,即"chmod 500 authority",此时再执行"ls authority",就可以得到与"1)读权限"不一样的结果

此时已经将inode节点的信息读取出来,就有了权限,时间等信息


能够读取inode节点信息的例子2:

比如现在有一个authority目录,其下有一个a.txt一般文件,authority目录的权限是"100",当前登录用户就是目录的Owner,当前登录用户对a.txt具有rw(读写)权限
执行"echo 'hello world'>authority/a.txt",可以发现成功修改a.txt一般文件的内容

因为能够读取inode节点的信息,就能获取权限信息进行判断,然后发现当前用户能够对该一般文件进行rw操作,然后根据读取到的inode节点信息获取该一般文件的block节点集,进行文件内容修改


3)写权限

指是否能够增加,删除,修改block节点中的<FileName InodeID>条目,即是否允许在该目录下增加文件,删除文件和进行文件重命名[注意:文件包括一般文件和目录]

由于增加文件,删除文件和进行文件重命名,都要使用到inode[比如增加文件需要修改inode上的时间属性,删除文件需要修改inode的硬链接计数,重命名通过先建立新的硬链接,再删除原有的硬链接来实现,因而也需要修改inode上的硬链接计数],因此需要拥有执行权限,写权限才能正常运作


比如现在有一个authority目录,其下有一个a.txt一般文件,authority目录的权限是"300",当前登录用户就是目录的Owner,
执行"touch authority/b.txt",就能在authority目录下创建一个b.txt一般文件
执行"rm authority/b.txt",就能将authority目录下的b.txt一般文件删除
执行"mv authority/a.txt authority/c.txt",就能将authority目录下的a.txt一般文件重命名为c.txt,如下图所示



4、进程权限

如何判定某个进程对文件的读取,写入和执行权限[注意:文件包括一般文件和目录]

首先介绍下进程的有效用户和有效用户组的概念,某个进程运行的时候,是以某个<有效用户组:有效用户>身份组合运行的[4][5],一般确定有效用户和有效用户组的方式是

有效用户:实际用户

有效用户组:实际用户组

实际用户:执行进程的用户

实际用户组:实际用户的primary group

比如说当前登录用户是dsl,它的primary group是dsl
那么执行kill命令,实际用户就是dsl,实际用户组是dsl,有效用户是dsl,有效用户组是dsl

那么执行sudo kill命令,实际用户就是root,实际用户组是root,有效用户是root,有效用户组是root[root的primary group是root]


判定某个进程对文件的读取,写入和执行权限,就只需要判定进程的<有效用户组:有效用户>身份组合对该文件的读取,写入和执行权限就可以了

我们经常使用的cd,ls等命令,在执行的时候也会创建相应的进程,我们经常会遇到"cd不了某个目录,ls不了某个目录下的文件"的情况,究其原因就是因为cd进程和ls进程的<有效用户组:有效用户>身份组合对这些目录缺少相关权限造成的

关于进程权限可参考另外一篇文章《进程的用户和用户组》



5、特殊权限
1)SUID
i、一般文件上设置SUID
当一个设置了SUID位的可执行文件被执行时,该文件将以文件所有者的身份运行,如果所有者是root,那么将以root的身份来执行该文件,即最后得到的进程的有效用户是root,在这种情况下效果与sudo执行一个文件一致[不过两者的Real UserId和Real GroupId并不一致,前者的<Real UserId:Real GroupId>是<dsl:dsl>,这里以dsl代表进程创建用户,dsl是dsl用户的primary group,后者的<Real UserId:Real GroupId>是<root:root>]
可通过以下代码来进行测试[6]
#include <stdio.h>
#include <unistd.h>
int main(int argc, char** argv) {
    printf("%d", geteuid());
    return 0;
}


> gcc -o setuid-test setuid-test.c
> ./setuid-test


备注:基于安全策略,在linux中,只能对二进制文件设置SUID,而不能对包括脚本文件在内的其他可执行文件设置SUID


ii、目录上设置SUID
The SUID permission set on a directory is ignored on UNIX and Linux systems.[7]


2)SGIT
i、一般文件上设置SGIT
当在一个可执行文件上设置了SGIT之后,那么文件执行创建得到的进程的有效用户组是该一般文件的所属组
可以用以下代码来测试有效用户组
#include<stdio.h>
#include<unistd.h>
int main(int argc,char** argv)
{
  printf("%d\n",getegid());
  return 0;
}


ii、目录上设置SGIT
当在一个目录A上设置了SGIT之后,在该目录下创建的的一般文件和目录的所属组跟A的所属组一致


3)sticky-bit

i、一般文件上设置sticky-bit

When set, it instructed the operating system to retain the text segment of the program in swap space after the process exited. This speeds up subsequent executions by allowing the kernel to make a single operation of moving the program from swap to real memory.

ii、目录上设置sticky-bit

当在一个目录A上设置了sticky-bit之后,在该目录下创建的一般文件和目录具有这样的一个特殊性质:

只有它们(一般文件和目录)的属主和root用户有权删除它们,其他任何用户即便拥有对A目录的rwx权限,也不可以删除它们
最典型的例子是:
tmp目录是所有用户共有的临时文件夹,所有用户都拥有读写权限,这就必然出现一个问题,A用户在/tmp里创建了文件a.file,此时B用户看了不爽,在/tmp里把它给删了(因为拥有读写权限),那肯定是不行的。实际上是不会发生这种情况的,因为有特殊权限sticky-bit权限,正如drwxrwxrwt中的最后一个t


参考文献
[1]http://en.wikipedia.org/wiki/Inode
[2]http://superuser.com/questions/520107/how-are-directory-structures-stored-in-unix-filesystem
[3]http://www.cyberciti.biz/faq/how-linux-file-permissions-work/
[4]http://haifux.org/lectures/84-sil/users-processes-files-and-permissions/users-perms-lec.html
[5]http://stackoverflow.com/questions/6305416/how-does-a-process-in-linux-decides-privileges-allotted-to-it
[6]http://unix.stackexchange.com/questions/364/allow-setuid-on-shell-scripts

[7]http://en.wikipedia.org/wiki/Setuid#setuid_and_setgid_on_directories

[8]http://en.wikipedia.org/wiki/Sticky_bit

你可能感兴趣的:(Linux文件系统权限详解)