Android Selinux 问题处理笔记

简介: 这篇文章是关于处理Android系统中SELinux权限问题的笔记,介绍了如何通过分析SELinux拒绝的日志、修改SELinux策略文件,并重新编译部署来解决权限问题,同时提供了一些SELinux的背景知识和实用工具。

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

相关文章
|
6月前
|
Linux 编译器 Android开发
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
在Linux环境下,本文指导如何交叉编译x265的so库以适应Android。首先,需安装cmake和下载android-ndk-r21e。接着,下载x265源码,修改crosscompile.cmake的编译器设置。配置x265源码,使用指定的NDK路径,并在配置界面修改相关选项。随后,修改编译规则,编译并安装x265,调整pc描述文件并更新PKG_CONFIG_PATH。最后,修改FFmpeg配置脚本启用x265支持,编译安装FFmpeg,将生成的so文件导入Android工程,调整gradle配置以确保顺利运行。
228 1
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
|
6月前
|
Android开发
Android 11 添加Service服务SELinux问题
Android 11 添加Service服务SELinux问题
330 1
|
6月前
|
Unix Linux Shell
FFmpeg开发笔记(八)Linux交叉编译Android的FFmpeg库
在Linux环境下交叉编译Android所需的FFmpeg so库,首先下载`android-ndk-r21e`,然后解压。接着,上传FFmpeg及相关库(如x264、freetype、lame)源码,修改相关sh文件,将`SYSTEM=windows-x86_64`改为`SYSTEM=linux-x86_64`并删除回车符。对x264的configure文件进行修改,然后编译x264。同样编译其他第三方库。设置环境变量`PKG_CONFIG_PATH`,最后在FFmpeg源码目录执行配置、编译和安装命令,生成的so文件复制到App工程指定目录。
336 9
FFmpeg开发笔记(八)Linux交叉编译Android的FFmpeg库
|
1月前
|
Web App开发 安全 程序员
FFmpeg开发笔记(五十五)寒冬里的安卓程序员可进阶修炼的几种姿势
多年的互联网寒冬在今年尤为凛冽,坚守安卓开发愈发不易。面对是否转行或学习新技术的迷茫,安卓程序员可从三个方向进阶:1)钻研谷歌新技术,如Kotlin、Flutter、Jetpack等;2)拓展新功能应用,掌握Socket、OpenGL、WebRTC等专业领域技能;3)结合其他行业,如汽车、游戏、安全等,拓宽职业道路。这三个方向各有学习难度和保饭碗指数,助你在安卓开发领域持续成长。
69 1
FFmpeg开发笔记(五十五)寒冬里的安卓程序员可进阶修炼的几种姿势
|
27天前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
75 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
6月前
|
Android开发
Android Service Call /dev/xxx SELinux
Android Service Call /dev/xxx SELinux
106 1
|
3月前
|
JavaScript 前端开发 Java
FFmpeg开发笔记(四十七)寒冬下安卓程序员的几个技术转型发展方向
IT寒冬使APP开发门槛提升,安卓程序员需转型。选项包括:深化Android开发,跟进Google新技术如Kotlin、Jetpack、Flutter及Compose;研究Android底层框架,掌握AOSP;转型Java后端开发,学习Spring Boot等框架;拓展大前端技能,掌握JavaScript、Node.js、Vue.js及特定框架如微信小程序、HarmonyOS;或转向C/C++底层开发,通过音视频项目如FFmpeg积累经验。每条路径都有相应的书籍和技术栈推荐,助你顺利过渡。
62 3
FFmpeg开发笔记(四十七)寒冬下安卓程序员的几个技术转型发展方向
|
6月前
|
安全 Linux Android开发
FFmpeg开发笔记(十六)Linux交叉编译Android的OpenSSL库
该文介绍了如何在Linux服务器上交叉编译Android的FFmpeg库以支持HTTPS视频播放。首先,从GitHub下载openssl源码,解压后通过编译脚本`build_openssl.sh`生成64位静态库。接着,更新环境变量加载openssl,并编辑FFmpeg配置脚本`config_ffmpeg_openssl.sh`启用openssl支持。然后,编译安装FFmpeg。最后,将编译好的库文件导入App工程的相应目录,修改视频链接为HTTPS,App即可播放HTTPS在线视频。
109 3
FFmpeg开发笔记(十六)Linux交叉编译Android的OpenSSL库
|
5月前
|
Java API Android开发
技术经验分享:Android源码笔记——Camera系统架构
技术经验分享:Android源码笔记——Camera系统架构
55 0
|
6月前
|
Java 测试技术 开发工具
Android 笔记:AndroidTrain , Lint , build(1),只需一篇文章吃透Android多线程技术
Android 笔记:AndroidTrain , Lint , build(1),只需一篇文章吃透Android多线程技术