linux内核工程导论-Linux用户和权限系统

Linux用户和权限系统

简介

我们使用linux系统,一定会使用一个用户,没有用户就不可能使用任何的系统功能,包括系统调用。因为系统调用本身也是要有用户的。我们刚登录一个系统,需要一个login程序,验证了用户名密码之后,就会返回给你一个shell。后面执行的内容都是在shell中执行的。包括可以在shell中设置ulimit做资源限制,我们也可以发现用户和密码都存储在/etc/passwd/etc/shadow这些文件中,很有可能产生用户权限校验是在系统级做的,而不是在内核中做的错觉。

所有的权限校验都是在内核中完成的,但是策略都是在用户空间配置的。

系统启动时的权限

为了最根本的解释整个过程,我们不使用glibc封装的函数名字,而是完全使用内核系统调用的名字和功能。

系统执行命令除了通过shell启动还可以通过其他的进程启动。由于linux内核设计的进程继承关系,第一个进程是init进程,这个进程是root权限,拥有最高的完全权限。如果你直接修改init程序,在里面实现逻辑,也是具有完全权限的,内核的所有权限检查都可以完全通过。

后来启动的进程全部是init进程复制出来的(感谢linux的进程启动方式),linux有两种复制接口(vfork不算),forkclonefork就是傻傻的完全复制,然后使用execve系统调用执行新的命令。execve系统调用的参数也只是路径,参数和环境变量,而继承自父进程的所有权限和句柄都还在。而clone是可以指定复制什么的,例如文件句柄,根文件系统,命名空间等,但是clone仍旧不能用其他的用户去执行程序,也不能设定新的capbilities等权限设置。

启动后面的低权限进程和用户的过程是一个不断降低权限的过程。例如不共享打开的文件句柄,设置新的更小capabilities权限,使用权限更小的用户启动程序等。设置这种区别的方法是使用高权限的进程调用系统调用例如用unshareprctlsetuid来完成的。这些进程权限高的原因是使用的root用户,是这个用户的权限高(后面我们会说两种不同的进程用户权限)。

su命令是我们常用的切换到其他用户执行命令的方法,它所使用的就是setuid系统调用方法将当前执行的具有root权限的用户降级为非root用户。Unshareprctl都不能用来切换用户,而是用来控制偏功能性的权限(capbilitiesnamespace等)。Setuid系列调用有很多,各有区别,暂不讨论。

系统启动后的权限

系统正常运行之后,进程要么由其他的进程启动,要么由shell启动。由其他进程启动的很多也是由shell启动的。Shelllinux的中坚,Shell程序本身也必须有一个用户。例如登录使用的用户user1,那么login程序(root权限)验证了这个用户名密码后,就可以setuid设置启动的shell以特定的权限用户运行。图形界面也是使用特定的用户运行了基础的组建之后再衍生(例如lightdm)。

Shell之所以重要就是因为它就是中转的中心。我们完全可以不需要shell,使用图形界面做中转中心,也可以使用一个服务进程,接收远端的socket指令作为中转中心。Ssh是服务进程作为中转中心的例子,但是登陆之后中心还是转变为了shell

我们也可以发现/etc/passwd中给每个用户都定义了shell,也可以使用/bin/false,可以看出shell的思想已经固化到系统中了。所以shell不再是一个简单的应用程序,而是一个系统组件(它本质就是一个应用程序)。

当我们在shell中切换用户的时候,我们是用新的用户开启了新的shell。这个shell的执行者就是新的用户,执行的命令也自然继承了新用户。而我们可以通过susudo改变这种情况。Su可以运行在低权限的shell中,但是切换到高权限的shell,是因为su命令本身是有suid的,这个二进制标志可以让进程被普通用户执行,但是却拥有root的操作权限。

 

内核中的用户和权限模型

Linux中为了定义权限,设计了一个对象模型。这个模型主要组件有:objectsubjectcontextactionrule

常见的对象都是objectTasksFiles/inodesSocketsMessage queuesShared memory segmentsSemaphoresKeys)。

object作用在其他object的时候,发起方就是subject,最常见的变成subjectobject的是task

无论是object还是subject都有自己的contextcontext主要是一些归属于自身的权限存储(credentials)。

一个subject作用到另外一个object的动作叫做action

限制一个action权限的叫做ruleRule包括MACDAC两类,常见的selinux规则就是在这里工作

 

