selinux的使用

(一)权限(Permission denied)问题如何确认是Selinux 约束引起

在Android KK 4.4 版本后,Google 有正式有限制的启用SELinux, 来增强android 的安全保护。
SELinux 分成enforcing mode 和 permissive mode, enforcing mode 会强制性限制访问; 而permissve mode 只审查权限, 但不限制, 即不会产生实质性影响.

KK 版本, Google 只有限制的启用SELinux, 即只有针对netd, installd, zygote, vold 以及它们直接fork 出的child process 使用enforcing mode, 但不包括zygote fork的普通app.
L 版本后, Google 全面开启SELinux, 所有的process 都使enforcing mode, 影响面非常广.

另外为了限制user 版本root 权限,针对su 有做特别的处理,可以参考FAQ android KK 4.4 版本后,user 版本su 权限严重被限制问题说明

目前所有的SELinux check 失败,在kernel log 或者android log(L版本后)中都有对应的"avc: denied" 或者 "avc: denied"的LOG 与之对应。反过来,有此LOG,并非就会直接失败,还需要确认当时SELinux 的模式, 是enforcing mode 还是 permissve mode, 通常在LOG 上带有 permissive = 1 即是permissive mode, 否则permissve = 0 即是enforcing mode.

如果问题容易复现,我们可以先将SELinux 模式调整到Permissive mode,然后再测试确认是否与SELinux 约束相关.
在ENG 版本中:
adb shell setenforce 0
如果设置成permissive mode 后问题依旧,说明还有其他的权限问题约束,否则就是SELinux 方面的问题

(二)如何快速验证 SELinux Policy 问题

修改了SELinux Policy 配置后,快速进行Debug 确认

[Keyword]
android, SELinux, SELinux Policy, SELinux Debug

[Solution]
在Android KK 4.4 版本后,Google 有正式有限制的启用SELinux, 来增强android 的安全保护。
KK 版本: 在MTK Solution 中,将SELinux Policy 文件存放在三个目录中。

  • 1). Google 原生目录 external/sepolicy
  • 2). MTK 配置目录 mediatek/custom/common/sepolicy
  • 3). 客户配置目录 mediatek/custom/{Project}/sepolicy (默认没有配置)
    在编译时,系统会以文件为单位整合替换,优先级: 客户配置目录 》MTK 配置目录 》 Google 原生目录.

L 版本以后: 将SELinux Policy 文件存放在下面目录。

  • 1). Google 原生目录 external/sepolicy
  • 2). MTK 配置目录 device/mediatek/common/sepolicy
  • 3). MTK 配置目录 device/mediatek/{platform}/sepolicy (M版本后才添加使用,主要是针对平台客制化) 在编译时, 系统会以合并的方式(union), 将MTK 配置目录下的policy 附加到Google 原生的policy 上,而非替换. 如果在device/mediatek/common/sepolicy 下面新增SELinux Policy file, 在L 版本需要更新device/mediatek/common/BoardConfig.mk 中的BROAD_SEPOLICY_UNION 增加对应的xxxx.te, M 版本已经取消了这个宏,无需再操作.

快速编译验证
在已经编译过的版本上, 首先编译出新的selinux policy, 然后打包boot image.
KK: ./mk project_name mm external/sepolicy
./mk project_name bootimage

L:
mmm external/sepolicy
make -j24 ramdisk-nodeps
make -j24 bootimage-nodeps

然后再重新刷bootimage 测试.

(三)设置SELinux 策略规则 ? 在Kernel Log 中出现"avc: denied" 要如何处理?

android KK 4.4 版本后,Google 默认启用了SELinux, 并会把SELinux 审查异常打印在kernel log 或者 android log(L 版本)中,对应的关键字是: “avc: denied” 或者"avc: denied"
如一行LOG:
<5>[ 17.285600].(0)[503:idmap]type=1400 audit(1356999072.320:202): avc: denied { create } for pid=503 comm=“idmap” name=“overlays.list” scontext=u:r:zygote:s0 tcontext=u:object_r:resource_cache_data_file:s0 tclass=file
即表明idmap 这个process, 使用zygote 的source context, 访问/data/resource_cache 目录,并创建文件时,被SELinux 拒绝访问。

