SEAndroid是在Android 4.3版本中开始引入的基于SELinux的系统安全机制。
关于SELinux的一些基础已经在SELinux基础中总结了。
在平时工作中,遇到SEAndroid最多的,就是一些权限问题,因此,本文的主要目标,是如何查看SELinux权限拒绝信息、如何修改添加权限。
该目录是SEAndroid的核心,该目录中的文件在编译后会包含 SELinux 内核安全政策,并涵盖上游 Android 操作系统。
一般来说,不能直接修改system/sepolicy
文件,而是添加或修改自己的设备专用政策文件,即在/device/xxx/xxx/sepolicy文件。
以.te结尾的文件是SEAndroid的政策文件,在文件位于/system/sepolicy中,用来定义域(domain)和标签.如在/system/sepolicy/public/init.te中:
# Create and mount on directories in /.
allow init rootfs:dir create_dir_perms;
allow init { rootfs cache_file cgroup storage_file system_data_file system_file vendor_file postinstall_mnt_dir }:dir mounton;
allow init cgroup_bpf:dir { create mounton };
...
# Init should not access sysfs node that are not explicitly labeled.
neverallow init sysfs:file { open read write };
allow语句和neverallow语句用来定义规则,具体含义参见在SELinux中的说明.
1.一般情况下,不能修改/system/sepolicy下的.te文件,而是在/device/xxx/xxx/sepolicy下进行修改或添加。
2.定义权限时,遵循最小权限原则,即缺什么权限,就添加什么权限。
该文件也位于/system/sepolicy中,上下文描述文件中可以给客体目标指定一个标签。上下文描述文件共有五个,其中使用最多的为file_contexts。如:
/(vendor|system/vendor)/bin/hw/android\.hardware\.ir@1\.0-service u:object_r:hal_ir_default_exec:s0
一般情况下,不能修改/system/sepolicy下的file_contexts文件,而是在/device/xxx/xxx/sepolicy下进行修改或添加。
修改或添加政策文件和上下文的描述文件后,需要更新 /device/manufacturer/device-name/BoardConfig.mk文件,设置BOARD_SEPOLICY_DIRS
,以引用sepolicy子目录和每个新的政策文件。
如:
在/android9.0/device/xxx/xxx/xxx/BoardConfig.mk
中:
BOARD_SEPOLICY_DIRS += device/xxx/xxx/common/sepolicy \
build/target/board/generic/sepolicy
SELinux中,查看权限拒绝信息,就需要查看log中的avc信息,在SEAndroid也是如此。一般来说,SEAndorid中如果存在权限拒绝,那么在kernel.log中搜索avc关键字,会有如下格式信息:
[118.812005] c3 type=1400 audit(1325540997.019:195): avc: denied { setattr } for pid=1 comm="init" name="brightness" dev="sysfs" ino=24526 scontext=u:r:init:s0 tcontext=u:object_r:sysfs:s0 tclass=file permissive=0
以上avc信息中各个关键字含义如下:
因此,从avc log中看出,主体类型为init对客体类型为sysfs
的file
类型文件没有setattr
权限。
还有一种方式就是进入adb shell直接查看kernal 中的avc log:
adb root
adb remount
adb shell
cat /proc/kmsg
<11>[ 3370.846310] c1 1 selinux: avc: denied { set } for property=persist.vendor.power.debug_d pid=14256 uid=1000 gid=1000 scontext=u:r:sprd_engineermode_app:s0:c512,c768 tcontext=u:object_r:vendor_power_prop:s0 tclass=property_service permissive=0
<11>[ 3370.846310] c1 1
<11>[ 3370.846405] c1 1 init: Unable to set property 'persist.vendor.power.debug_d' to '1' from uid:1000 gid:1000 pid:14256: SELinux permission check failed
对于SELinux权限拒绝问题,可以有两种方式对其进行修改,第一种方式是配置相关权限,这也是优先选择的方式,于是我们可以在/device/xxx/…/sepolicy/init.te中配置权限:
allow init sysfs:file setattr;
这种方式如果编译不过,说明违反了Google原生的策略。
针对于该问题,一般采用第二种方式:修改安全上下文。
首先,通过ls -lZ
查看对应节点的安全上下文:
图中第5列是安全上下文信息,由四部分组成,分别表示SELinux用户、SELinux角色、类型、安全级别,我们只关注类型,这里类型为sysfs
.
从查看结果看,/sys/class/leds/下的文件其实是/sys/device/…/的连接文件,所以使用同样的方式再查看实际文件的安全上下文信息,并且修改时也需要修改原文件安全上下文。
然后,开始修改安全上下文,可以将sysfs
修改为sysfs_leds
,在/device/BOARD/common/sepolicy/file_context
中,自定义安全上下文信息:
修改之后,编译烧录,我们直接查看对应节点连接的原文件:
说明修改生效了。
这里为何要将安全上下文类型由sysfs
修改为sysfs_leds
呢?
因为在Google原生init.te中,有如下定义:
332# init chmod/chown access to /sys files.
333allow init {
334 sysfs_android_usb
335 sysfs_devices_system_cpu
336 sysfs_ipv4
337 sysfs_leds
338 sysfs_lowmemorykiller
339 sysfs_power
340 sysfs_vibrator
341 sysfs_wake_lock
342}:file setattr;
搜索avc log信息:
E SELinux : avc: denied { find } for interface=android.hardware.health::IHealth pid=367 scontext=u:r:hal_power_default:s0 tcontext=u:object_r:hal_health_hwservice:s0 tclass=hwservice_manager permissive=0
在以上avc denied信息中,主体安全上下文类型为hal_power_default
,客体安全上下文类型为hal_health_hwservice
,客体文件类型为hwservice_manager
,拒绝原因是hal_power_default
对hal_health_hwservice
缺少find
权限。
于是在/device/…/sepolicy/hal_power_default.te中:
allow hal_power_default hal_health_hwservice:hwservice_manager find;
如果不存在/device/…/sepolicy/hal_power_default.te文件,则新建该文件,并配置BoardConfig.mk的BOARD_SEPOLICY_DIRS变量中即可。
优先配置权限,如果配置权限违反Google原生策略,则只能修改安全上下文。是否违反Google原生策略,根据修改后是否编译失败来判定。如果编译成功,则说明没有违反,反之。
Android Open Source Project