Unix权限这点事

时间:2022-11-20 07:58:55

Unix/Linux的权限管理还是比较复杂的,别人说看高级环境编程得看2,3遍。我想这应该是在Linux有了一定基础。但是我看的过程中确需要反复推敲,有些地方得翻来覆去看上5,6遍甚至更多,下面是自己的一些对Unix权限的理解,尽量翻译成了大白话。如果有不对的地方,欢迎讨论。

用户和组

现实生活中的例子

关于用户和组,对比现实生活中的例子。Linux系统好比一个大型的图书馆,里面存放着各种书籍,文件和一些演示设备(像天体运行动态演示设备等等),还有电脑,普通人想进入图书馆进行学习必须注册(useradd)为为会员(User),成为会员后图书馆管理员(root)会给会员发送门禁卡(password),会员进入图书馆刷门禁卡即可。会员在图书馆内可以阅读书籍(read),也可以触发演示设备,操作电脑(run)来进行学习。这些书籍,文件和设备的拥有者(owner)都是管理员,会员的权限由管理员指定。另外,会员是可以在书籍中记(write)笔记的,但要获得管理员的许可。

用户

这个图书馆比较特殊,会员可以把属于你自己的书籍,甚至电脑放(create)到图书馆中,会员自己的书籍可以自己决定是否有读(read)和写(write)的权限,可以决定自己的电脑自己是否是可执行(run)的。既然会员把图书和设备放到了图书馆中,管理员有权对这些书籍和设备进行读写和执行。

好了,总结一下,现在图书馆中的各种书籍和设备的拥有者分成两类,一类是管理员,一类是会员。会员是管理员发放了门禁卡之后才能进入。到这里你发现没发现一个问题,一个会员的书籍只能够给两个人看,一个人是他自己,另一个是管理员。这样的话就浪费了图书馆的资源,如今都讲究共享,共享单车,共享充电宝,共享经济(这个概念已经很老旧了,Linux/Unix中已经使用了这个概念)。。

如何才能解决资源共享的问题呢?共享也不是随意共享的,有些会员的资源可能只愿意给自己认识的人看,有的愿意认识的人在自己的书籍中记笔记;有的人愿意自己的资源只给对其感兴趣的人读和写;而有的愿意给所有人读和写。为了达到这种精确控制。管理员创建了一个规则:设定组(group)。管理员可以创建(groupadd)一个组,普通会员在获得管理员许可后(sudo)也能创建组。

例如:会员A,B,C,D达成共识,咱们创建一个组吧,以后四个人的资源就可以*共享了,于是他们向管理员申请创建组adGroup,管理员亲自创建(groupadd)或者授权给(sudo groupadd)其中某一个人创建。创建完成之后把四个人加入(usermod)这个组即可。以后其他人可以申请加入这个组。一个人可以同时加入多个组。这里会有个问题,既然一个人可以属于多个组,那么一个用户往图书管理放一本书,为这本书设置组权限的时候,设置的权限是哪个组的呢,好吧,我们首先设置一个默认组,会员进入图书馆的时候,拿进去的书籍开始都是属于默认组(有效组)的,其余的组叫做附属组,可以把附属组修改为当前有效组(newgrp)。书籍放到图书馆之后,所属组就会记录下来,这个组可以由书籍所有者修改(chgrp),修改之后,这本书的组权限就变成新组的权限了。

接着上面说,四个会员可以分别指定属于自己资源的组权限,会员A的书籍bookA属于组adGroup,他可以指定属于这个组的用户可以读写。会员B有洁癖,他的书籍bookB属于组adGroup,他只给组权限设为只读。会员C突然发现自己的书籍中藏有宝藏密码,立即关闭了组读写权限,和管理员一起研究宝藏密码去了。。。

其它

我们看一下接下来的场景,会员E自己出了一本书,为了宣传自己的新作,他想尽可能快的让尽可能多的人看到这本书,并且得到反馈,他把这本书放到了图书管,他加入了所有组,把这本书的所属组设置为人数最多的一个组,并把组权限设置为读写。看到没有,尽管他加入了所有组,他的一本书籍只能为一个组设定组权限。他有两个选择:

  • 让其它所有人加入最大的组,但是现在作者知名度不高,是你在做宣传,谁会鸟你啊。
  • 统计一下组的数量N,拿N本书到图书馆,每本书指定一个组,开放所有组的读写权限。但是有个问题,以后有新创建的组改怎么办?