[Keyword]
android, SELinux, avc: denied, audit

[Solution]
KK 版本, Google 只有限制的启用SELinux, 即只有针对netd, installd, zygote, vold 以及它们直接fork 出的child process 使用enforcing mode, 但不包括zygote fork的普通app.
L 版本, Google 全面开启SELinux, 几乎所有的process 都使enforcing mode, 影响面非常广.

目前所有的SELinux check 失败,在kernel log 或者android log(L版本后)中都有对应的"avc: denied" 或者 "avc: denied"的LOG 与之对应。反过来,有此LOG,并非就会直接失败,还需要确认当时SELinux 的模式, 是enforcing mode 还是 permissve mode.
首先, 务必确认对应进程访问系统资源是否正常, 是否有必要 ?如果本身是异常非法访问,那么就要自行消除访问。
其次, 如果确认访问是必要,并且正常的,那么就要对对应的process/domain 增加新的policy.

1). 简化方法
  • 1.提取所有的avc LOG. 如 adb shell “cat /proc/kmsg | grep avc” > avc_log.txt
  • 2.使用 audit2allow tool 直接生成policy. audit2allow -i avc_log.txt 即可自动输出生成的policy
  • 3.将对应的policy 添加到selinux policy 规则中,对应MTK Solution, 您可以将它们添加在KK: mediatek/custom/common/sepolicy, L: device/mediatek/common/sepolicy
    下面,如

allow zygote resource_cache_data_file:dir rw_dir_perms;
allow zygote resource_cache_data_file:file create_file_perms;
===> mediatek/custom/common/sepolicy/zygote.te (KK)
===> device/mediatek/common/sepolicy/zygote.te (L)
注意audit2allow 它自动机械的帮您将LOG 转换成policy, 而无法知道你操作的真实意图,有可能出现权限放大问题,经常出现policy 无法编译通过的情况。

2). 按需确认方法

此方法需要工程人员对SELinux 基本原理,以及SELinux Policy Language 有了解.

  • 2.1 确认是哪个进程访问哪个资源,具体需要哪些访问权限,read ? write ? exec ? create ? search ?
  • 2.2 当前进程是否已经创建了policy 文件? 通常是process 的执行档.te,如果没有,并且它的父进程即source context 无须访问对应的资源,则创建新的te 文件.
    在L 版本上, Google 要求维护关键 security context 的唯一性, 比如严禁zygote, netd, installd, vold, ueventd 等关键process 与其它process 共享同一个security context.
  • 2.3 创建文件后,关联它的执行档,在file_contexts 中, 关联相关的执行档. 比如 /system/bin/idmap 则是 /system/bin/idmap u:object_r:idmap_exec:s0
  • 2.4 填写policy 到相关的te 文件中 如果沿用原来父进程的te 文件,则直接添加. 如果是新的文件,那么首先:

Type Declaration

#==============================================
type idmap, domain;
type idmap_exec, exec_type, file_type;

#==============================================

Android Policy Rule

#==============================================
#permissive idmap;
domain_auto_trans(zygote, idmap_exec, idmap);

然后添加新的policy

new policy

allow idmap resource_cache_data_file:dir rw_dir_perms;
allow idmap resource_cache_data_file:file create_file_perms;

3). 权限放大情况处理

