Android 系统SELinux

一、概念

作为 Android 安全模型的一部分,Android 使用安全增强型 Linux (SELinux) 对所有进程强制执行强制访问控制 (MAC),其中包括以 Root/超级用户权限运行的进程(Linux 功能)。很多公司和组织都为 Android 的 SELinux 实现做出了贡献。借助 SELinux,Android 可以更好地保护和限制系统服务、控制对应用数据和系统日志的访问、降低恶意软件的影响,并保护用户免遭移动设备上的代码可能存在的缺陷的影响。

SELinux 按照默认拒绝的原则运行:任何未经明确允许的行为都会被拒绝。SELinux 可按两种全局模式运行:

  • 宽容模式(permissive ):权限拒绝事件会被记录下来,但不会被强制执行。
  • 强制模式(Enforcing):权限拒绝事件会被记录下来并强制执行。

二、如何切换SELinux模式及问题确认

2.1 Selinux不同模式切换

android KK 4.4 版本后,Google 默认启用了SELinux即(Enforcing mode),SELinux 强制模式可以在 userdebug 或 eng build 中通过 ADB 停用。为此,请先运行 adb root 以将 ADB 切换为 root 权限。然后,如需停用 SELinux 强制模式,请运行以下命令

 adb root
 adb shell setenforce 0    //设置成permissive 模式
 adb shell setenforce 1    //设置成enforce 模式
 adb shell getenforce
 Permissive
 Enforcing

2.2 问题如何确认是Selinux 约束引起

userdebug或eng软件,通过adb命令(adb shell setenforce 0)临时关闭SElinux(使进入Permissive模式) 使请求都能被执行,重启失效。
如果问题消失,这样就能确认是SELinux 权限导致的问题。如果问题依然在,则是其他原因而非SELinux权限导致。

2.3 终端中查看安全上下文的方法

  • 查看文件上下文命令:adb shell ls -lZ
  • 查看属性安全上下文:adb shell getprop -Z
  • 查看进程安全上下文:adb shell ps -AZ

三、权限问题分析与修改

3.1 avc denied

adb logcat | grep “avc: denied” 过滤出报错log如下:

I auditd  : type=1400 audit(0.0:276): avc: denied { write } for comm="eeme.backscreen" name="tiny_lcd" dev="tmpfs" ino=12463 scontext=u:r:backscreen_app:s0:c512,c768 tcontext=u:object_r:device:s0 tclass=chr_file permissive=0

格式如下:avc: denied { 操作权限 } for comm=“进程名” scontext=u:r:源类型:s0 tcontext=u:r:目标类型:s0 tclass=访问类型 permissive=0

源类型:授予访问的类型,通常是进程的域类型
目标类型:客体的类型,它被授权可以访问的类型
访问类型
操作权限:表示主体对客体访问时允许的操作类型(也叫做访问向量)

3.2 分析过程如下:

问题点寻找点结果
缺什么权限denied{ write }
谁缺少权限scontext=u:r:backscreen_app
对哪个文件缺少权限tcontext=u:object_r:device
什么类型的文件tclass=chr_file

3.3 解决方法:

套用公式: allow
backscreen_app.te
allow scontext tcontext:tclass 操作权限
allow backscreen_app device:chr_file write ;
编译image,此时会出现如下报错:

neverallow check failed at out/soong/.intermediates/system/sepolicy/recovery_sepolicy.cil/android_common/recovery_sepolicy.cil:12400 from system/sepolicy/public/domain.te:471
  (neverallow domain device (chr_file (read write open)))
    <root>
    allow at out/soong/.intermediates/system/sepolicy/recovery_sepolicy.cil/android_common/recovery_sepolicy.cil:35615
      (allow backscreen_app device (chr_file (ioctl read write getattr lock append map open watch watch_reads)))

因为直接按照LOG 转换出SELinux Policy: allow backscreen_app device:chr_file write ; 就会放开backscreen_app 读写所有device 的权限. 而Google 为了防止这样的情况, 使用了neverallow 语句来约束, 这样你编译sepolicy 时就无法编译通过
对于neverallow错误的解决方法,可以去另外百度,有直接修改neverallow规则,或者去提示violate的策略文件中加上我们需要的例外服务,但这些方法都违反了Google定义的强制规则,并可能导致CTS报错,所以在这里我只分享一种比较安全但是稍显复杂的方法:
为了规避这种权限放大情况, 我们需要细化访问目标(Object) 的SELinux Label, 做到按需申请. 通常会由三步构成

  • 定义相关的SELinux type.
    比如上述案例, 在 device/mediatek/common/sepolicy/device.te 添加
    type oled_device, dev_type, mlstrustedobject;
  • 绑定文件与SELinux type.
    比如上述案例, 在 device/mediatek/common/sepolicy/file_contexts 添加
    /dev/tiny_lcd u:object_r:oled_device:s0

/dev/tiny_lcd是一个实际存在的节点

  • 添加对应process/domain 的访问权限.
    比如上述案例, 在 device/mediatek/common/sepolicy/backscreen_app.te 添加
    allow backscreen_app oled_device:chr_file rw_file_perms;
    完成后,编译刷机,此问题解决。

补充说明:

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

3.4 那么哪些访问对象通常会遇到此类呢?

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

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

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

  • Service 类型:
    – 类型定义: external/sepolicy/service.te;
    – 绑定类型:external/sepolicyservice_contexts;

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

通常我们强烈反对更新google default 的policy, 大家可以更新芯片厂商下面的相关的policy或者自己补充添加的policy

参考文档

android selinux 分析 selinux安卓是干什么的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值