当你有所得,最好是用文字总结记录,这才是进步的关键!!
——–20191009
一、先了解一下SELinux的安全机制
DAC和MAC
SELinux出现之前,Linux上的安全模型叫DAC,全称是Discretionary Access Control,翻译为自主访问控制。DAC的核心思想很简单,就是:
进程理论上所拥有的权限与执行它的用户的权限相同。比如,以root用户启动Browser,那么Browser就有root用户的权限,在Linux系统上能干任何事情。
显然,DAC太过宽松了,所以各路高手想方设法都要在Android系统上搞到root权限。那么SELinux如何解决这个问题呢?原来,它在DAC之外,设计了一个新的安全模型,叫MAC(Mandatory Access Control),翻译为强制访问控制。MAC的处世哲学非常简单:即任何进程想在SELinux系统中干任何事情,都必须先在安全策略配置文件中赋予权限。凡是没有出现在安全策略配置文件中的权限,进程就没有该权限。
二.在SELinux中有几个比较重要的关键字,安全上下文,安全策略
1.什么是安全上下文?
我们在通过adb shell ls -Z 可以显示如下的一个界面
u:object_r:rootfs:s0 custom u:object_r:rootfs:s0 sdcard
u:object_r:rootfs:s0 d u:object_r:storage_file:s0 storage
u:object_r:system_data_file:s0 data u:object_r:sysfs:s0 sys
u:object_r:rootfs:s0 default.prop u:object_r:system_file:s0 system
u:object_r:device:s0 dev u:object_r:vendor_file:s0 vendor
其中u:object_r:rootfs:s0 就是文件夹custom的安全上下文,只有具备了u:object_r:rootfs:s0的安全上下文权限才能对custom的文件进行操作。否则就会报一些权限不够的error。
u:object_r:rootfs:s0 的具体含义是:SELinux用户:SELinux角色:类型:安全级别,每一个部分都通过一个冒号来分隔,android的所有进程都是用u来表示,object_r 表示角色role的意思其定义在roles文件中。rootfs表示类型,是最重要的,s0表示权限等级。
SELinux用户、SELinux角色和安全级别都几乎可以忽略不计的。正因为如此,SEAndroid安全机制又称为是基于TE(Type Enforcement)策略的安全机制
u:object_r:rootfs:s0 这个上下文系统是怎么定义的呢?
像这种上下文的定义在:xxx_contexts 文件里面,比如我们的之前的custom是文件夹就在file_contexts,如果是服务的话就在service_contexts里面
/system(/.*)? u:object_r:system_file:s0
/system/bin/atrace u:object_r:atrace_exec:s0
(/.*)? 是正则表达式,表示system文件夹下面的子文件或者子文件夹都具有u:object_r:system_file:s0 安全上下文。因此我们常常在system目录或者sdcard目录下创建文件夹或者文件,我们并没有给予安全权限,在实际中确有。就是因为这个原因。相当于linux中羣组的意思。
2.什么是安全策略?
安全策略就是在安全策略文件中会有许多allow开头的语句
allow netd proc:file write
这条语句的语法为:
allow:TE的allow语句,表示授权。除了allow之外,还有allowaudit、dontaudit、neverallow等。
netd:source type。也叫subject(主体),domain。
proc:target type。也叫客体,它代表其后的file所对应的Type。
file:代表Object Class。它代表能够给subject操作的一类东西。例如File、Dir、socket等。在Android系统中,有一个其他Linux系统没有的Object Class,那就是Binder。
write:在该类Object Class中所定义的操作。
根据SELinux规范,完整的allow相关的语句格式为:
rule_name source_type target_type : class perm_set
rule_name有以下几个:allow、allowaudit、dontaudit、neverallow
source_type :一般是指进程类型,如appdomain system_app untrusted_app 等。
target_type :可以是进程类型也可以是文件类型,像之前的custom 文件夹的上下文u:object_r:rootfs:s0 ,rootfs就是文件类型。
class :表示操作target_type 的类型是什么一般会有filesystem ,file ,dir,lnk_file 定义在security_classes文件里面
perm_set:表示具备的权限 read write create getattr setattr rename等。 定义文件在:access_vectors
在阅读SELinux权限的文件中常常能看到这样的写法:
allow appdomain {
audio_device
camera_device
dm_device
radio_device
rpmsg_device
video_device
}:chr_file { read write };
这段话的意思是:允许appdomain 对audio_device, camera_device,dm_device,radio_device,rpmsg_device,video_device,文件类型是chr_file进行read 和write操作。如果有多个source_type 或者target_type 或者class或者perm_set用 {}包围起来。
#特殊符号:
# 1):-号表示去除某项内容。
# 2):*号表示所有内容。
# 2):~号表示除了某项之外的其他项,取余操作。
source_type target_type都是type类型,那么type类型是怎么定义的?
#type命令的完整格式为:type type_id [alias alias_id,] [attribute_id] attribute_id
其中,方括号中的内容为可选。alias指定了type的别名,可以指定多个别名。attribute_id 由attribute关键字定义在attributes文件夹里面。
type untrusted_app, domain; 类型untrusted_app 关联domain属性。
特别注意:对初学者而言,attribute和type的关系最难理解,因为“attribute”这个关键词实在是没取好名字,很容易产生误解:
实际上,type和attribute位于同一个命名空间,即不能用type命令和attribute命令定义相同名字的东西。
其实,attribute真正的意思应该是类似type(或domain) group这样的概念。比如,将type A和attribute B关联起来,就是说type A属于group B中的一员。
使用attribute有什么好处呢?一般而言,系统会定义数十或数百个Type,每个Type都需要通过allow语句来设置相应的权限,这样我们的安全策略文件编起来就会非常麻烦。有了attribute之后呢,我们可以将这些Type与某个attribute关联起来,然后用一个allow语句,直接将source_type设置为这个attribute就可以了:
这也正是type和attribute位于同一命名空间的原因。
这种做法实际上只是减轻了TE文件编写者的烦恼,安全策略文件在编译时会将attribute拓展为其包含的type。如例子4所示:
[例子]
#定义两个type,分别是A_t和B_t,它们都管理到attribute_test
type A_t attribute_test;
type B_t attribute_test;
#写一个allow语句,直接针对attribute_test
allow attribute_test C_t:file {read write};
#上面这个allow语句在编译后的安全策略文件中会被如下两条语句替代:
allow A_t C_t:file {read write};
allow B_t C_t:file {read write};
前面讲过,TE的完整格式为:
rule_name source_type target_type : class perm_set
所以,attribute可以出现在source_type中,也可以出现在target_type中。
大家可以参考以下几篇博文
https://blog.csdn.net/luoshengyang/article/details/35392905
https://blog.csdn.net/innost/article/details/19299937/