SELinux&SEAndroid简介

来源:互联网 发布:mysql if exists用法 编辑:程序博客网 时间:2024/05/21 20:28

这篇文章是替老婆写的公司内部培训PPT。

自从不搞机后,很少研究Android底层架构了,想想我搞智能机的时侯,android4.0 ICS才刚出来。现在已经是Andorid N 7.0了。时光飞逝呀。

文章的主要目的是介绍SELinux及在Android上的规则,让看人看了之后懂得SELinux安全机制是啥样的,并且知道一些常见的问题怎么入手处理。不涉及它的实现。

文章分四部分: SELinux, SEAndroid,Samples, Debug

第一部分 SELinux

1 SELinux是什么

SELinux全称Security-Enhanced Linux

由美国国家安全局NSA 和SCC(Secure Computing Corporation)发起的一个强制访问控制安全模块。在linux kernel 2.6版本后,整合到linux的安全模块中。

SElinux想要解决的是安全问题,简单地说就是,指定的进程只能访问特定的资源,执行特定的操作,而在规定之外的则不能进行操作。从而避免越权的操作,进而达到系统安全。

SELinux提供了一种灵活的强制访问控制(MAC)系统,且内嵌于Linux Kernel中。

2 传统DAC机制

DAC linux 传统的权限管理机制

全称Discretionary Access control, 自主访问控制

基于用户和分组,进程的权限取决于调起这个进程的用户的权限

按照 Owner Group Other 对访问资源的进程的权限进行定义

Root用户具有所有的访问权限

3 SELinux MAC机制

MAC Mandatory Access control, 强制性访问控制

每一项访问, 每访问一个文件资源都需要根据已定义的策略进行针对性的验证

限制Root 权限, 即使你有root 权限, 如果无法通过MAC 验证, 那么一样的无法真正执行相关的操作

对每一项权限进行了更加完整的细化, 可限制用户对资源的访问行为

4 SELinux审查流程

这里写图片描述
每个系统调用(system call)访问资源时:
先DAC审查,通过后过再进行SELinux的MAC审查

5 SELinux引入的概念

主体(subject)与客体(object)

所有资源可以分为两类: 主体和客体
主体是活的,可以主动对其他资源进行某些操作的,在linux中指进程。
客体则是死的,被动的。除了主体之外的资源(file,socket,device等)。

标签(Labels)

所有subject和object都有自己的标签,比如进程,目录,文件,设备,网终端口,主机名等资源都有自己的标签。
通过编写规则来控制某个subject标签对某个object标签的访问,这就是所谓管理政策。

如下面 u:object_r:system_file:s0 表示 用户,角色,类型,安全级别 , 这些字符串都是标签
-rwxr-xr-x root shell u:object_r:system_file:s0 dexdump

安全上下文(Security Context)

对象都有一个安全上下文(Security Context),它是一串字符串,通示标签构建。
标准格式:user:role:type:mls_level
比如u:object_r:system_file:s0

用户user与角色role

用于角色访问控制,user不是linux uid,是MAC专用的定义,一个user可以属于多个role,不同的role具有不同的权限, android只定义一个用户u和一个subject角色r,一个object角色object_r,即不使用角色访问控制功能,这里不作详述。

安全级别

主体(subject)和客体(object)都关联有一个安全级别,安全级别较高的主体可以读取安全级别较低的客体,而安全级别较低的主体可以写入安全级别较高的客体,通过这种规则,可以允许数据从安全级别较低的主体流向安全级别较高的主体,而限制数据从安全级别较高的主体流向安全级别较低的主体.Android只定义一种安全级别S0,即不使用安全级别。

类型type,域domain,类class

type: 标注资源类型。
domain:和type一样,但是只限于标注subject,即进程的类型。
class:客体(object)的类别,本质上是具有相同操作权限集合的资源类型 , 比如file,它有open,read,write等操作,就定义一个file的class,包含所有相关操作权限。

策略

指定处于什么域的subject可以对什么类型的object执行那些权限的操作.