这一整个模型运作起来,给所有的对象都赋予了静态和动态的权限,就形成了完整的权限系统。

我们常见的用户和文件权限工作在context层次,linux起了一个名字叫credentialscredentials目前有7种,这些权限检查都是要同时满足的,一个不满足就不通过安全检查:

传统的uid系列,设置在文件object context credentials层次,但是euid系列是设置在subject context credentials层次的。但是都是在文件本身保存的,除非不是物理的文件。

l Capabilities。这是linux独创的系统。将系统分成了几个部分,权限一个一个子系统的设置和删除。这是进程subject context的内容

l Securebits是在capabilities机制运行比较老,并且很多不适应。

l Keys and keyrings

l Lsm。这是大部分大规模的安全系统所基于的内核安全机制。通过在常用的路径上安装钩子实现,是完全独立于模型的机制

l AF_KEY。这是网络层的权限控制,主要用于ipsec

 

当我们创建一个进程的时候,内核是知道是谁创建的,并且会设置该进程task_struct的对应的域(credreal_cred),里面有存储有效用户和实际用户的id。内核知道并不是通过系统调用传递的,而是进程是复制产生的。就是上一个进程的id。如果上一个进程要用其他的id启动进程,它会首先setuid改变自己(例如su命令),然后再做系统调用的。

所以内核本身也不知道具体用户的名字和它对应的shell和组。这些都是存储在用户可见的文件系统,由用户维护。调用su命令后面加的用户名也是在用户空间去查到的对应的uid。登陆时候验证密码也是login程序计算验证直接通过文件查询的结果,并不需要经过内核。

内核中并没有专门的数据库存储用户和组信息,而是依附在每个进程上的。至于每个进程都可以有多种用户和组的设置,还包括线程的处理(linux内核是基于单个线程(进程)的,而线程要求进程范围内统一)。

 

Linux安全体系

内核只管权限,其他不管。如果文件的所有者是普通进程,但是却调用了reboot。只要执行的时候有root权限,这个程序就能够执行成功(除非额外设置了系统调用限制或capbilities等其他安全维度)。所以内核默认大部分是依赖于是谁(uid)在执行程序的,而不是依赖执行的内容。

而大部分额外的安全系统(例如apparmorselinuxseccompcapabilitiesacl 等),都是对默认最有效的基于用户的安全体系的补充,大都作用于执行的内容,而不是执行的用户,并且作用在不同的位置。

用户和组概念

用户和组是独立于文件和进程存在的,他们被存储在/etc/下的几个文件中。

一个用户可以属于多个组,一个主要组,其它的叫做supplementary group。这是历史原因,这些组之间没什么区别。

文件object静态的包含了用户和组设置,而task(进程)也分为静态和动态的用户和组的设置。

文件object权限

文件有标准权限和扩展权限。标准权限包括用户,组,其他组三个的rwxst权限。s是让非root程序以root身份运行的标志位,t是让进程启动后滞留内存不被回收的标志位。还有该文件属于哪个用户哪个组。

扩展的有ia比较常见(主要是ext系列文件系统支持),i限制文件不能被删除,a限制文件只能追加,不同的文件系统可以实现不同的扩展权限,甚至可以用户自己定义,acl扩展是所有文件系统都有的能力。

设置标准权限用chmod,设置扩展权限用chattr

进程的objectsubject权限

进程看起来是动态的,但是他们既是object(静态的一面)也是subject(动态的一面)。静态的一面就是我们设置在文件上的用户和组以及其对应的权限,大部分情况下,内核依据这个信息进行权限判断。这个用户叫做实际用户。

动态的一面就是当文件suid置位的时候,用户以root权限运行,这时进程的权限是root的,这个用户就是有效用户。理论上有效用户不一定要是root,但是目前都是。

Sgid也是一个道理。

所以文件object本身的权限设置既提供了文件object本身的权限,也提供了进程object的权限和进程subject的权限。

总结

Linux中默认基于用户的安全,并且各个文件系统的权限位相配合。后续发展了多种维度基于行为的安全机制,成为linux安全系统发展的方向。安全系统大部分都在内核中完成,内核只是一个管理和验证系统,并不是所有的安全验证都在内核,系统层次可以完成相当多的权限验证。

 

 

 

 

 

 

你可能感兴趣的:(linux)