Android系统SELinux详解

前言

SELinux是一种加强文件安全的一种策略,可以更好地保护我们的Android系统, 比如限制系统服务的访问权限、控制应用对数据和系统日志的访问等措施,这样就降低了恶意软件的影响,并且可以防止因代码存在的缺陷而产生的对系统安全的影响。

从系统安全方面考虑,SELinux是保护神,但是从软件开发方面,SELinux就是一道牵绊,这是一把双刃剑。SELinux默认开启,即使获得了该系统的root权限,也只能向相关策略中指定的设备写入数据,从而更好地保护和限制系统服务,保障系统和数据的安全。

环境

硬件平台:Google Pixel2

操作系统:Android10.0

selinux有两种工作模式

名称 作用
permissive 所有操作都被允许(即没有MAC),但是如果有违反权限的话,会记录日志
enforcing 所有操作都会进行权限检查

标签、规则和域

SELinux 依靠标签来匹配操作和策略。标签用于决定允许的事项。套接字、文件和进程在 SELinux 中都有标签。SELinux 在做决定时需参照两点:一是为这些对象分配的标签,二是定义这些对象如何交互的策略。

在 SELinux 中,标签采用以下形式:user:role:type:mls_level,其中 type 是访问决定的主要组成部分,可通过构成标签的其他组成部分进行修改。对象会映射到类,对每个类的不同访问类型由权限表示。

策略规则采用以下形式:allow domains types:classes permissions;,其中:

名称 作用
domain 一个进程或一组进程的标签。也称为域类型,因为它只是指进程的类型。
type 一个对象(例如,文件、套接字)或一组对象的标签。
class 要访问的对象(例如,文件、套接字)的类型。Permission - 要执行的操作(例如,读取、写入)。

策略配置源文件

  1. external/sepolicy
    这是独立于设备的配置,一般不能针对设备进行修改
  2. device///sepolicy
    这是特定于设备的配置,基于 BOARD_SEPOLICY_* 变量来选择对应平台的策略配置。

Type Enforcement (TE) 配置文件

.te 文件中保存了对应对象的域和类型定义、规则。通常每个域一个 .te 文件,例如installd.te。在 device.te、file.te 中声明了设备和文件类型。在某些文件(例如domain.te、app.te)中则存储着共享规则。

标签配置文件

  1. file_contexts:文件安全上下文
  2. property_contexts:属性安全上下文

SEAndroid app分类

SELinux(或SEAndroid)将app划分为主要三种类型(根据user不同,也有其他的domain类型):

名称 作用
untrusted_app 第三方app,没有Android平台签名,没有system权限
platform_app 有android平台签名,没有system权限
system_app 有android平台签名和system权限

从上面划分,权限等级,理论上:untrusted_app < platform_app < system_app

user

user可以理解为UID。android的UID和linux的UID根本是两回事,Linux的UID是用于针对多用户操作系统中用于区分用户的,而Android中的UID是用于系统进行权限管理的。参考链接中的文章对于uid的产生讲的很清楚。

seinfo

不同签名会创建对应的selinux上下文。

Android.mk
LOCAL_CERTIFICATE := platform

有platform签名,所以seinfo是platform。

自定义安全策略

以上面两个运行的app来说,我们为这两个APP添加额外的权限,对应的TE配置文件分别就是system_app.te、untrusted_app.te,对应路径为:

java 复制代码
$aosp/system/sepolicy/public/system_app.te
$aosp/system/sepolicy/public/untrusted_app.te

以longzhiye.example.app为例,我们为其添加can设备的执行权限:

java 复制代码
longzhiye@longzhiye-laptop:~/mount/project/androidq$ vi system/sepolicy/public/system_app.te
java 复制代码
......
allow system_app vendor_shell_exec:file { getattr open read execute execute_no_trans };
allow system_app shell_exec:file { getattr open read execute execute_no_trans };
allow system_app shell:file { getattr open read execute execute_no_trans };
......

以策略规则配置形式(allow domains types:classes permissions)

分析:

策略规则 示例
domains system_app
types vendor_shell_exec
classes file
permissions getattr open read execute execute_no_trans

neverallow failures

有时我们增加的权限,系统默认的配置是不允许的,比如我们上面给forlinx.example.app增加的执行脚本的权限,报错如下:

java 复制代码
libsepol.report_failure: neverallow on line 9 of system/sepolicy/private/system_app.te

(or line 41463 of policy.conf) violated by allow system_app shell:file { read open };

libsepol.report_failure: neverallow on line 22 of system/sepolicy/private/shell.te

(or line 40025 of policy.conf) violated by allow system_app shell:file { read open };

libsepol.check_assertions: 2 neverallow failures occurred

系统默认的安全策略的路径为system/sepolicy/,根据报错的提示,我们可以修改默认的配置,修改system/sepolicy/private/system_app.te和system/sepolicy/private/shell.te,从而完成权限的赋予。

安卓中快速编译sepolicy并验证(需要本地代码整编过一次,已经生成out目录)

