Android Selinux 问题处理笔记
时间:2023年05月04日:整理案例一
篇头
对于Selinux,如果只是解决权限问题,不需要去理解那么多理论,按下面模板处理即可。但请注意,在enforce模式下,报错是不会有打印产生的,所以先要将selinux设置为Permissive才行。
一、标签模板
1.1 报错模板
avc: denied { read write getattr } for pid=3944 comm="handsetpowerlib" name="xxxx" dev="tmpfs" ino=5545 scontext=u:r:AAA:s0:c512,c768 tcontext=u:object_r:BBB:s0 tclass=CCC permissive=1
---
1.2 信息提取
主体:AAA
客体:BBB
客体类别:CCC
需要allow的权限:read write getattr
1.3 修改策略
1.3.1 增加主体新类型te文件(如果不存在)
devices/vendorxxx/sepolicy/common/下新增AAA.te:
type AAA, domain,mlstrustedsubject; #mlstrustedsubject看情况决定是否添加
type AAA_exec, exec_type,file_type;
init_daemon_domain(AAA)
allow AAA BBB:CCC { read write getattr };
allow …; #添加其他avc:denied
1.3.2 修改file_contexts
devices/vendorxxx/sepolicy/common/file_contexts新增:
/…/AAA u:object_r:AAA_exec:s0 #/…/AAA为AAA的绝对路径
二、官文扫盲
源自谷歌文档
1.1 政策文件
以 *.te 结尾的文件是 SELinux 政策源代码文件,用于定义域及其标签。您可能需要在 /device/manufacturer/device-name/sepolicy 中创建新的政策文件,但您应尽可能尝试更新现有文件。
1.2 上下文的描述文件
您可以在上下文的描述文件中为您的对象指定标签。
- file_contexts 用于为文件分配标签,并且可供多种用户空间组件使用。在创建新政策时,请创建或更新该文件,以便为文件分配新标签。如需应用新的 file_contexts,请重新构建文件系统映像,或对要重新添加标签的文件运行 restorecon。在升级时,对 file_contexts 所做的更改会在升级过程中自动应用于系统和用户数据分区。此外,您还可以通过以下方式使这些更改在升级过程中自动应用于其他分区:在以允许读写的方式装载相应分区后,将 restorecon_recursive 调用添加到 init.board.rc 文件中。
- genfs_contexts 用于为不支持扩展属性的文件系统(例如,proc 或 vfat)分配标签。此配置会作为内核政策的一部分进行加载,但更改可能对内核 inode 无效。要全面应用更改,您需要重新启动设备,或卸载并重新装载文件系统。 此外,通过使用 context=mount 选项,您还可以为装载的特定系统文件(例如 vfat)分配特定标签。
- property_contexts 用于为 Android 系统属性分配标签,以便控制哪些进程可以设置这些属性。在启动期间,init 进程会读取此配置。
- service_contexts 用于为 Android binder 服务分配标签,以便控制哪些进程可以为相应服务添加(注册)和查找(查询)binder 引用。在启动期间,servicemanager 进程会读取此配置。
- seapp_contexts 用于为应用进程和 /data/data 目录分配标签。在每次应用启动时,zygote 进程都会读取此配置;在启动期间,installd 会读取此配置。
- mac_permissions.xml 用于根据应用签名和应用软件包名称(后者可选)为应用分配 seinfo 标记。随后,分配的 seinfo 标记可在 seapp_contexts 文件中用作密钥,以便为带有该 seinfo 标记的所有应用分配特定标签。在启动期间,system_server 会读取此配置。
- keystore2_key_contexts 用于为密钥库 2.0 命名空间分配标签。 这些命名空间由 keystore2 守护程序强制执行。密钥库始终都提供基于 UID/AID 的命名空间。密钥库 2.0 还会强制执行 sepolicy 定义的命名空间。如需详细了解此文件的格式和规范,请点击此处。
三、案例(1):Hal 无法获取服务
3.1 问题现象
- 系统AC开机后跑到楼下代码处,但最终会失败
- 如下图所示,尝试20次后,直接失败退出,service对象为null
3.2 实现代码
#ifdef VEIHAL_CONFIG
using com::zs::vehicledevice::V1_0::IVehicleDevice;
sp<IVehicleDevice> mVehicleDevice = nullptr;
int retry = 0;
do {
mVehicleDevice = IVehicleDevice::getService();
if (mVehicleDevice == nullptr) {
ALOGE("zs, !!!can't get VehicleDevice, try again!!!~~");
usleep(100 * 1000);
retry++;
if (retry > 20) {
ALOGE("zs, !!! FATAL ERROR, can't connect to VehicleDevice service!!!");
break;
}
} else {
ALOGE("zs, init DspVehicleDevice: connect to VehicleDevice service successful");
}
} while (mVehicleDevice == nullptr);
if (mVehicleDevice != nullptr)
{
mVehicleDevice->getProjectConfigs([&](const auto &configs){
projectConfigs = configs;
});
ALOGE("zs, RadioVehicleDevice projectConfigs:%s", projectConfigs.c_str());
}
else
{
ALOGE("zs, RadioVehicleDevice mVehicleDevice is fainl");
}
#endif
3.3 问题分析
1. 同样的代码在其他进程中有案例,是OK的
2. 所以,可能是Selinux权限问题
3.4 实验:暂停Selinux ,重启进程看是否OK
- 对于selinux权限的怀疑,可以先暂停做下验证,如果暂停后验证OK,则查找缺失的权限,最后补充其标签文件即可。
3.4.1 暂停Selinux
(1)查看Selinux运行状态,得知功能生效中
130|SA8155:/ # getenforce
Enforcing
SA8155:/ #
(2)暂停Selinux
130|SA8155:/ # setenforce 0
130|SA8155:/ # getenforce
Permissive
SA8155:/ #
3.4.2 杀zygote64,重启服务
- 顺带获取了 avc: denied打印
SA8155:/ # ps -A | grep zy
root 5599 1 13272888 133128 poll_schedule_timeout 0 S zygote64
root 5600 1 1234144 115292 poll_schedule_timeout 0 S zygote
webview_zygote 6265 5600 1169856 64072 poll_schedule_timeout 0 S webview_zygote
SA8155:/ # kill 5599
SA8155:/ #
SA8155:/ #
SA8155:/ #
SA8155:/ #
SA8155:/ # logcat | grep avc
04-13 09:38:56.411 5494 5494 I broadcastradio@: type=1400 audit(0.0:247): avc: denied { call } for scontext=u:r:hal_broadcastradio_default:s0 tcontext=u:r:hal_vehicledevice_default:s0 tclass=binder permissive=1
备注:下面这条是后面补的,在添加第1条的之前未发现
04-13 09:29:54.350 1648 1648 E SELinux : liblog:135-6-0-avc: denied { find } for interface=com.xxx.vehicledevice::IVehicleDevice sid=u:r:hal_broadcastradio_default:s0 pid=2125 scontext=u:r:hal_broadcastradio_default:s0 tcontext=u:object_r:hal_vehicledevice_hwservice:s0 tclass=hwservice_manager permissive=0
3.4.3 成功的打印
130|SA8155:/ # logcat | grep zs
04-13 09:29:17.260 5693 5825 D OverlayManager: targetPackage=PackageInfo{17bc289 android}, overlayPackage=PackageInfo{6f02db9 com.zscustomoverlay.zs11emcein.fwkresoverlay}
04-13 09:29:19.715 5693 5693 D OverlayManager: targetPackage=PackageInfo{17bc289 android}, overlayPackage=PackageInfo{6f02db9 com.zscustomoverlay.zs11emcein.fwkresoverlay}
04-13 09:29:21.496 5693 5693 V StorageManagerService: Package com.zscustomoverlay.zs11emcein.fwkresoverlay does not have legacy storage
04-13 09:29:25.521 5693 5736 I JobScheduler.Quota: Moving pkg <0>com.zscustomoverlay.zs11emcein.fwkresoverlay to bucketIndex 0
04-13 09:29:27.533 5494 6968 E default_broadcastradio_hal: liblog:53-18-0-zs, init DspVehicleDevice: connect to VehicleDevice service successful
04-13 09:29:27.739 5494 6968 E default_broadcastradio_hal: liblog:56-0-0-zs, RadioVehicleDevice projectConfigs:253.253.1.254.253.0.1.253.1.0.1.4.253.253.253.253.253.253.86.253.253.253.193.255.195.255.6.0.0.1.253.253.0.253.3.1.253.253.0.0
04-13 09:29:31.698 7379 7532 I AA-Config-ConfigUtils: jxUidlO0d082zsrw6bZsivPo5szW4zYHNpIddYx7/+jEhXnEGFVIdjnRtexzHQ4O
3.5 分析及修改标签
3.5.1 分析 avc: denied
(1)信息提取
04-13 09:38:56.411 5494 5494 I broadcastradio@: type=1400 audit(0.0:247): avc: denied { call } for scontext=u:r:hal_broadcastradio_default:s0 tcontext=u:r:hal_vehicledevice_default:s0 tclass=binder permissive=1
主体:hal_broadcastradio_default
客体:hal_vehicledevice_default
客体类别:binder
需要allow的权限:avc: denied { call }
04-13 09:29:54.350 1648 1648 E SELinux : liblog:135-6-0-avc: denied { find } for interface=com.zs.vehicledevice::IVehicleDevice sid=u:r:hal_broadcastradio_default:s0 pid=2125 scontext=u:r:hal_broadcastradio_default:s0 tcontext=u:object_r:hal_vehicledevice_hwservice:s0 tclass=hwservice_manager permissive=0
主体:hal_broadcastradio_default
客体:hal_vehicledevice_hwservice
客体类别:hwservice_manager
需要allow的权限:avc: denied { call }
(2)查找te文件
- 根据hal_broadcastradio_default,找到hal_broadcastradio_default.te文件,已存在,不需要再创建。
- 文件位置:develop\vendor\zs\SA8155\device\sepolicy\vendor\hal_broadcastradio_default.te
get_prop(hal_broadcastradio_default, persist_sys_tuner_region_type)
allow hal_broadcastradio_default audioin:binder { call transfer };
allow hal_broadcastradio_default hal_audioin_hwservice:hwservice_manager find;
allow hal_broadcastradio_default init:unix_stream_socket connectto;
allow hal_broadcastradio_default mfi_auth_device:chr_file { read write open ioctl };
allow hal_broadcastradio_default property_socket:sock_file write;
allow hal_broadcastradio_default persist_sys_tuner_region_type:property_service set;
allow hal_broadcastradio_default sys_tuner_ext_comm_created:property_service set;
allow hal_broadcastradio_default socket_device:dir { write add_name };
allow hal_broadcastradio_default socket_device:sock_file { create read write };
(3)修改te文件
- 根据步骤一分析的信息,添加下面这两行
allow hal_broadcastradio_default hal_vehicledevice_default:binder { call transfer };
allow hal_broadcastradio_default hal_vehicledevice_hwservice:hwservice_manager find;
3.5.2 编译及部署
(1)编译
略
(2)部署
- 先将编译生成的 develop\out\target\product\SA8155\vendor\etc\selinux目录复制到adb.exe同级目录下
- 使用下面命令覆盖板子上的selinux文件,复制完后确认操作正确后,重启系统即可验证
D:\tools\Android\Sdk\platform-tools>adb root
D:\tools\Android\Sdk\platform-tools>adb remount remount
D:\tools\Android\Sdk\platform-tools>adb push selinux /vendor/etc/
selinux\: 15 files pushed, 0 skipped. 24.9 MB/s (2091204 bytes in 0.080s)
3.5.3 验证
- 因修改te后变动文件较多,若出现替换有问题,可尝试全编译,之后烧录
四、附录
4.1 库替换方法
- 替换板子上lib64下同名文件即可
develop\out\target\product\SA8155\vendor\lib64\hw\broadcastradio.default.so
4.2 分区挂载方法
- 需执行以下remount命令
- 对于在adb shell之后执行的mount -o remount,rw /vendor命令,替换表面上成功了,但实际文件无法复制过去,重启后就丢失了
D:\tools\Android\Sdk\platform-tools>adb usb
D:\tools\Android\Sdk\platform-tools>adb remount remount
sophia fs_mgr_remount read success
remount succeeded 0
D:\tools\Android\Sdk\platform-tools>
4.3 Userdebug 与 User 的区别
- 如下图所示,AOSP默认情况下,只有选择user版本,才会开启 SELINUX 功能
- 文件路径:system\core\init\Android.mk
4.4 快捷方式 audit2allow
- 提取所有的avc LOG. 如 adb shell “cat /proc/kmsg | grep avc” > avc_log.txt
- 使用 audit2allow tool 直接生成policy: audit2allow -i avc_log.txt
- Ubuntu 14.04:adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
4.5 参考资料
[1] 《实现 SELinux》, https://source.android.com/security/selinux/implement
[2] 《政策兼容性》, https://source.android.com/security/selinux/compatibility