【Android】SElinux(Security-Enhanced Linux)

作为安卓安全模型的一部分,安卓使用安全增强型Linux(SELinux)对所有进程实施强制性访问控制(MAC),甚至是以root/超级用户权限(Linux能力)运行的进程。许多公司和组织都为安卓的SELinux实现做出了贡献。有了SELinux,安卓可以更好地保护和限制系统服务,控制对应用程序数据和系统日志的访问,减少恶意软件的影响,并保护用户免受移动设备上代码的潜在缺陷。
SELinux根据默认拒绝的原则运作。任何没有明确允许的东西都会被拒绝。SELinux可以在两种全局模式下运行。

  • Permissive mode: 其中权限拒绝被记录下来,但不强制执行。
  • Enforcing mode: 其中权限拒绝被记录和强制执行。
  • Disabled:表示SELinux没有实际运行。
setenv append_bootargs androidboot.selinux=permissive
saveenv

getenforce、setenforce命令
可以通过getenforce和setenforce命令来查看和切换当前的模式,如:

# 查看当前系统SELinux模式
jyq@ubuntu:~$ getenforce
Permissive
# 将SELinux模式设置为Enforcing模式,1表示Enforing模式,0表示Permissive模式
jyq@ubuntu:~$ sudo setenforce 1
jyq@ubuntu:~$ getenforce
Enforcing

但是需要注意的是,setenforce命令无法在Disabled的模式下进行模式的切换,如果要切换Diabled模式,则通过上面的bootargs来实现。

SELinux概念

一个政策规则的形式是:

allow source target:class permissions;
  • Source - 规则主体的类型(或属性)。谁在请求访问?
  • Target - 对象的类型(或属性)。要求访问的是什么?
  • Class - 被访问对象的种类(如文件、套接字)。
  • Permissions - 正在进行的操作(或一组操作)(例如,读、写)。

一个规则的例子是:

allow untrusted_app app_data_file:file { read write };

这说明应用程序被允许读写标有app_data_file的文件。还存在其他类型的应用程序。例如,isolated_app用于其清单中带有isolatedProcess=true的应用服务。Android没有对这两种类型重复规则,而是对涵盖应用程序的所有类型使用一个名为appdomain的属性:

# 将属性appdomain与类型untrusted_app相关联。
typeattribute untrusted_app, appdomain;

# 将属性appdomain与类型isolated_app相关联。
typeattribute isolated_app, appdomain;

allow appdomain app_data_file:file { read write };
allow appdomain app_data_file:file { read write };
与
allow appdomain app_data_file:file rw_file_perms;
相等

当写下一条指定属性名称的规则时,该名称会自动扩展到与该属性相关的域或类型列表。一些值得注意的属性是。

  • domain - 与所有进程类型相关的属性。
  • file_type - 与所有文件类型关联的属性。

在调试SELinux策略或标记文件时(通过file_contexts或运行ls -Z时),你可能会遇到一个安全上下文(也称为标签)。

# ls -Z /sys/devices/platform/sc-powerkey/wakeup
u:object_r:sysfs:s0 wakeup0

安全上下文具有这种格式:

user:role:type:sensitivity[:categories]

你通常可以忽略一个上下文的user:role:sensitivity。type也就是前面说的file_type。categories是SELinux中多级安全(MLS)支持的一部分。从android S开始,类别被用来:

  • 隔离应用程序的数据,使其不被其他应用程序访问。
  • 将应用程序数据从一个物理用户隔离到另一个。

实施SELinux

关键文件

要启用SELinux,请整合最新的安卓内核,然后纳入在system/sepolicy目录中发现的文件。编译后,这些文件构成了SELinux内核的安全策略,并覆盖了上游的安卓操作系统。

一般来说,你不应该直接修改 system/sepolicy 文件。相反,在/device/manufacturer/device-name/sepolicy目录下添加或编辑你自己的设备特定策略文件。

Policy 文件

以*.te结尾的文件是SELinux策略源文件,它定义域和它们的标签。你可能需要在/device/manufacturer/device-name/sepolicy中创建新的策略文件,但你应该尽可能地更新现有文件。

Context 文件

Context文件是你为你的对象指定标签的地方。

  • file_contexts: file_contex为文件分配标签,被各种用户空间组件使用。当你创建新的策略时,创建或更新这个文件来给文件分配新的标签。要应用新的file_contexts,需要重建文件系统镜像或对要重新标记的文件运行restorecon。在升级时,对file_contexts的改变会作为升级的一部分自动应用到系统和用户数据分区上。通过在分区被读写挂载后,在 init.board.rc 文件中添加 restorecon_recursive 调用,也可以在升级时自动应用到其他分区。
  • genfs_contexts: genfs_contexts给文件系统分配标签,比如不支持扩展属性的proc或vfat。这个配置作为内核策略的一部分被加载,但是变化可能不会对核心节点生效,需要重启或者卸载并重新挂载文件系统来完全应用这个变化。特定的标签也可以被分配给特定的挂载,比如使用context=mount选项的vfat。
  • property_contexts: 为Android系统属性分配标签,以控制哪些进程可以设置它们。这个配置在启动时由init进程读取。
  • service_contexts: 为Android绑定服务分配标签,以控制哪些进程可以为该服务添加(注册)和查找(查询)绑定参考。这个配置在启动时由servicemanager进程读取。
  • seapp_contexts: seapp_contex为应用程序进程和/data/data目录分配标签。这个配置在每个应用启动时由zygote进程读取,在启动时由installd读取。
  • mac_permissions.xml: 根据应用程序的签名和可选的软件包名称,为其分配一个seinfo标签。然后,这个seinfo标签可以作为seapp_contexts文件中的一个键,为所有带有该seinfo标签的应用程序分配一个特定的标签。这个配置在启动时由system_server读取。
  • keystore2_key_contexts: 为Keystore 2.0命名空间分配标签。这些命名空间是由keystore2守护程序执行的。Keystore一直提供基于UID/AID的命名空间。Keystore 2.0另外还强制执行sepolicy定义的命名空间。关于这个文件的格式和惯例的详细描述可以在这里找到。