比如:
allow appdomain app_data_file:file rw_file_perms;
表示 所有应用的域都允许读写标记有app_data_file的文件

6 SELinux审查规则

对象访问系统资源都要进行安全上下文审查,审查规则有:
类型强制检测(type enforcement)
主要的审查机制,根据对像类型和域制定权限策略。

多层安全审查(Multi-Level Security)
android只定义一种权限级别s0,没有启用多层权限。

基于角色的访问控制(RBAC: Role Based Access Control)
android只定一种用户u,没有启用角色控制。

7 类型强制检测(TE)

TE根据Type标签进行安全审查
审查 subject type 对 object type 的某个class 类型中某种permission 是否具有访问权限,是目前使用最为广泛的MAC 审查机制

策略格式:
rule subject_type target_type : class perm_set
rule:控制类型,比如allow neverallow.
subject_type:指domain
target_type:请求资源的类型
class perm_set: 对资源的操作

//init进程 创建/data/property and files
allow init property_data_file:dir create_dir_perms;
allow init property_data_file:file create_file_perms;

8 Type Transitions类型切换

Domain Transitions
一个进程fork 另外一个进程并执行(exec) 一个执行档时,为了避免新进程权限和源进程一样大,需要进行domain 切换

Object Transitions
process创建文件时, 默认是沿用父目录的Security Context, 如果要设置成特定的Label, 就必须进行Object切换。

9 SELinux模式

Permissve Mode(宽容模式)
通过Audit System 记录LOG, 但不真正拦截访问。

Enfocing mode(强制模式)
在打印LOG 的同时,还会真正的拦截访问.

在调试时,我们会启用Permissive Mode, 以便尽可能的发现多的问题, 然后一次修正. 在真正量产时使用Enforcing mode, 来保护系统.

第二部分 SEAndroid

1 SEAndroid是什么

SEAndroid 是将SELinux 移植到Android 上的产物,可以看成SELinux 辅以一套适用于Android 的策略。

特点:
只定义一个用户u和一个subject角色r,一个object角色object_r.
只定义一种权限级别s0
表明SEAndroid的安全策略只用到了类型强制检测,多层安全审查和角色访问控制都没有使用。

2 Android安全机制演变

Android的安全模型是基于应用程序沙箱(sandbox)的概念, 每个应用程序都运行在自己的沙箱之中。

Android 4.3之前:
应用程序安装时为每一个应用程序创建一个独立的uid,基于uid来控制进程权限,即DAC机制。
Android 4.3:
开启SELlinux Permissive 模式
Android 4.4:
对netd, installd, zygote, vold 四个原本具有root 权限的process, 以及它们fork 出的子进程启用Enforce 模式
Android 5.0(L):
普遍性开启SELinux Enforce mode
除了init进程,其他进程都不应该在init 域中

3 SEAndroid策略文件在那里

android rom中的路径:
/sepolicy
/file_contexts
/seapp_contexts
/service_contexts
/property_contexts
/system/etc/security/mac_permissions.xml
/selinux_version
/selinux_network.sh

android源码中路径:
external/sepolicy (通用)
device/mediatek/common/sepolicy/ 设备商定制
这里写图片描述

4 SEAndorid策略中的一些基本语法

讲解SEAndroid策略文件前,先了解一些基本语法,主要有下面三类
type
class
allow

type

type用于定义资源类型 即把资源类型和属性关联到一起
属性在后面有详细介绍
type type_id [alias alias_id,] [attribute_id]
将type_id(别名为alias)关联到attribute. 这样的话,方便用attribute来管理不同的type中包含相同的属性的部分。
例子:
type init, domain;
将init关联到domain,即将domain设置为init类型的属性

class

用于定义资源类别的权限集合
class class_name [ inherits common_name ] { permission_name … }
inherits表示继承了common定义的权限,然后自己额外实现了permission_name的权限
例子:
class dir inherits file
{
add_name
remove_name
reparent
search
rmdir
open
audit_access
execmod
}
dir继承 file的操作权限集合并增加自己的操作