java 复制代码
$ mmm system/sepolicy/
$ adb push out/target/product/xxx/system/etc/selinux /system/etc/selinux
$ adb push out/target/product/xxx/vendor/etc/selinux /vendor/etc/selinux

也可单编systemimage,并刷机

java 复制代码
$ make systemimage
$ adb reboot bootloader
$ fastboot flash system ./system.img
$ fastboot reboot

如何应对neverallow? 绕过CTS认证

在system/sepolicy/private/logpersist.te与system/sepolicy/prebuilts/api/29.0/private/logpersist.te中配置以下allow语句并编译,

会报neverallow的错。如下声明allow:

allow logpersist system_data_file:dir write;

这表示谷歌不允许我们使用allow语句,解除限制的最暴力方法就是将报错处的neverallow语句删掉,这样确实可行,但是会过不了cts。

由于我们要访问的目录path为/data/syslog,将该目录定义成自己的Type,可以自定义Type,如下:

在file.te中自定义一个type为file_type,data_file_type,core_data_file_type:

  1. type log_data_file, file_type, data_file_type, core_data_file_type;
    在file_contexts中定义安全上下文:
  2. /data/syslog(/.*)? u:object_r:log_data_file:s0
    在logpersist.te将allow语句改为:
  3. allow logpersist log_data_file write;
    然后在logpersist.te中单独将自定义的log_data_file减去即可。(这里最好的是自定义一个service代替logpersist,那就要新建一个te文件了,比较麻烦)
java 复制代码
neverallow logpersist {
  file_type
  userdebug_or_eng(`-misc_logd_file -coredump_file')
  with_native_coverage(`-method_trace_data_file')
  -log_data_file
}:file { create write append };

如何新增domian域?(一般在平台相关目录下添加)

例子如下

在device/平台名/system/private/file_contexts 文件添加

java 复制代码
# tcontext=u:object_r:sysfs:s0

/sys/kernel/display/abcd u:object_r:wxl_abcd:s0 #wxl_abcd替换sysfs,wxl_abcd随便取

在device/平台名/system/public/file.te 中添加

java 复制代码
type wxl_cabc, fs_type,sysfs_type;

在 device/平台名/system/private/system_server.te 文件中添加

java 复制代码
allow system_server wxl_abcd:file { r_file_perms w_file_perms rw_file_perms };

添加 write 或者 read 的权限要注意 open 的权限,最后使用 r_file_perms、w_file_perms、rw_file_perms。

添加设备文件节点权限(sysfs gpio管脚节点权限)?

/sys/class/leds/green/brightness //快捷方式
/sys/devices/soc.0/gpio-leds.66/leds/green/brightness //实际节点

操作LED灯的设备文件节点为APP层system app进程开放该节点访问权限(读或写),权限配置主要修改(一般在/device/平台/sepolicy/common)目录下的file.te、file_contexts和system_app.te三个文件

(1)file.te修改如下:

GPIO accessed by system app

java 复制代码
    type sysfs_gpio, fs_type, sysfs_type;

(2)file_contexts修改如下:

java 复制代码
    /sys/devices/soc/1010000.pinctrl/gpio/gpio62/value           u:object_r:sysfs_gpio:s0
    /sys/devices/soc/1010000.pinctrl/gpio/gpio63/value           u:object_r:sysfs_gpio:s0

(3)system_app.te修改如下:

java 复制代码
    allow system_app sysfs_gpio:file rw_file_perms;

如果通过以上添加SELinux之后,仍没有权限读写sys或proc节点,需要到/system/core/rootdir/init.rc里面配置如下:

(1)修改设备节点用户所有者和所属用户组,以及它们所对应的权限

chown system system 设备文件结点

chmod 777 设备文件结点

修改selinux没有生效???

将SELinux Policy 文件存放在下面目录

(1) Google 原生目录 /system/sepolicy

(2) 厂商配置目录 /device/厂商平台/sepolicy/

android将SELinux Policy 文件存放的te一般都是在device/平台/sepolicy 和 /system/sepolicy两个目录下

👀关注公众号:Android老皮!!!欢迎大家来找我探讨交流👀

相关推荐
踢球的打工仔4 小时前
PHP面向对象(7)
android·开发语言·php
安卓理事人4 小时前
安卓socket
android
安卓理事人10 小时前
安卓LinkedBlockingQueue消息队列
android
万能的小裴同学11 小时前
Android M3U8视频播放器
android·音视频
q***577412 小时前
MySql的慢查询(慢日志)
android·mysql·adb
JavaNoober12 小时前
Android 前台服务 "Bad Notification" 崩溃机制分析文档
android
城东米粉儿13 小时前
关于ObjectAnimator
android
zhangphil14 小时前
Android渲染线程Render Thread的RenderNode与DisplayList,引用Bitmap及Open GL纹理上传GPU
android
火柴就是我15 小时前
从头写一个自己的app
android·前端·flutter
lichong95116 小时前
XLog debug 开启打印日志,release 关闭打印日志
android·java·前端