如果直接按照avc: denied 的LOG 转换出SELinux Policy, 往往会产生权限放大问题. 比如因为要访问某个device, 在这个device 没有细化SELinux Label 的情况下, 可能出现:
<7>[11281.586780] avc: denied { read write } for pid=1217 comm=“mediaserver” name=“tfa9897” dev=“tmpfs” ino=4385 scontext=u:r:mediaserver:s0 tcontext=u:object_r:device:s0 tclass=chr_file permissive=0
如果直接按照此LOG 转换出SELinux Policy: allow mediaserver device:chr_file {read write}; 那么就会放开mediaserver 读写所有device 的权限. 而Google 为了防止这样的情况, 使用了neverallow 语句来约束, 这样你编译sepolicy 时就无法编译通过.
为了规避这种权限放大情况, 我们需要细化访问目标(Object) 的SELinux Label, 做到按需申请. 通常会由三步构成

  • 3.1 定义相关的SELinux type.
    比如上述案例, 在 device/mediatek/common/sepolicy/device.te 添加
    type tfa9897_device, dev_type;
  • 3.2 绑定文件与SELinux type.
    比如上述案例, 在 device/mediatek/common/sepolicy/file_contexts 添加
    /dev/tfa9897(/.*)? u:object_r:tfa9897_device:s0
    安全上下文实际上就是一个附加在对象上的标签(Tag)。这个标签实际上就是一个字符串,它由四部分内容组成,分别是SELinux用户、SELinux角色、类型、安全级别,每一个部分都通过一个冒号来分隔,格式为“user:role:type:sensitivity”
  • 3.3 添加对应process/domain 的访问权限.
    比如上述案例, 在 device/mediatek/common/sepolicy/mediaserver.te 添加
    allow mediaserver tfa9897_device:chr_file { open read write };

那么哪些访问对象通常会遇到此类呢?(以L 版本为例)
* device
– 类型定义: external/sepolicy/device.te;device/mediatek/common/sepolicy/device.te
– 类型绑定: external/sepolicy/file_contexts;device/mediatek/common/sepolicy/file_contexts

  • File 类型:
    – 类型定义: external/sepolicy/file.te;device/mediatek/common/sepolicy/file.te
    – 绑定类型: external/sepolicy/file_contexts;device/mediatek/common/sepolicy/file_contexts

  • 虚拟File 类型:
    类型定义: external/sepolicy/file.te;device/mediatek/common/sepolicy/file.te
    绑定类型: external/sepolicy/genfs_contexts;device/mediatek/common/sepolicy/genfs_contexts

  • Service 类型:
    类型定义: external/sepolicy/service.te; device/mediatek/common/sepolicy/service.te
    绑定类型:external/sepolicyservice_contexts;device/mediatek/common/sepolicy/service_contexts

  • Property 类型:
    类型定义: external/sepolicy/property.te;device/mediatek/common/sepolicy/property.te
    绑定类型: external/sepolicy/property_contexts;device/mediatek/common/sepolicy/property_contexts;

通常我们强烈反对更新google default 的policy, 大家可以更新mediatek 下面的相关的policy.


本部分来自 u010867436 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/u010867436/article/details/50916131?utm_source=copy

几个解决selinux的案例,

原则:缺什么,补什么,一步一步补到没有avc denied为止。

 audit(0.0:67): avc: denied { write } for path="/dev/block/vold/93:96" dev="tmpfs" ino=1263 scontext=u:r:kernel:s0 tcontext=u:object_r:block_device:s0 tclass=blk_file permissive=0

分析过程:

缺少什么权限: { write }权限,

谁缺少权限: scontext=u:r:kernel:s0,

对哪个文件缺少权限:tcontext=u:object_r:block_device

什么类型的文件: tclass=blk_file
解决方法:kernel.te

allow kernel block_device:blk_file write;

audit(0.0:53): avc: denied { execute } for path="/data/data/com.mofing/qt-reserved-files/plugins/platforms/libgnustl_shared.so" dev="nandl" ino=115502 scontext=u:r:platform_app:s0 tcontext=u:object_r:app_data_file:s0 tclass=file permissive=0

解决方法 :platform_app.te

allow platform_app app_data_file:file execute;

audit(1444651438.800:8): avc: denied { search } for pid=158 comm="setmacaddr" name="/" dev="nandi" ino=1 scontext=u:r:engsetmacaddr:s0 tcontext=u:object_r:vfat:s0 tclass=dir permissive=0

解决方法 :engsetmacaddr.te

allow engsetmacaddr vfat:dir { search write add_name create }; 或者

allow engsetmacaddr vfat:dir create_dir_perms;

audit(1441759284.810:5): avc: denied { read } for pid=1494 comm="sdcard" name="0" dev="nandk" ino=245281 scontext=u:r:sdcardd:s0 tcontext=u:object_r:system_data_file:s0 tclass=dir permissive=0

解决方法 :sdcardd.te

