SELinux (Security Enhanced Linux)是由美国NSA(国安局)和 SCC 开发的 Linux 的一个扩张强制访问控制安全模块,目的是最大限度减少系统中服务进程可访问的资源。Google 在 Android 4.4 上正式添加以 SELinux 为基础的系统安全机制,命名为SEAndroid。SEAndroid 在架构和机制上与 SELinux 完全一样,基于移动设备的特点,SEAndroid 的只是所以移植 SELinux 的一个子集。
当程序要操作文件时,系统根据程序的 Owner/Group,对比文件的权限,若通过权限检查,则可操作文件,但可能造成问题:
以进程为主体,任何进程想在系统上干任何事情,都必须在《安全策略文件》中赋予权限。
//获取SeLinux模式
adb shell getenforce
//设置SeLinux模式为Enforcing(只允许Enforcing和Permissive之间切换)
adb shell setenforce 1
//设置SeLinux模式为Permisssive
adb shell setenforce 0
SELinux 安全策略是建立在对象安全上下文的基础上的,对象可以分为两种:
在 SELinux 中,每种东西都会被 Policy 赋予一个安全属性,官方说法叫做 Security Context(sContext),sContext 是一个字符串。根据 SELinux 规范,完整的 sContext 字符串主要由三个部分组成:user:role:type[:range]
u
r
,客体等role为object_r
可以通过命令ps -Z
查看进程的 sContext,通过命令ls -Z
查看文件的 sContext
定义sContext标准格式为:resource sContext
,其都定义在type_contexts
当中,例如file的定义在 file_contexts
中,service定义在 service_contexts
中,property 定义在property_contexts
中
//file_contexts示例,指定 adb_keys 文件的 sContext 为 u:object_r:adb_keys_file:s0
/adb_keys u:object_r:adb_keys_file:s0
//service_contexts示例,指定名为 account 的 service 的 sContext 为 u:object_r:account_service:s0
account u:object_r:account_service:s0
SELinux 中每一个进程或者文件都对应一个type, 而每一个type 都对应有一个或几个attribute。属性类似一个组,type 关联属性之后, 新增的 type 就可以加入到这个属性组中,这个属性(组)拥有的权限, 新增的type也就自然拥有了这个权限)。
system/sepolicy/*/*.te
)//type 类型名称;
//例如
type domain;
//typealias 类型名称 alias 别名;
//例如
typealias mozilla_t alias netscape_t;
system/sepolicy/*/attributes
文件中attribute XXXX;
//例如
attribute domain;
//app_data_file类型,关联 file_type、data_file_type 两个属性
type app_data_file, file_type, data_file_type
SELinux 对于不同的资源类型,定义了不同的class,比如普通的file
、socket
等等,每一个 class 都有相对应的 permissions, 比如 file 就有 read, write, create, getattr, setattr, lock, ioctl 等等。这些相关的class、permissions都定义在system/sepolicy/*/access_vectors
文件中
common file
{
ioctl
read
write
... ...
}
common socket
{
connect
listen
accept
...
}
定义完之后,在对应的 security_classes 文件(system/sepolicy/*/security_classes
)中声明定义的classes
class file
class dir
class fd
在system/sepolicy/public/global_macros
文件中有定义,例如:
define(`w_file_perms`,`{open append write lock map}`)
//Domain:主体,进程类型
//Type:客体,对象类型
//Class:客体的class。
//Permission:要执行的操作(例如,读取、写入)。
allow domains types:classes permissions;
allow domain {type1 type2}:file execute;
allow {domain1 domain2} {type1 type2 type3}:file {execute read };
allow domain type:{ file dir } { read getattr };
allow:表示容许主体对客体执行许可的操做。
neverallow:表示不容许主体对客体执行制定的操做。
auditallow: 表示容许操做并记录访问决策信息。
dontaudit:表示不记录违反规则的决策信息,切违反规则不影响运行。
SEAndroid将app划分为主要三种类型(根据user不同,也有其他的domain类型)
untrusted_app
:第三方app,没有Android平台签名,没有system权限platform_app
:有android平台签名,没有system权限system_app
:有android平台签名和system权限untrusted_app_25
:第三方app,没有Android平台签名,没有system权限//访问主体是 demo_service,对应的 sContext 的 type 是 system_server
//对default_android_service,类型是service_manager,缺少 add 权限
avc: denied { add } for pid=9981 uid=1000 name=demo_service scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager permissive=0
//在 service_contexts 文件中为 demo_service 定义 sContext
demo_service u:object_r:demo_service_type:s0
//在 te 文件中定义 demo_service 的 type,且关联 app_api_service、system_server_service、service_manager_type 属性
type demo_service_type, app_api_service, system_server_service, service_manager_type;
//在 te 文件中进行授权
allow system_server demo_service_type:service_manager {add find};