会员E的这种情况,我们给出一个解决方案,再加入一种特殊的组,况且这么叫吧,就是其它(others),它能够设定不在资源所属组内会员的权限。也就是其他人的权限。上面的问题迎刃而解,E不用再加入每个组了,也不用特定把书所属到人数最多的组,只需要把组权限和其他权限设为读写即可。

文件的权限

继续图书馆的例子,书籍是一个文件,我们已经知道的有关这个文件的权限的属性包括:

  • 文件所属者(Owner)
  • 文件所属组(Group)
  • 文件所有者的权限(u rwx)
  • 文件所属组的权限(g rwx)
  • 其它人的权限(o rwx)

还有其它的会在这一节里面详细说。看官们继续吧。。

我们知道,书籍是放在书架上的,书架是放在某个具体的屋子内的,屋子是坐落在图书馆内的。会员找到一本书,先得进入图书馆(login),然后进入某个屋子(cd),找到某本书籍所在的书架(继续cd),最后看到书籍,然后打开进行读和写。

为了方便管理,除了书籍和设备本身的读写和执行权限之外,图书馆可能会指定一下规章制度:

  • 这个图书馆历史比较悠久,有很多珍贵的资料单独存放在一个屋子内,管理者只想让少数的人进入屋子内浏览资料,其它人不用说看这些书了,屋子都不会让你进去。但是有可能会让你知道屋子里面有什么。
  • 为了保证图书馆内图书的分类正确,管理员不可能随随便便就让一个人把书籍放到一个书架上。当然也不会让一个人随随便便就把书拿出图书馆。

为了达到这种效果,聪明的规则制定者想出了一个办法,给屋子和书架也分配上面的5种权限。我们暂且把屋子和书架称作容器(folder)。

我们把会员和管理员可以执行的操作分成一下几种:

  • 向某个屋子新加一个书架(mkdir)(加屋子不太可能。。),挪走一个书架(rm)。
  • 拿一本书进来(touch cp ....),拿一本书出去(rm..)。
  • 浏览(ls)屋子内(书架上)的书籍名称。
  • 读写(vim cat..)一本书籍,操作一个设备。

我们看一下上面的四种操作需要什么权限。

  • 首先看一下普世法则,任何需要走到容器里面才能进行的操作,对整条路径上的容器都需要执行权限(只有一个例外);改变容器格局的操作都需要写权限。
  • 加减书架需要先走进图书馆(根),再走到屋子里面才能进行,因此对图书馆和屋子都需要执行权限。加书架屋子内东西多了,减书架屋子内东西少了,格局变了,因此都需要写权限。
  • 拿书到书架上也一样,手到了书架里才能操作,因此对书架的整条路径需要执行权限。当然也需要写权限。需要注意的是拿走一本书籍对书籍本书不需要读或者写的权限。
  • 浏览容器内的书籍和设备名字,这是第一条提到的例外,因为只是匆匆一撇,因此只需要路径各个容器的读权限就可以了。这里看到的只有书籍名字,其他信息一律获取不到。
  • 读书籍除了对书籍本身要有读权限,对书籍所在路径的所有容器都要有执行权限;写书籍出了对书籍本身要有写权限,对书籍所在路径的所有容器都要有执行权限;运行设备除了对设备本身要有执行权限,对设备所在路径的所有容器都要有执行权限。

将第五条规则详细说明

