【Android】SElinux(Security-Enhanced Linux)
作为安卓安全模型的一部分,安卓使用安全增强型Linux(SELinux)对所有进程实施强制性访问控制(MAC),甚至是以root/超级用户权限(Linux能力)运行的进程。许多公司和组织都为安卓的SELinux实现做出了贡献。有了SELinux,安卓可以更好地保护和限制系统服务,控制对应用程序数据和系统日志的访问,减少恶意软件的影响,并保护用户免受移动设备上代码的潜在缺陷。SELinux根据默认拒
作为安卓安全模型的一部分,安卓使用安全增强型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
- 首先搜索
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
- 所以sys/kernel/sched_util_clamp_min_rt_default 的type 为proc_sched。
- 然后确定你要加入的.rc是放到systerm还是vendor
device$ grep "***.rc" ./ -nr
./:535: $(DEVICE_PATH)/"***.rc":$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/"**".rc \
Binary file ./.git/index matches
- 因为放在VENDOR 下面,所以在
sepolicy/vendor_init.te中进行
allow vendor_init proc_sched:file w_file_perms
- 如果上面搜的是在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基础学习 |
更多推荐
所有评论(0)