allow sdcardd system_data_file:dir read; 或者
allow sdcardd system_data_file:dir rw_dir_perms
(rw_dir_perms包含read write,可以参考external/sepolicy/global_macros的定义声明)

通过这四个案例,我们可以总结出一般规律,

以第4个为例

允许某个scontext对某个tcontext拥有某个权限

我们的log重新排列一下,

scontext=u:r:sdcardd

tcontext=u:object_r:system_data_file:s0

tclass=dir

avc: denied { read }

得到万能套用公式如下:

在scontext所指的te文件中加入类似如下内容:

以上以.te为后缀的文件都在external/sepolicy/或者device/softwinner/xxxx-commm/sepolicy/下,修改之后,都要重刷boot.img。

补充说明:

  1. 有时候avc denied的log不是一次性显示所有问题,要等你解决一个权限问题之后,才会提示另外一个权限问题。比如提示确实某个目录的read权限,你加入read之后,再显示缺少write权限,要你一次次一次试,一次一次加。这时你可以简单粗暴写个rw_dir_perms,这个权限包含了{open search write …}等等很多权限。

可以查看external/sepolicy/global_macros来了解更多权限声明;

  1. 要加入的权限很多时,可以用中括号,比如
    allow engsetmacaddr vfat:dir { search write add_name create};

  2. 遇到问题不确定是否由于selinux问题造成,可先在adb shell 下,输入setenforce 0,让selinux失效,看是否问题还出现。以此可以澄清是非selinux造成的问题。

以上基本是对已经存在的进程增加权限,但对第三方进程改如何新增一个全新的te文件并赋予权限呢?

以写mac地址的setmacaddr执行文件为例(这个执行档android原生不存在,自行添加的):

  1. 在external/sepolicy/file_contexts中,参考其他进程声明一个:
    /system/bin/install-recovery.sh u:object_r:install_recovery_exec:s0
    /system/bin/dex2oat u:object_r:dex2oat_exec:s0
    /system/bin/patchoat u:object_r:dex2oat_exec:s0
    /system/bin/setmacaddr u:object_r:engsetmacaddr_exec:s0
    指定setmacaddr的路径,并指定一个名字,一定要以_exec结尾

2.参考其他文件在external/sepolicy/ 创建engsetmacaddr.te文件,内容如下:

type engsetmacaddr, domain;
type engsetmacaddr_exec, exec_type, file_type;
init_daemon_domain(engsetmacaddr)
allow engsetmacaddr vfat:dir { search write add_name create};
allow engsetmacaddr vfat:file { create read write open };
allow engsetmacaddr engsetmacaddr:capability dac_override;
allow engsetmacaddr shell_exec:file { execute read open execute_no_trans};
allow engsetmacaddr system_data_file:dir { write add_name remove_name };
allow engsetmacaddr system_data_file:file { create execute_no_trans write open setattr};

allow engsetmacaddr system_file:file { execute_no_trans};

以上赋予的权限全部是根据avc denied的log缺什么一步一步补什么来的。


本部分来自 韩半仙 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/hanmengaidudu/article/details/56671679?utm_source=copy

更多相关文章

  1. (转载)不需要任何权限获得Android设备的唯一ID
  2. android 主流浏览器对 scheme 打开本地 APP 功能的兼容性
  3. android之AndroidManifest.xml简述
  4. android studio导入eclipse项目方式及相关问题解决办法
  5. 百度网盘邀请码:还剩三个哦
  6. Android资源文件命名规则
  7. React Native 项目运行在安卓模拟器Http请求报错
  8. Android(安卓)MediaPlayer 分析 - service端文件结构
  9. Android(安卓)Vendor Test Suite (VTS) 的概念、作用及测试方法

随机推荐

  1. 升级Android内置apk版本
  2. Android(安卓)7.0 FileProvider简单使用
  3. 错误ava.lang.RuntimeException: Unable
  4. Android中网络框架简单封装的实例方法
  5. 批量反编译Android XML文件Python脚本
  6. 深入理解Android WebView
  7. android activity开发文档翻译 - 1 - 基
  8. Android中SparseArray性能优化的使用方法
  9. android学习笔记-1
  10. 自定义程序实现Android(安卓)EditText只