Linux的文件、用户权限以及sudo原理漫谈

万物皆文件的思想

很简单,所有的东西都看为文件即可。

包括普通文件、IO设备等等。对这些东西的处理都可以抽象成:open、close、read、write。(想想网络IO是不是这样?)

文件怎么持久化的

既然万物都是文件,那在文件抽象层,对文件的管理就可以是统一的。

区别在于有些文件是要落地(比如数据),有些只是临时的(比如socket和Process)。
对于需要落地的文件,可以简单的理解为分两部分存储。一部分是数据的本体(比如2.3G的电影),另一部分是meta附加信息。而有关于权限的部分,就是存在这个 meta 上的(想想也是,权限跟电影本身又有什么关系呢?)。

为什么需要这么做?大家肯定自己管理过数据,特别是数组。它有个特点是“等大”。只要每一个对象都是等大小的,那么这些对象的合集就会更容易管理,无论是数组还是链表抑或是其他的数据结构形式。
对于文件的本体,File System 并不需要特别关心具体内容。抽出meta之后,就能轻易的集中管理大小一样、形状类似的一堆东西了。

这个meta、就是Innode

我们这里不具体讨论存储系统,大家有个概念就行。权限是一种文件的 meta 信息,并且存储在硬盘上的统一的meta 管理区(亦即Innode区)即可。按照这种思想和结构,对文件的管理可以无限拓展附加信息,而不限于权限相关的属性。

文件权限该怎么设计?

大家肯定第一反应的到,Read 跟 Write 两种权限。Linux差不多也是这样,只是作为 “万物皆文件” 思想贯穿的OS,它还必须有一个表示某某文件可以被Load入到内存并且执行的概念(毕竟磁盘里的程序也是一种文件)。这就是X权限(executable 的开头读音 “艾克斯”,试试就知道了)。

  • 当然有些人觉得这种说法不严谨,x权限除了可执行外,其在文件夹这种特殊文件下有其特殊的含义,表示可以展现下面的文件列表(而不是通过read权限来进行)。但文件夹作为一个特殊的文件,下面的文件列表需要一个 “执行展开” 的过程,需要x权限也能说得过去。

总结起来,就是 rwx 三维度的权限。我们平时在操作系统里 ls -l 看到左边的那一列就是了。
ll截图

除开这些,还有两种权限。这两种在日常使用中就比较少见了(而且一旦认为自己业务上需要用到,就要多加三思)。这里先简单介绍一下,有个印象即可。它们是:
s:文件在执行阶段具有文件所有者的权限
t:使一个目录既能够让任何用户写入文档,又不让用户删除这个目录下他人的文档

s 权限在后面的 sudo 原理中会提及。

权限之上还需要用户来承载

有了权限的概念,还需要一个User,用户的概念来承载它。毕竟如果不区分用户,直接使用,那么权限也无从谈起了。就像是你直接操作一个单片机,所有的零件、部分都可以自己自由控制,full access,还需要什么权限吗?

操作系统是需要解决这个问题的。一个系统要面临多个用户共同使用的情况。不同用户就应当有不同的权限,以达到系统的安全和规范运行。

用户该怎么设计呢

可以类比到现实中来,我们人类为了有效的进行关系的组织,不知不觉中已经在自己的个体之上,建立了“敌我识别”。无论自己的社会关系多么复杂,总结起来只有三个基础概念:
1、我;
2、跟我一起的人(组织);
3、其他人。
这套敌我识别系统可以无限交叉、重叠。
比如,家庭组织中,我还是我,组织是家庭其他成员,3就是陌生人;公司组织中,我还是我,组织是同事,3就是其他人(甚至父母在这个划分中,也是其他人)。

Linux也是这样的,一共有对应的三个概念:文件拥有者对应的本人——User用户、文件所属的组——UserGroup用户组、Others其他。
每一个文件的权限设置,都必须显示给定这三者对应的权限。然后大大小小父父子子文件发散出去,各种交叉重叠,组成了庞大的文件权限系统。

具体到Linux中,使用 ls -l 来显示文件时,前面的除了第一个字母表示文件类型(比如d就是 directory),剩下的九位就是对这三者的具体权限分配,每一个概念对应三个位。
截图
上图中,从左到右,就是:
1、此文件对于本文件的所有者来说,rwx,可读可写可执行;
2、此文件对于本文件的用户同组的用户来说,rwx,可读可写可执行;
3、此文件对于其他用户来说,rx,可读可执行(对于文件夹来说就是可以看下面的文件列表了)。

Linux的用户设计大体就是这样了。其他的花里胡哨的、文件组转移、组加人、组踢人等等,就都是这个简单体系上的一些扩充了。用到自然懂。

既然Linux有严格的权限,有没有例外

绝大部分的用户权限,都能以上面的用户、用户组概念来解决掉。之所以说绝大部分,是因为有一个特殊的用户需要特别的去考虑。那就是 root 用户。
这个用户拥有至高的权限,是整个系统的绝对Master,所有东西都要Obey他。
也因此,他不能随便滥用,否则就是《西游记》里的太上老君,《封神榜》里的元始天尊。一出动就是核爆炸。

但有一些操作又的的确确需要他来出马,特别是操作系统中的一些敏感的部位。他觉得这样挺烦的,而且容易误操作,怎么办呢?找一个替身,临时授予他权限,成为 agent 即可。
找替身的方法,就是 sudo。

sudo是怎么绕开上面所设计好的、看似已经没有漏洞可钻的用户权限管理系统呢?

用户的操作者并不是用户

对,有点反直觉,但从概念上来讲,其实我们在使用OS中,产生的 “自己在操作OS” 的感觉,其实并不是简单的两点一线关系——这中间是有替身的。

这让我想起有名的 Terminal 跟 Console 概念。如图(渣画):
在这里插入图片描述

其实真正跟OS连接的,是Agent,也就是以用户的名义启动的各种Process进程。而并不是用户直接下达指令的Terminal(终端)。
也因此,Agent 是可以被动手脚拓展的。

怎么动手脚

所有的Process,除了Termial的User直接的所属身份,还能有一个实际的生效的身份。它们是:

  • real user id(ruid):执行进程者的 user id,一般情况下就是用户登录时的 user id
  • effective user id(euid):决定进程是否对某个文件有操作权限,默认为ruid

也就是说,进程在运行中,ruser 可以跟 euser 是不同的。那么就产生了一个通道:就算我们不是root用户,也可以让我们跑起来的Process拥有Root的权限(也就是euser是 root)。

好了,问题在于,怎么样设置 euser 为 root呢?
Linux提供了一个seteuid的函数,可以更改进程的euid。
int seteuid(uid_t euid);

但是普通用户肯定是没办法直接用的,因为不能随便突破权限墙。
那么只能在root上找缺口。那就是上面提到的,文件的s权限。

  • s:文件在执行阶段具有文件所有者的权限

只要有一个root认可的可执行文件,通过一个配置文件来决定执行的环境——允许指定的用户通过它来中转一下启动的指令请求,那么后续的执行就是拥有 root 权限的了。这个被允许的用户,就成了完美的 root 的替身。
而这个可执行文件,其实就是 sudo 的本质。

SUDO的流程

一图胜千言(渣画)。
我们执行的:
sudo ping
实际发生的:
在这里插入图片描述

完结撒花。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值