赞
踩
Android SELinux开发多场景实战指南目录:
Android SELinux开发入门指南之SELinux基础知识
Android SEAndroid权限问题指南
Android SELinux开发入门指南之如何增加Java Binder Service权限
Android SELinux开发入门指南之权限解决万能规则
Android SELinux开发入门指南之如何增加Native Binder Service权限
Android SELinux开发入门指南之正确姿势解决访问data目录权限问题
正确姿势临时和永久关闭Android的SELinux
SEAndroid是在Android系统中基于SELinux推出的强制访问控制模型,其被设计的主要意图就是用来来完善自主访问模型中只要取得root权限就可以为所欲为的情况。那么SELinux究竟是何方神圣呢,老规矩认识一个事物我们通常会从它是什么,怎么使用它,最后深入它的三个步骤来进行,我们这里对SELinux也是如此,秉承三部曲的节奏来进行!
我们先对SELinux来一个整体的概述那就是SELinux是一种基于域-类型(domain-type)模型的强制访问控制(MAC)安全系统,其原则是任何进程想在SELinux系统中干任何事,都必须先在安全策略的配置文件中赋予权限。凡是没有在安全策略中配置的权限,进程就没有该项操作的权限。在SELinux出现之前,Linux的安全模型是DAC(DiscretionaryAccess Control),译为自主访问控制。其核心思想是进程理论上所拥有的权限与运行它的用户权限相同。比如,以root用户启动shell,那么shell就有root用户的权限,在Linux系统上能干任何事。这种管理显然比较松散。在SELinux中,如果需要访问资源,系统会先进行DAC检查,不通过则访问失败,然后再进行MAC权限检查。
SELinux涉及的基本知识比较多,下面让我们来一一细说。
SELinux分为三种模式,下面我们看看究竟是那三种模式:
Disable模式
此种模式关闭SELinux检测,不进行任何SELinux权限检查,畅通无阻。
Permissive模式
宽容模式,当权限检查不通过时,不决绝资源访问,只打印avc log日志。
Enforceing模式
强制模式,此种模式下权限检查不通过时,拒绝资源访问,并打出avc log,这个是最恨模式。
查看SElinux的状态:
查看SELinux状态比较简单,可以通过命令行查看SELinux状态:
adb shell getenforce
还有一种就是通过avc log来确认SELinux的状态:
如果是avc log结尾有permissive=1/0的标识,如果permissive=1说明是Permissive模式模式,如果permissive=0则说明是Enforce模式。
关闭SELinux:
关于怎么关闭SELinux可以参考如下的博文正确姿势临时和永久关闭Android的SELinux里面有比较详细的讲解。
SELinux(或SEAndroid)将app划分为主要三种类型(根据user不同,也有其他的domain类型):
untrusted_app 第三方app,没有Android平台签名,没有system权限
platform_app 有android平台签名,没有system权限
system_app 有android平台签名和system权限
untrusted_app_25 第三方app,没有Android平台签名,没有system权限,其定义如下This file defines the rules for untrusted apps running with targetSdkVersion <= 25.
从上面划分,权限等级,理论上:untrusted_app < platform_app < system_app按照这个进行排序property_contexts(系统属性)主要描述系统属性相关
seapp_contexts定义在system/sepolicy/seapp_contexts数据文件,如下
isSystemServer=true domain=system_server
user=system seinfo=platform domain=system_app type=system_app_data_file
user=bluetooth seinfo=platform domain=bluetooth type=bluetooth_data_file
user=nfc seinfo=platform domain=nfc type=nfc_data_file
user=radio seinfo=platform domain=radio type=radio_data_file
user=shared_relro domain=shared_relro
user=shell seinfo=platform domain=shell type=shell_data_file
user=_isolated domain=isolated_app levelFrom=user
user=_app seinfo=platform domain=platform_app type=app_data_file levelFrom=user
user=_app domain=untrusted_app type=app_data_file levelFrom=user
从上面可以看出,domain和type由user和seinfo两个参数决定。
比如:
user=system seinfo=platform,domain才是system_app
user=_app,可以是untrusted_app或platform_app,如果seinfo=platform,则是platform_app。
首先看user,user可以理解为UID,例如ps -Z结果如下:
u:r:system_app:s0 system 2414 1172 com.android.keychain
u:r:platform_app:s0 u0_a6 2439 1172 com.android.managedprovisioning
u:r:untrusted_app:s0 u0_a8 2460 1172 com.android.onetimeinitializer
u:r:system_app:s0 system 2480 1172 com.android.tv.settings
u:r:untrusted_app:s0 u0_a27 2504 1172 com.android.email
u:r:untrusted_app:s0 u0_a28 2523 1172 com.android.exchange
u:r:untrusted_app:s0 u0_a7 2567 1172 com.android.musicfx
第一列是SContext,第二列是UID,只要UID是system的基本都是system_app,反过来一样。
其他的U0_XXX要么属于platform_app或untrusted_app
seinfo由external\sepolicy\mac_permissions.xml决定,内容如下:
<!-- Platform dev key in AOSP -->
<signer signature="@PLATFORM" >
<seinfo value="platform" />
</signer>
<!-- All other keys -->
<default>
<seinfo value="default" />
</default>
即如果签名是platform,seinfo就是platform,其他的比如shared等,seinfo是default。
比如上面ps -Z的结果里面,OneTimeInitializer.apk是untrusted_app,ManagedProvisioning.apk是platform_app。
分别查看这两个app的Android.mk
packages\apps\OneTimeInitializer\Android.mk 没有定义LOCAL_CERTIFICATE,默认是shared
packages\apps\ManagedProvisioning\Android.mk 有定义LOCAL_CERTIFICATE := platform
因为ManagedProvisioning.apk有platform签名,所以seinfo是platform。
由前文可知,.te文件内部包含各种allow, type等语句,这些都是TEAC(type enforcement access control),属于SELinux MAC中的核心组成部分。
在TEAC之上,SELinux还有一种基于Role的安全策略,也就是RBAC(role based access control)。
e.g.
constrain file write (u1 == u2 and r1 == r2)
这句话表示只有source和targe的user相同,并且role也相同,才允许write file
使用allow和neverallow语句的时候,可以使用下面的一些小技巧来简化命令书写;
””号,表示除了””以外
”-”号,表示去除某项内容
”*”号,表示所有内容
在Android8.0中,SELinux策略分离成平台(platform)和非平台(non-platform)两部分,而平台策略为了给非平台策略导出特定的类型和属性,又分为平台私有(platform private)和平台公有(platform public)部分。
平台共有策略全部定义在/system/sepolicy/public下,public下的type和attribute可以被non-platform中的策略所使用,也就是说,设备制造商的sepolicy策略在non-platform下可以对platform public sepolicy的策略进行扩展。
与公有策略相反,被声明为私有策略的type或attribute对non-platform的策略是不可见的,这里有些费解,我们举例来说,这里以8.0版本的aosp源代码中的/system/sepolicy/private/目录下的atrace.te文件为例;
8.0版本的aosp中的/system/sepolicy/private/file_contexts定义了“/system/bin/atrace u:object_r:atrace_exec:s0”
然后在/system/sepolicy/private/atrace.te中定义atrace相关的规则;
我们在device/qcom/sepolicy/common目录下新增一个atrace.te文件,并添加规则 “allow atrace sdcardfs:file read;”
当我们make进行编译时会在校验的时候失败,提示我们“device/qcom/sepolicy/common/atrace.te:2:ERROR ‘unknown type atrace’ at token ‘;’ on line 23355”,那么也就是说private策略中的type和attribute对我们是不可见的。
这里有一点需要注意的是public的SContext安全上下文只有平台和非平台之分,也就是说,定义在平台private下面file_contexts属性,public和非平台的也可以共享它。
映射主要针对旧版本的映射,应用比较少,这里不作研究;
为了快速的开发SELinux的相关策略,我们通常不会将策略文件定义到Android aosp的system/sepolicy目录下面,而是通常会将platform或者non-plarform定义到自己的device目录下面,Android的设计者也考虑到了这个问题,在system/sepolicy/Android.mk定义了如下的一些宏,可以将我们定制的平台策略和非平台策略整合编译,定义的有如下几个:
BOARD_SEPOLICY_DIRS ##此宏涉及到的目录,会编译到vendor/etc/sepolicy下
PLAT_PUBLIC_POLICY ##此宏涉及到的目录,会当成system/sepolicy/public
PLAT_PRIVATE_POLICY##此宏涉及到的目录,会当成system/sepolicy/private
我们可以在自己的device的BoardConfig.mk下面对上述的宏赋值,这样就可以避免直接修改system/sepolicy目录了。
我们将策略文件或者SELinux修改好以后,怎么快速的验证或者编译了,不要再直接make整个Android系统了,这样耗时又麻烦,我们可以通过如下的命令快速编译:
xxx:#= make selinux_policy
接着将生成的策略文件push到Android设备终端,重启设备终端即可,这里我放上我经常使用的一个push脚本,如下:
adb push /xxx/system/etc/selinux/* /system/etc/selinux/
adb push /xxx/vendor/etc/selinux/* /vendor/etc/selinux/
adb push /xxx/system/system_ext/etc/selinux/* /system/system_ext/etc/selinux/
adb push /xxx/system/product/etc/selinux/* /system/product/etc/selinux/
adb shell sync
adb shell sync
adb reboot
修行至此,上述就是本人总结的在实际开发工作中经常使用到的相关SElinux的重点基础知识,希望对各位有所帮组,各位江湖见。
各位读者看官朋友们,Android SELinux开发入门指南之SELinux基础知识已经全部完毕,希望能吸引你,激活发你的学习欲望和斗志。在最后麻烦读者朋友们如果本篇对你有帮助,关注和点赞一下,当然如果有错误和不足的地方也可以拍砖。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。