allow

allow:赋予某项权限。
allowaudit:audit含义就是记录某项操作。默认情况下是SELinux只记录那些权限检查失败的操作
dontaudit:对那些权限检查失败的操作不做记录。
neverallow:用来检查安全策略文件中是否有违反该项规则的allow语句。

例子:
allow init unlabeled:filesystem mount;
允许init类型对unlabeled类型的filesystem进行mount的操作

neverallow { appdomain -unconfineddomain } kmem_device:chr_file { read write };
绝对不允许app(除了有unconfineddomain属性的app)对kmem_device类型的字符设备进行读写的操作

5 SEAndroid策略文件说明

attributes与type

TE安全策略中最基本的参量是type,同时将具有共性的type归在一起构成一个称为attribute的集合。
sepolicy的规则执行也能以attribute作为执行对象
每一个资源对应一个type, 每一个type 对应有一个或几个Attribute.

attrubites定义在external/attrubites:
attribute dev_type;
attribute domain;
attribute fs_type;
Type 的定义就比较分散, 主要有:

普通文件 type 定义在 file.te:

type pipefs, fs_type;
type sockfs, fs_type;
type rootfs, fs_type;

设备文件 type 定义在 device.te

type device, dev_type, fs_type;
type adb_device, dev_type;
type ashmem_device, dev_type, mlstrustedobject;
type audio_device, dev_type;
type binder_device, dev_type, mlstrustedobject;
type camera_device, dev_type;

security_classes:定义了所有的class标签名字。

这里写图片描述

access_vectors

access_vectors:定义每一个class被允许的操作
这里写图片描述
这里写图片描述

file_contexts

ile_contexts:保存系统中所有文件的安全上下文定义
这里写图片描述
这里写图片描述

其它文件

roles:只定义了一个role,名字就是r
users:将user与role进行了关联
global_macros:定义一些全局的宏定义
te_macros:定义一些TE策略通用操作的宏
*.te:类型强制规则文件
genfs_contexts:虚拟文件系统的安全上下文设置规则
seapp_contexts :用于app打type标签
service_contexts :系统服务安全上下文
property_contexts :系统属性安全上下文
port_contexts:网络端口安全上下文

7 Google官方SELinux策略限定

维持external/sepolicy 与Google AOSP一致, 尽量不要修改. 特别是不要去除任何的neverallow 语句.

严禁修改untrusted_app.te, 放开untrusted_app 的权限.

系统关键进程启动长时间运行的process, 必须进行domain 切换. 比如netd, installd, vold, zygote 等.

Native thread 严禁使用kernel 标签, 而kernel thread 除init 外, 都应当是kernel 标签.

在user build 中不能存在如su, recovery, init_shell 标签的进程.

在user build 中所有的process 都必须是Enforce Mode

第三部分 Samples

1 mediaserver.te类型审查说明

类型审查, 通常涉及到:

domain 类型定义
执行档 入口定义
SELinux 模式设置
domain 切换
类型访问规则

以mediaserver 这个进程的定义来说明, 对应文件是 mediaserver.te

domain 类型定义

type mediaserver, domain;

执行档 入口定义

type mediaserver_exec, exec_type, file_type;

SELinux 模式设置

在L 版本上,默认都是 enforcing mode

domain 切换

init_daemon_domain(mediaserver)
这个是一个复杂的TE操作宏, 简单来说就是当init fork 子进程执行mediaserver_exec 这个类型的执行档时, 其domain 从init 切换到mediaserver.

允许 mediaserver 访问init 的property socket

unix_socket_connect(mediaserver, property, init)

允许mediaserver 读取sdcard_type 类型的目录和文件

r_dir_file(mediaserver, sdcard_type)

允许mediaserver 使用binder 服务 和发起 binder call.

binder_use(mediaserver)
binder_call(mediaserver, binderservicedomain)
binder_call(mediaserver, appdomain)
binder_service(mediaserver)