举例子

properties

selinux就是给每个Object(是通过进程访问的文件,套接字,管道或网络接口等资源。)打一个标签,例如:

ro.boot.wifivendor   u:object_r:vendor_default_prop:s0                   

然后让audioserver的进程可以访问以vendor_default_prop为标签的properties(ro.boot.wifivendor)

get_prop(audioserver, vendor_default_prop)

这个是对properties的selinux设置方式。

增加对一个节点的SELinux访问权限

第一种方法

设置如下参数:

setenv append_bootargs androidboot.selinux=permissive
saveenv

你可能会得到如下的log

 type=1400 audit(1669145756.868:93): avc: denied { search } for comm="usb@1.3-service" name="usb" dev="sysfs" ino=39035 scontext=u:r:hal_usb_impl:s0 tcontext=u:object_r:sysfs_batteryinfo:s0 tclass=dir permissive=0
allow hal_usb_impl sysfs_batteryinfo:dir {search};

允许主体 hal_usb_impl访问客体sysfs_batteryinfo,dir是客体的问题类型,search是允许主体对客体的动作。

然后写到 hal_usb_impl对应的文件sepolicy/hal_usb_impl.te中。

也就是如下的原理:

allow Rule | source_domain | target_type   : class    | permission
----------------------------------------------------------------
allow        unconfined_t    ext_gateway_t : process    transition;

allow:表示allow规则
source_domain:主体Type标识,即domain
target_type:目标Type标识,即type
class:目标类型
permission:授予主体对目标的权限

以上语句也称为TE语法,如:

allow user_t user_home_t:file { create read write unlink };

该语法含义为:允许具有user_t类型的进程(主体)对具有user_home_t类型的、目标类是file的目标有create read write unlink的权限,或者为:允许domain为user_t的进程(主体)对type为user_home_t的、目标类为file的目标有create read write unlink的权限。

第二种方法

增加一个***.rc需要访问的文件:

write /proc/sys/kernel/sched_util_clamp_min_rt_default 512
  1. 首先搜索
system/sepolicy$ grep "sched_util_clamp_min_rt_default" ./ -nr
./private/genfs_contexts:73:genfscon proc /sys/kernel/sched_util_clamp_min_rt_default u:object_r:proc_sched:s0
./prebuilts/api/31.0/private/genfs_contexts:73:genfscon proc /sys/kernel/sched_util_clamp_min_rt_default u:object_r:proc_sched:s0
  1. 所以sys/kernel/sched_util_clamp_min_rt_default 的type 为proc_sched。
  2. 然后确定你要加入的.rc是放到systerm还是vendor
device$ grep "***.rc" ./ -nr
./:535:    $(DEVICE_PATH)/"***.rc":$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/"**".rc \
Binary file ./.git/index matches
  1. 因为放在VENDOR 下面,所以在
    sepolicy/vendor_init.te中进行
allow vendor_init proc_sched:file w_file_perms
  1. 如果上面搜的是在systerm中而不是vendor中进行修改,应该在sepolicy/init.te进行:
allow init proc_sched:file w_file_perms;

第三种方法

dumpsys suspend_control_internal

时候遇到

avc: denied { read } for comm="binder:331_1" path="/sys/devices/platform/scu/scu:rtc/rtc/rtc0/alarmtimer.0.auto/wakeup/wakeup2/event_count" dev="sysfs" ino=38293 scontext=u:r:system_suspend:s0 tcontext=u:object_r:sysfs:s0 tclass=file permissive=1

因为tcontext=u:object_r:sysfs:s0,肯定不可能让system_suspend对所有sysfs都有某种selinux权限,因此可以看到system_suspend.te中已经有如下的code:

system/sepolicy/private/system_suspend.te
r_dir_file(system_suspend, sysfs_wakeup)

我们要做的就是在device/***/sepolicy/file_context(也可以在genfs_contexts 中加入genfscon **)中加入

/sys/devices/platform/scu/scu:rtc/rtc/rtc0/alarmtimer.0.auto/wakeup/wakeup2/event_count   u:object_r:sysfs_wakeup:s0

也就是给它打一个标签,然后r_dir_file(system_suspend, sysfs_wakeup)能够找到它。

参考链接
Security-Enhanced Linux in Android
SELinux基础学习
  • 6
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值