第五条规则里面的对书籍本身要有读写权限,那么什么情况下才会对书籍有读写权限呢,我们详细展开说明。
继续图书馆中的例子,我们注册成为图书馆的会员时,管理员是会给我们分配一个ID号的,这个ID号用来标识我们的身份。每次进入图书馆进行图书的读(read)和写(write),以及操作(run)设备,检查权限的时候是通过这个ID号来检查的:会员A进入图书馆,会员A的ID——r_id_a(real id)就会被记录下来,会员A打开书籍bookA进行读或者写的时候,会使用id_a来进行检查:

  • 如果id_a=0,代表是管理员。管理员就是上帝,可以为所欲为。读写都可。
  • 如果打开书籍的owner_id=id_a,说明这本书的拥有者就是会员A,接下来就看会员A给自己的这本书设置了什么权限,如果设置了自己可以读或者写,那就可以读或者写。反之,如果你认为这本书籍有害,设成了禁止自己读和写,你就不能读写。
  • 如果id_a和bookA的owner_id在同一个组中,那么,就要看这本书的owner如何设置组权限了,如果设置的组内成员可以读写,则可以读写。否则,不能读写。
  • 如果id_a既不等于owner_id,也不和owner_id在同一个组中,就需要看其它(others)设置的权限了,如果设置成可以读写,则可以读写。否则,不能读写。

上面的四个步骤,如果走到其中一个步骤的判断是允许或者拒绝,就不会再继续往下判断了。例如,如果bookA的owner_id=id_a,并且你设置的权限是禁止自己读写。即使你所在的组设置的权限为允许读写,结果也会是拒绝。

需要指出的是,上面的五条规则都是错误的,错误的地方在id_a上,我只是为了方便说明,实际上一个会员在图书馆里身份是可以通过某种方式进行变化的,也就是说会员在读写时,用来判断权限的id有可能不是id_a。接下来说明。

进程中的权限

进程的概念是动态的。也就是说权限这个东西是随系统运行会发生变化的。继续图书馆的例子,上一节最后我们说到了会员的身份问题。这里详细阐述一下,会员进入图书馆有一个ID(实际ID),这个ID确切标识了会员的身份,但是在会员进行活动时,操作某个设备(run)时,他这时的身份(有效ID)就有可能发生变化了。

纠正上一节中的错误:其实进行比较的不是id_a,而是身份变化后的ID——e_id_a(effective id)。

图书馆引入了一批机器人,这些机器人可以代替人进行图书的读和写。这样会员就可以直接通过电脑操控机器人。每个会员都可以拥有一个自己的机器人。这时候就可以把机器人看成会员的替身。当机器人进行读写书籍时,机器人的身份ID初始情况下就是会员本身的ID。会员的身份是如何通过机器人发生变化的呢?

会员可以真正操控别人的替身

一个会员是可以使用别人的机器人(run一个owner不是自己的程序)的,但是在通常情况下,e_id就是r_id。用真实身份去操控别人的机器人。权限结果有上一节的条款而定。但是只可能通过组权限或者其它权限来获得访问权。因此有很大的局限性。如何把会员的身份伪装成操控机器人的owner呢?
上一节我们提到了关于文件的5个属性。这里还要说两个:

  • 设置用户ID
  • 设置组ID

这两个ID是做什么用的?如果机器人(机器人是可以运行的文件)设置了设置用户ID,别的用户在操控这个机器人时,r_id会变成机器人的ownner_id。这就可以用机器人拥有者的身份来操控机器人呢了。有人有疑问,如果有其它会员搞破坏会怎么办?其实管理权真正在owner手里,替身还是替身,并不是owner本人。替身的功能是可以限制的,owner在设置替身的功能时,如果设置了设置用户ID,可以自定义机器人可以读写哪些书籍。
设置组ID是相同的道理。

需要注意的是,如果会员结束操控别人的机器人?这时的r_id会如何变化呢?答案是会变回原来的r_id。但是原来的r_id和g_r_id保存在什么地方呢?这里有另外两个ID来临时保存这两个ID:

  • 保存的设置用户ID
  • 保存的设置组ID

运行过程中变换身份

上面的身份变换是机器人开始运行时就发生变化的,那么在运行过程中可以发生变化么?也是可以的。

  • 微服私访。管理员就是上帝。管理员在操控别人的机器人时,因为r_id为0,可以读写任何书籍。上帝不能太招摇,为了防止自己权限太大犯错误,上帝可以伪装自己的身份。上帝可以修改r_id,e_id和设置用户ID为任意值。
  • 卑微的平民。普通会员的r_id只能修改为r_id或者保存的设置用户ID。其它均不可。