允许mediaserver 做其他的一些操作.

allow mediaserver self:process execmem;
allow mediaserver kernel:system module_request;
allow mediaserver media_data_file:dir create_dir_perms;
allow mediaserver media_data_file:file create_file_perms;
allow mediaserver app_data_file:dir search;
allow mediaserver app_data_file:file rw_file_perms;
allow mediaserver sdcard_type:file write;
allow mediaserver gpu_device:chr_file rw_file_perms;
allow mediaserver video_device:dir r_dir_perms;

2 新的service如何添加SELinux策略

假如我们要新增一个init 启动的service,名字叫demo_service, 对应的执行档是/system/bin/demo.

1.创建一个demo.te

/device/mediatke/common/sepolicy 目录下新增demo.te, 在/device/mediatke/common/BoardConfig.mk 的BOARD_SEPOLICY_UNION 宏中新增 demo.te

2 定义demo 类型,init 启动service 时进行类型转换,

在demo.te 中
•type demo, domain;
•type demo_exec, exec_type, file_type;
•init_daemon_domain(demo)

3.绑定执行档 file_contexts 类型

/system/bin/demo u:object_r:demo_exec:s0

4.根据demo 需要访问的文件以及设备, 定义其它的权限在demo.te 中.

第四部分 Debug

1 确认问题是否有SELinux有关

将SELinux 调整到Permissive 模式测试.

将SELinux 模式调整到Permissive 模式,然后再测试确认是否与SELinux 约束相关.
ENG 版本:
adb shell setenforce 0
如果还能复现问题,则与SELinux 无关, 如果原本很容易复现, 而Permissive mode 不能再复现, 那么就可能关系比较大.

查看LOG 中是否有标准的SELinux Policy Exception.

在Kernel LOG / Main Log 中查询关键字 “avc:” 看看是否有SELinux Policy Exception, 并进一步确认这个异常是否与当时的逻辑相关.

2 SELinux Policy Exception LOG解释

SELinux Policy Exception 的LOG 关键字是 “avc: denied” 或者 “avc: denied”, 下面就是一句典型的LOG

<5> type=1400 audit: avc: denied { read write } for pid=177
comm=”rmt_storage” name=”mem” dev=”tmpfs” ino=6004 scontext=u:r:rmt:s0
tcontext=u:object_r:kmem_device:s0 tclass=chr_file

avc: denied { read write } : 拒绝 read write操作

pid=177 comm=”rmt_storage”: pid进程号 comm进程名

scontext=u:r:rmt:s0 : subject context

tcontext=u:object_r:kmem_device:s0 : object context

tclass=chr_file : class类型是chr_file(字符设备文件)

意思是rmt_storeage进程使用rmt的context访问字符设备kmem_device,并进行read write操作时,被SELinux拒绝

3 如何解决avc: denied

上面的例子中,很明显看出原因是在sepolicy 策略语言中,缺乏这样的语句allow rmt kmem_device:chr_file {read write}
所以在/external/sepolicy/ 目录下相应的te文件加入allow rmt kmem_device:chr_file {read write},重编编译,刷机即可。

4 audit2allow工具

当avc很多时,人工去看容易出错且慢,我们可以使用aduit2allow工具来完成这项工作.
audit2allow是policycoreutils中的工具之一,需要在你的linux开发环境中安装。
aduit2allow可以分析log,并自动给出建议的sepolicy语句。

adb shell su -c dmesg | audit2allow
把dmesg log输入到aduit2allow

例如上诉avc语句就会输出:
============= rmt ==============
allow rmt kmem_device:chr_file { read write };

audit2allow只是自动的帮您将LOG 转换成policy, 而无法知道你操作的真实意图,有可能出现权限放大问题,导致被Google默认的neverallow规则拒绝,出现policy 无法编译通过的情况。

最好把audit2allow的输出作为参考,再参考neverallow规则,自己定义sepolicy策略语句。

0 0
原创粉丝点击