Android SELinux开发入门指南之SELinux基础知识

   Android SELinux开发入门指南之SELinux基础知识


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涉及的基本知识比较多,下面让我们来一一细说。

1.1 SELinux的三种模式

SELinux分为三种模式,下面我们看看究竟是那三种模式:

  • Disable模式
    此种模式关闭SELinux检测,不进行任何SELinux权限检查,畅通无阻。

  • Permissive模式
    宽容模式,当权限检查不通过时,不决绝资源访问,只打印avc log日志。

  • Enforceing模式
    强制模式,此种模式下权限检查不通过时,拒绝资源访问,并打出avc log,这个是最恨模式。


1.2 查看SELiux状态和关闭SELinux

查看SElinux的状态:
查看SELinux状态比较简单,可以通过命令行查看SELinux状态:

adb  shell getenforce

还有一种就是通过avc log来确认SELinux的状态:
如果是avc log结尾有permissive=1/0的标识,如果permissive=1说明是Permissive模式模式,如果permissive=0则说明是Enforce模式。

关闭SELinux:
关于怎么关闭SELinux可以参考如下的博文正确姿势临时和永久关闭Android的SELinux里面有比较详细的讲解。


1.3 SEAndroid app分类和其他

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(系统属性)主要描述系统属性相关


1.4 seapp_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。


1.5 user和seinfo判定方式

首先看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。


1.6 RBAC和constrain

由前文可知,.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


1.7 小技巧

使用allow和neverallow语句的时候,可以使用下面的一些小技巧来简化命令书写;

  • ”号,表示除了””以外

  • ”-”号,表示去除某项内容

  • ”*”号,表示所有内容


1.8 SELinux 策略构建和客制化

在Android8.0中,SELinux策略分离成平台(platform)和非平台(non-platform)两部分,而平台策略为了给非平台策略导出特定的类型和属性,又分为平台私有(platform private)和平台公有(platform public)部分。

1.8.1.平台公有策略(platform public seoplicy)

平台共有策略全部定义在/system/sepolicy/public下,public下的type和attribute可以被non-platform中的策略所使用,也就是说,设备制造商的sepolicy策略在non-platform下可以对platform public sepolicy的策略进行扩展。

1.8.2.平台私有策略(platform private seoplicy)

与公有策略相反,被声明为私有策略的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和非平台的也可以共享它。

1.8.3.平台私有映射

映射主要针对旧版本的映射,应用比较少,这里不作研究;

1.8.4 SELinux策略开发小技巧

为了快速的开发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目录了。


1.9 快速编译验证SELinux策略

我们将策略文件或者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基础知识已经全部完毕,希望能吸引你,激活发你的学习欲望和斗志。在最后麻烦读者朋友们如果本篇对你有帮助,关注和点赞一下,当然如果有错误和不足的地方也可以拍砖。

  • 20
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值