1 进程和进程边界
1.1 进程和线程
-
可执行文件:不活动就是废物
-
进程:可执行文件的活动表现,一次生命的历练
-
线程:CPU(核)的调度单位,并发的执行序列,进程的多管齐下
-
资源和调度
1.2 手机操作系统的发展
- Feature Phone时代的实时简单的单进程多任务非智能系统
- Smart Phone时代的多进程多任务智能系统
1.3 进程的地址空间边界
- 虚拟内存(32bit系统 0-3G用户空间,3G-4G内核空间)(64bit系统 内存空间够大,随便分配,不同系统不同)
1.4 进程边界的安全围栏:Crash的不可扩延性
- 进程本身崩溃不影响系统
1.5 进程边界的安全围栏:全局数据和服务的不可访问性
- 进程自己的内存不会直接被其他进程访问
2 多用户和多用户边界
2.1 需求背景
- 资源缺乏
- 中央统一管理
2.2 多用户的边界:独立的工作目录
- 每个用户都有自己的home目录
2.3 多用户的边界:可操作/访问 的资源
- 资源分类
2.4 多用户的边界:可执行的操作
- 权限管理
2.5 多用户的特殊标志:UID/GID
- Name只是供看的
- Identifier才是系统层面的标识
- 用户的行为是一系列进程的行为
- 特性标识其实是进程的 UID/GID
3 进程和文件的UID/GID
3.1 文件资源的权限力度:UID/GID
- 文件是一类资源
- 在Linux中,甚至一切皆是文件,Socket,Driver
- 文件资源对不同Target(用户)的不同操作权限的需求应运而生
- 如何描述和区分不同的Target?(ID、UID 唯一的)
- 某些场景下,允许多个不同的Target/用户(而不是一个)具有一致的操作权限,怎么办? 多个用户可以属于一个GID,一个用户可以属于多个GIDs
- 所以文件权限的管理力度区分3类群体: 属于特定UID的用户,属于特定GID的用户(们),其他用户
- 一个上帝用户存在:ROOT,其UID=0,上帝用户 永远满足属于任何UID
3.2 文件的可操作权限
- 文件/文件夹可读
- 文件/文件夹可写
- 文件/文件夹可执行
3.3 进程的标识:PID、UID、GID、GIDs
- PID:进程的Unique Identifier。每次Running的PID可能相同,或者不同,由系统分配
- UID: 进程的身份标识。每次运行,即便重启后默认都相同。不同进程允许有相同的UID(用户身份标识)
- GID: 进程的(组)身份标识。每次运行,即便重启后默认都相同。不同进程允许有相同的GID(组用户身份标识)。同一进程允许属于多个GID
- GIDs: 进程所属的全部GID
cat /proc/<进程ID>/status | grep Groups
3.4 Name和ID的映射
- 在Android系统中,有对各个UID的定义,分别对应不同的用户
3.5 chmod和chown
3.6 UID/GID的衔接
- Linux一切皆是文件
- 文件基于UID/GID来划分它的面向群体,对它的面向群体定义不同的操作权限
- 用户的行为映射为进程的运行
- 进程的运行使用进程的UID/GID来标识自己的身份
- 进程的UID/GID <—>文件的UID/GID 完美衔接!!
- 进程的UID/GID除了被授予可操作文件的范畴外,非文件范畴的需要进行权限控制的操作(如重启系统等特权操作) 继续通过进程的UID/GID身份来进行控制和授权
- 比如,对于Reboot这个API,其入口处可以check calling的Process的UID,如果不是Root,则Reject。
4 进程的RealUID和EffectiveUID
4.1 身份的标识:进程的RealUID
- 进程的UID只是泛称,其实有很多种不同的UID。
- 进程的Real UID是进程的身份的标识,用来说明Who am i
- 仅仅说明Who am i,但是没有“实权”是不行的。
- Linux中,进程能做什么事情不是由Real UID来决定的。
- Real UID仅仅是身份,有身份没有权利是无用的。
4.2 权利的标识:EffectiveUID
- 有身份无权利是不行的
- Effective UID是进程的权利的标识。标识了该进程的“权利“
- Linux中的进程的授权(即,当前进程具有的操作权限)是靠EffectiveUID来识别的。
- 有权利就能做一切,Linux中具有“特权”Effective UID的进程能为所欲为。
- 前面几节说明的,文件,资源以及特权API操作时对进程是否有权限的识别的UID,即是指Effective UID。
4.3 身份和权利的关系
- 一般情况下,身份和权利是一致的,即 RealUID=EffectiveUID
- 所以,默认PS CMD输出的UID指的是Effective UID,而没有输出RealUID。
- 我们也可以显式的显示完整的Effective UID和 RealUID
ps -p <进程ID> -o pid,ruid,euid
4.4 root用户的特权
- 你应该已经知道,这里指ROOT用户,均是指EffectiveUID=ROOT的进程,尽管一般情况下,Real UID =Effective UID。
- Effective UID =ROOT的进程具有“皇权”,他不受任何限制,可以为所欲为。
- 它可以为自己正身:如果自己的身份(Real UID)其实不是“皇帝”(ROOT),它可以将自己的身份名正言顺的改成ROOT(调用SetXUID),从而使得身份和权利均是ROOT
- 它也可以自降为庶民:出家皈依,将自己的Real UID 和 Effective UID均设置(降低,也是调用SetXUID)为庶民(非特权普通的RealUIDEffective UID)。
4.5 UID的世袭
- 在Linux世界里,为了安全考虑,UID的世袭遵循:身份世袭而权利不世袭的准则。
- 子进程的Real UID =Effective UID =父进程的Real UID
- 这使得临时夺权且尚未正身(普通Real UID而特权Effective UID)的进程的子嗣不能继承其特权而仅能继承其的正身(Real UID)
5 文件的setUID标识
5.1 平民身份,皇族特权的需求背景
- Linux的passwd是一个可执行程序(CMD),用于修改用户的密码
- Passwd需要操作多用户的账号文件(该文件高度安全,仅有ROOT用户可以读写 )
- 普通用户难道不能修改自己的密码?!
- Passwd进程虽然是平民身份(普通用户启动它),但却需要皇族的权利。身份和权利不一致。
5.2 如何解决
- 临时提升特权(Effective UID)而维持身份不变(Real UID),使得其利用特权行使职责时可避免世袭的安全问题。
5.3 Linux的setUID标志位
- 文件的Owner UID设置为特权用户,比如ROOT
- 文件面向Owner UID的群体的操作权限增加额外的setUID标志
- Linux系统保证,任何用户(进程)执行该可执行文件(会Fork一个新的进程来加载该可执行文件running)时,该可执行文件所在子进程的Real UID仍然继承其父进程的Real UID,但是其Effective UID不在等于其父的Real UID而是被提升到该可执行文件的Owner的UID。
5.4 Chmod设置setUID的方式
- 和基本的RWX设置类似,有助记符和直接数字设置。直接数字设置时采用4位数字,第一位标志setUID。
chmod 4775 xxxx
5.5 setUID的安全问题
- sUID的进程的EUID提升了
- sUID的进程的RUID默认没有提升
- 在sUID进程的RUID没有正身(也设置为ROOT)之前,其子民的RUID/EUID只是平民
- 要依据实际场景,有限制的决定是否要在sUID进程中为自己正身,需要明确知道其后果是,其任何子民的RUID/EUID将均变为贵族(ROOT)
- 两个例子: passwd(未正身),Android中的su(正身)
5.6 有RealGID、EffectiveGID、setGID吗?
- 有
6 Capability
6.1 UID怎么了
- 权限颗粒度太大
- 容易引起权限过剩
- 权力溢出/过剩引起的安全问题
6.2 Capability:细粒度的权限控制
- 我们需要细粒度的权限
- 除了皇帝,我们也需要不同的地方官
- Linux引入了Capability:每个Capability系统内以一位Bit代表,OS内部使用64bit存储
6.3 进程的Capability
-
Permitted Capability Sets
当前进程的权利的围栏,最大权利范围,是Effective Capability Sets的超集。
-
Effective Capability Sets
当前进程的实际使用(支配)的权利集,该集内的Capability必须从属于Permitted Capability Sets。该集合与Effective UID类似,是实际的权利标识。
-
Inheritable Capability Sets
子进程唯一可以直接继承的Capability Sets。在Capability模式下,只有子进程的Inheritable Capability Sets = 父进程的 Inheritable CapabilitySets。其他的皆是 NO。
6.4 (可执行)文件的Capability
-
Permitted Capability Sets
该可执行文件可以为其进程带来的Permitted Capability Sets
-
Effective Capability Set
仅1bit,Enable or Disable,标识该可执行文件running所在的进程的Permitted Capability Sets是否自动全部Assign到其Effective CapabilitySets。通常用于与传统的Root-setUID可执行文件向下兼容。
-
Inheritable Capability Sets
与进程的Inheritable Capability Sets一起作用(位与)以决定新的进程的Permitted Capability Sets
6.5 Capability的BoundSet
- Capability BoundSet是进程的属性
- 是进程自己为自己设定的安全围栏(CapabilitySets),限制可执行文件的Permitted Capability Sets仅有局部能转化为进程的PermittedCapability Sets
- Capability BoundSet能够被子进程继承
- Init进程默认Capability BoundSet为全1
6.6 Spawn进程的Capability
- P代表父进程 P`代表子进程 F代表可执行文件
6.7 Capability与UID的兼容