背景
Linux的默认访问控制是DAC(Discretionary Access Control),自主访问控制,其特点是资源的拥有者可以对资源进行任意的操作,如读、写、执行等。其实现逻辑是进程准备操作资源时,Linux内核会比较进程的UID和GID,如果权限允许,则可以进行相应的操作。这种方式的问题是,如果一个进程以root身份运行,即意味着它能够对系统的任何资源进行操作,而不被限制。如果我们安装了有漏洞或有恶意的软件,系统存在安全问题。由此,我们需要另外一种安全访问控制机制MAC(Mandatory Access Control),强制访问控制。selinux就是MAC的一种,Android也采用这种增强的安全访问控制机制。
SELinux
Security Enhanced Linux(SELinux) 为Linux 提供了一种增强的安全机制,其本质就是回答了一个“Subject是否可以对Object做Action?”的问题,例如进程是否可以读写persist分区某文件夹下的文件?其中进程就是Subject而文件就是Object,写入对应的就是Action。 与DAC的区别是,MAC使用文件的方式直接规定进程对资源的操作权限,且配置文件被编译到rom中,通过指令或程序无法对sepolicy进行修改。
理解selinux的核心思想
- Subject:在SELinux里指的就是进程,也就是操作的主体。
- Object: 操作的目标对象,例如文件
- Action: 对Object做的动作,例如 读取、写入或者执行等等
- Context: Subject和Object都有属于自己的Context,也可以称作为Label。Context由几个部分组成,分别是SELinux User、SELinux Role、SELinux Type、SELinux Level
用户程序执行的系统调用(例如读取文件),都要被SELinux依据安全策略进行检查。如果安全策略允许操作,则继续,否则将会抛出错误信息给应用程序。SELinux决策的同时还需要Subject和Object的Context信息,确定所属的User、Role和Type等信息,以此查询对应的安全策略进行决策
SELinux 依靠标签来匹配操作和规则。标签用于决定允许的事项,系统中,无论是文件、进程,还是套接字等都拥有标签。SELinux 在做决定时需参照两点: 1)这些对象分配的标签 2)定义这些对象如何交互的规则
标签
标签在selinux中指明了subject或object的一些属性,其格式如下
user:role:type:mls_level
user:
system_u:表示系统程序
user_u:代表一般使用者账号相关的身份
role:
object_r:代表文件或目录等文件资源
system_r:代表的是进程
type:
type在文件资源上是类型
type在进程则成为领域(domain)
mls_level:
级别,仅在策略支持MCS或者MLS时才显示;
单个安全级别,其中包含敏感级别和零个或多个类别(例如s0:c0,s7:c10.c15)等
由两个安全级别组成的范围,两个安全级别之间使用连字符分开
#Android中的MLS的sensitivity level只有一个,即s0
标签由*.xxx_contexts文件定义
#flashlight file
/sys/devices/platform/soc/c42d000.qcom,spmi/spmi-0/0-01/c42d000.qcom,spmi:qcom,pm8550@1:qcom,flash_led@ee00/leds/led:torch_[0-3](/.*) u:object_r:sysfs_led_torch:s0
查看标签
- 查看进程的标签 以camera的provider为例,u:r:hal_camera_default:s0为其标签;
- 查看文件的标签
ls -Z
- 可以通过chcon指令来修改标签,
chcon lable files
规则
allow domains types:classes permissions;
domains:一个进程或一组进程的标签,也成为域类型,它只是进程的类型
Type:一个对象或一组对象的标签
Class:要访问的对象的类型,如文件、套接字等
Permission:要执行的操作,如write,read,exec等
规则写在.te文件中
#read/write flashlight file
allow system_app sysfs_leds:dir { search }; //允许system_app标签下的进程在sysfs_leds标签下对文件夹进行搜索
allow system_app sysfs_led_torch:dir r_dir_perms;//读文件夹
allow system_app sysfs_led_torch:file rw_file_perms;//读写文件
allow system_app sysfs_flashlight:file rw_file_perms;//读写文件
SELinux的运行模式
三个运行模式:
- Disable:禁用SELinux,不会给任何资源打lable;将SELinux重新启用时,会给资源重新打lable
- Permissive:如果有违反SELinux的操作,SELinux会向log中写入拒绝信息,但不会正真拒绝操作
- Enforcing:SELinux的正常状态,会实际禁用违反策略的操作
更改运行模式
//查看当前SELinux运行模式
adb shell getenforce
//设置为Permissive
adb shell setenforce 0
//设置为Enforcing
adb shell setenforce 1
SELinux Policy写法
安全策略文件,selinux的核心,编写安全策略文件的语言被称为SELinux Policy语言。 MAC的基本管理单位是TEAC(Type Enforcement Access Control)
RULE_VARIANT SOURCE_TYPES TARGET_TYPES:CLASSES PERMISSION
如:
allow system_app sysfs_leds:dir { search };
RULE_VARIANT
allow:赋予某项权限。
allowaudit:audit含义就是记录某项操作。默认情况下是SELinux只记录那些权限检查失败的操作。allowaudit则使得权限检查成功的操作也被记录。注意,allowaudit只是允许记录,它和赋予权限没关系。赋予权限必须且只能使用allow语句。
dontaudit:对那些权限检查失败的操作不做记录。
neverallow:用来检查安全策略文件中是否有违反该项规则的allow语句。
get_prop
get_prop($1,$2)
添加TE策略,使得2对应的文件/进程
set_prop
set_prop($1,$2)
添加TE策略,使得2对应的文件/进程
SOURCE_TYPES&TARGET_TYPES
type
类型声明语法:type 类型名称 [alias 别名集 ] 属性集
• 别名集 如果有多个别名,可在一对大括号中用空 格将各个别名区别开来,如:alias {aliasa_t aliasb_t} 。
• 属性集 如果同时指定多个属性标识符,属性之间使用逗号进行分隔,如:type bin_t,file_type,exec_type;
PERMISSIONS
指的是classes所被允许的操作,例如,以file为例,其PERMISSIONS就包含read,write,create,open和rename等。
MLS
TE,RBAC基本满足了“平等社会”条件下的权限管理,但它无法反映现实社会中等级的概念。为此,SELinux又添加了一种新的权限管理方法,即Multi-Lever Security,多等级安全。
多等级安全信息也被添加到SContext(也就是前面说的标签)中。所以,在MLS启用的情况下(注意,你可以控制SELinux启用MLS还是不启用MLS),完整的SContext由:
- MLS未启用前:user_u:role_r:type_t。
- MLS启用后:user:role:type:sensitivity[:category,…]- sensitivity [:category,…]。
SEAndroid其实就是安卓平台的SELinux,SELinux除了基于角色的访问控制机制(RBAC)和基于类型的访问控制机制外,还支持基于安全等级访问控制机制(MLS)。因此SEAndroid也继承此特性。
一般情况下,实施SELinux主要是基于类型进行访问控制策略的配置,但是安卓默认使用了MLS。虽然大部分情况下,只需要基于类型进行策略的编写即可满足要求,但是由于MLS默认是打开的,某些情况下会对访问、以及我们的策略配置造成影响,所以需要对MLS机制的原理和配置方法有所了解。
security level,由两部分组成
sensitivity[:category,...] - sensitivity [:category,...]
- low security level:表明当前Security Context所对应的对象的当前安全级别。
- high security level:表明当前Security Context所对应的对象的最高可能获得的安全级别
sensitivity
用sensitivity关键字定义一个sens_id,alias指定别名。
sensitivity sens_id alias [ alias_id ];
在SELinux中,真正设置sensitivity级别的是由下面这个关键词表示,括号内最左边的s0级别最低,依次递增,直到最右边的sn级别最高
dominance {s0 s1 s2.....sn}
category
category和sensitivity不同,它定义的是类别,类别之间是没有层级关系的
category cat_id alias alias_id;
senstivity和category一起组成了一个security level,由关键字level声明
level sens_id [ :category_id ];#category_id是可选的
举例: 1)level s0:c0.c255; 其中sensitivity为s0,category从c0,c1,c2一直到c255
2)重新理解前面的标签,u:r:shell:s0 ,其中Low Security Level等于High Security Level,而且Security Level没有包含Category
mlsconstrain
mlsconstrain语法和constrain基本一致
mlsconstrain class perm_set expression;
expression新增如下内容:
- l1,l2:小写的L。l1表示源的low senstivity level。l2表示target的low sensitivity。
- h1,h2:小写的H。h1表示源的high senstivity level。h2表示target的high sensitivity。
- l和h的关系,包括dom,domby,eq和incomp。
MLS在安全策略上有一个形象的描述叫no write down和no read up,意思是高级别的东西不能往低级别的东西里边写数据,低级别不能读高级别的东西。
SEAndroid
SEAndroid中的MLS:
系统中只有一个sensitivity level,即s0。
系统中有1024个category,从c0到c1023。
具体定义在system/sepolicy/private/mls_decl文件中
调试技巧(需要有root权限)
- 若某操作执行失败,如写入文件、设置property等,若怀疑是权限相关问题,可以将SELinux设置为Permissive,观察问题是否存在 a. 若存在,则与selinux无关 b. 不存在,则配置需要的selinux文件
参考
Android SELinux: source.android.com/docs/securi…