1.前言
在Linux中NSN开发了SELinux,来保护linux系统的安全,因为Android有着独特的用户运行时空间,
所以SELinux并不完全适用Android,故而在SELinux的基础上有了SEAndroid,SEAndroid主要保护的
对象就是系统中的资源例如文件,属性等和系统中的进程,Socket,IPC等。
2.SELinux的整体结构
在SEAndroid的整体结构中,通过SELinux的文件系统,将其划分为了用户空间和内核空间。用户空间中包含了
Security Context,Security Server,selinux库libselinux。内核空间包含了LSM.
1.Security Context:描述了对象安全上下,安全策略就是由资源安全上下文决定的
2.Security Server:一方面到Security Context中去检索安全上下文,另一方面也到内核空间操作安全上下文
3.SEAndroid Policy:安全策略。在系统启动的时候,Security Server会将其加载到内核空间的LSM中。
4.libselinux:是SELinux库,可以用来读写SELinux文件系统,加载SEAndroid Policy,检索和操作安全上下文等都是由libselinux完成的
5.LSM:负责内核资源的访问控制
3.内核空间
LSM:LSM是内核MAC机制的一个通用的模块,而SEAndroid仅仅是LSM的一个实现。这体现了内核设计的一个思想。在LSM中包含了Access Vector Cache
和Security Server两个模块。当要访问一个资源的时候,首先会到Access Vector Cache检查是否允许访问,如果不允许访问,则到Security Server
中查询是否可以访问,如果可以访问在访问的同时,也会在Access Vector Cache中将结果进行保存。
SELinux LSM 和内核子系统的交互:当访问内核子系统中的资源的时候,LSM就会调用他的Hook代码,而Hook代码就会回调SELinux中的回调方法。
例如当调用系统的read函数的时候,进入到内核子系统中的文件系统。在文件子系统中负责读取文件的vfs_read函数,就会回调LSM加入的Hook代码,
Hook代码就会回调SELinux中的回调函数,以确保安全性的检查
安全访问资源的流程:
进行了三次错误性检查:
1. 检查对象是否存在,访问参数是否正确等
2. Linux UID/GID是否允许
3. 安全策略是否允许
4.用户空间
1.Security Context:对象安全上下文,用来定制安全策略。由用户,角色,类型和安全级别组成。在第一篇文章我们可知
查看上下文的方法。对象安全上下文又分为主体(指进程)和客体(指资源如文件等)。
其实用户和角色并不重要,重要的是类型。下面分别来对其进行介绍。
用户和角色只是用来限制进程可以标注的类型,而对文件来说是可以完成不记的。对所有主体和客体来说,只有一个SELinux用户,那就是
u(系统中只定义了这一个SELinux用户),对客体来说通常将它的角色定为object_r。而对所有的主体来说,只定义了一个角色那就是r。
在src/system/sepolicy/private/users中可以看到系统定义的SELinux用户
user u roles { r } level s0 range s0 - mls_systemhigh;
表明了一个SELinux的用户u,他可用的角色为r,安全级别默认为s0,而安全级别的范围为s0-mls_systemhigh
在src/system/sepolicy/private/roles_decl中可以看到角色的定义
role r;
在src/system/sepolicy/public/roles中可以看到角色可以关联的类型:
role r types domain;
表明角色r可以关联的类型为domain
可以看到u和r关联,而r又和类型domain关联。换句话说如果没有定义其他的用户,角色和类型,那么只有u,r和domain的组合才是正确的。
可是我们又会看到
$ ps -Z
LABEL USER PID PPID NAME
u:r:init:s0 root 1 0 /init
难道u:r:init:s0的组合是错误的吗?当然不是了。在src/system/sepolicy/public/init.te中
type init, domain, mlstrustedsubject;表明了将domain定义为init的属性,那么能用domain的地方就能用init.所以上面的说法也是正确的。
安全级别:在SELinux中安全级别是由敏感性(sensitivity)和类别(category)两部分组成的.但是类别这部分是可以省略的。一般的形式为sensitivity[:category]
如由敏感性s0和策略c0,c1组成的安全级别就为s0[:c0,c1]. 在SEAndroid中,低安全级别可以向高安全级别的写入数据,但是不能读。高安全级别的可以读取低安全
级别的数据,但是不能写入。如果两个安全级别是相同的,那么既可以读又可以写。
类型:类型是SEAndroid中最为重要的。在src/system/sepolicy/public/roles中我们可以看到
role r types domain
domain表示的是进程的类型。每一个进程的类型都会将domain作为属性,每一个文件的类型都会将file_context作为属性。
那么安全策略又是如何定义的呢?
主要分析四种安全策略的定义,app进程,app数据文件,系统文件已经系统属性。与其相关的文件有
src/system/sepolicy/private/mac_permissions.xml,src/system/sepolicy/private/seapp_contexts,src/system/sepolicy/private/file_contexts,
property_contexts.
安全策略的确定首先要确定安全上下文,其实也就是确定最为重要的类型。
看mac_permissions.xml
如果我们的app使用的是系统的签名,那么从该文件中得知,对应的seinfo为platform.从当前代码中我们可以看到系统只提供了两个签名(nexus8.1的代码),如果
还有其他的签名的app怎么办?从注释中我们可以看到,它将会用seinfo为"default"。seinfo并不是app进程的类型,接下来再看seapp_contexts文件
# Input selectors:
# isSystemServer (boolean)
# isEphemeralApp (boolean)
# isV2App (boolean)
# isOwner (boolean)
# user (string)
# seinfo (string)
# name (string)
# path (string)
# isPrivApp (boolean)
# minTargetSdkVersion (unsigned integer)
# isSystemServer=true can only be used once.
# An unspecified isSystemServer defaults to false.
# isEphemeralApp=true will match