Android13 添加init.rc自定义服务,编译的时候在Selinux检测阶段出现 neverallow 编译报错 ,已解决

文章讲述了作者在Android13环境下添加自启动服务时遇到的Selinux冲突问题,通过探索和实验,发现不能修改系统定义的neverallow规则,而是需要在自己的te文件中加入排除类型以通过编译。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景介绍

注:本文适合亲自添加过init.rc自定义服务的人阅读,没有搞过的话,可以先去看看如何添加,再结合本篇文章阅读,可以更好的理解意思。

我使用的Android版本:Android13
  最近在搞init.rc 新增自启动服务的功能,一般添加自启动服务的步骤如下:
1、将服务源代码通过mk / bp 添加编译到Android镜像。
2、init.rc添加自定义服务 定义。
/system/core/rootdir/init.rc
3、为服务制定Selinux规则。
修改目录:device/芯片商/common/sepolicy/vendor
file_contexts

#ftpd
/system/bin/ftpd 		u:object_r:ftpd_exec:s0
#ntpd
/system/bin/ntpd 		u:object_r:ntpd_exec:s0

ftpd.te

type ftpd, domain, coredomain;
type ftpd_exec, exec_type, file_type;
init_daemon_domain(ftpd)

allow ftpd ftpd:tcp_socket {create setopt bind};
allow ftpd ftpd:process {execmem};
allow ftpd ftpd:capability {net_raw};

ntpd.te

type ntpd, domain, coredomain;
type ntpd_exec, exec_type, file_type;
init_daemon_domain(ntpd)

allow ntpd node:udp_socket node_bind;
allow ntpd port:udp_socket name_bind;
allow ntpd self:capability net_bind_service;

走完上面这些过程,编译的时候 就直接报了这个错误:
在这里插入图片描述
关键的报错提取出来:

libsepol.report_failure: neverallow on line 948 of system/sepolicy/public/domain.te violated by allow ntpd ntpd_exec:file { entrypoint };
libsepol.report_failure: neverallow on line 948 of system/sepolicy/public/domain.te violated by allow ftpd ftpd_exec:file { entrypoint };
libsepol.check_assertions: 2 neverallow failures occurred
Error while expanding policy

上述就是整个问题的背景介绍。

解释一下,就是我定义的te文件allow部分的规则和谷歌定义的neverallow的规则发生了冲突,导致编译不过。这个问题我内网 墙网都搜了,根本找不到靠谱的答案,所以最后解决了我觉得非常有必要记录下来。
上面报错说和domain.te 948行冲突了,那么我们直接看看冲突部分:
在这里插入图片描述
红框 框出来的就是冲突部分,我第一眼看到,只想说,我靠这怎么解决,在搜索了无数低质量文章饱受摧残之后,我开始尝试各种解决方法:
注:这里我没有注释domain.te ftpd.te ntpd.te 中每一行的意思,读者可以自己先看看,把意思看懂,实在不会可以评论区问我。
第一种:直接排除相关的 file_type

full_treble_only(`
  # Do not allow coredomain to access entrypoint for files other
  # than system_file_type and postinstall_file
  neverallow coredomain {
    -file_type
    -system_file_type
    -postinstall_file
  }:file entrypoint;

结果失败,会报另外的错误,无法解决的错误。
第二种:将coredomain排除

full_treble_only(`
  # Do not allow coredomain to access entrypoint for files other
  # than system_file_type and postinstall_file
  neverallow { -coredomain } {
    file_type
    -system_file_type
    -postinstall_file
  }:file entrypoint;

结果失败,会报另外的错误,无法解决的错误。
第三种:看了不靠谱博主的博客,选择添加ftpd ntpd

full_treble_only(`
  # Do not allow coredomain to access entrypoint for files other
  # than system_file_type and postinstall_file
  neverallow coredomain {
    -ftpd
    -ntpd
    file_type
    -system_file_type
    -postinstall_file
  }:file entrypoint;

结果直接报unknown type ftpd ntpd ,根本不行,真的低质量博客。
第四种:代码中强行关闭Selinux

system/core/init/selinux.cpp
bool IsEnforcing() {
  if(1>0){
    return false;
   }

}

结果完全没用,会报新错误,解决不了哪种。
第五种:我考虑的是,既然domain.te里面有这么一条neverallow,那么把整个neverallow删除了不就行了?
结果也是会报一些奇奇怪怪的错误。
第六种:我选择将te文件的所属范围减小,删掉cordomain file_type 类型包含。

ftpd.te
type ftpd, domain;
type ftpd_exec, exec_type;
init_daemon_domain(ftpd)

allow ftpd ftpd:tcp_socket {create setopt bind};
allow ftpd ftpd:process {execmem};
allow ftpd ftpd:capability {net_raw};

ntpd.te
type ntpd, domain;
type ntpd_exec, exec_type;
init_daemon_domain(ntpd)

allow ntpd node:udp_socket node_bind;
allow ntpd port:udp_socket name_bind;
allow ntpd self:capability net_bind_service;

结果还是会报其它编译错误。

综上所述,我卡在这里好几天,感觉每一条路都被堵死了。
直到前不久我看到这篇博客:

https://blog.youkuaiyun.com/yxw0609131056/article/details/79784490

他的解决方法和我的不太一样,但是看了他的博客让我突然之间灵光一现,既然domain.te里面的规则是不能改也不能删除,我自己缩小allow范围好像也行不通,那么为什么不可以把neverallow中排除掉的类型加到我自己的te文件里面呢?
有了这个想法,让我们回到最初的domain.te 948行,看看:
在这里插入图片描述
这里neverallow coredomain file_type:file entrypoint,我的ftpd ntpd 都属于coredomain类型,所以才会报错,之前试过了删除coredomain file_type 类型包含没用,但是仔细看上面 -system_file_type -postinstall_file两种类型是被排除在外的,于是,把te文件改成这样:
注:neverallow中的-system_file_type表示排除对这种文件类型的neverallow。人话解释就是 system_file_type不受此规则限制。
在这里插入图片描述
结果 顺利编译通过,刷到板子上,功能也运行正常。

总结:Android13 规定好的neverallow规则是改不了的,改了会报很多莫名其妙看不懂的错误,只能在自己的te文件里加上neverallow中的 排除类型,以此通过neverallow的编译规则检测。这种解决方法应该是比较通用的了,只要编译出现neverallow报错,都可以通过这种方式排错。

最后这次排错解决花了一个星期的时间,中间大部分花在了无用的博客上面,如果大家也是搞计算机的,拜托 麻烦写博客的时候动点脑子,不要抄袭,不要照搬,不要胡言乱语,尽量不要有错别字,行文严谨有逻辑一点,让人好读懂一点,还有就是要确保自己写的东西是正确的。希望大家都能把博客写好,给人以便利,给自己以价值。

<think>好的,我现在需要帮助用户解决Androidinit.rc文件中通过shell脚本启动APK服务的问题。首先,我需要回忆一下相关的知识,并结合提供的引用内容来给出正确的步骤。 首先,用户提到的是init.rc文件,这是Android初始化过程中使用的脚本文件,由init进程解析执行。根据引用[2]和[3],init.rc不能直接通过adb修改,必须修改系统源码中的文件,然后重新编译ROM或者修改boot.img。所以用户需要修改系统源码中的init.rc文件,比如在/system/core/rootdir/init.rc或者device目录下的特定文件,如引用[4]提到的device/mediatek/mt67xx/init.mt67xx.rc。 接下来,用户想在init.rc中启动APK的服务。根据引用[5],使用pm install安装APK,然后使用am startservice启动服务。这需要在init.rc添加相应的命令。但是,init.rc中的语法是特定的,不能直接写shell命令,需要通过service和exec来执行。 根据引用[3],init.rc使用AIL(Android Init Language)语法,需要定义服务,并指定执行命令。例如,定义一个服务,执行sh脚本,或者在命令中直接运行pm和am命令。但需要注意的是,pm和am命令可能需要一定的环境变量和上下文才能正确执行,可能需要等待zygote启动完成,因此可能需要设置on property触发器,比如在boot完成后的某个阶段执行。 另外,引用[1]提到在init.rc中加入脚本开机安装APK并启动服务。这里可能需要将APK预置到系统镜像中,比如放在/system/app目录下,或者通过脚本从特定位置安装。例如,将APK放在device目录下,编译时拷贝到out目录,这样在系统启动时可以通过脚本安装。 结合这些信息,步骤应该是: 1. 将APK文件放置在系统镜像的某个位置,比如/system/AirPlayer/,如引用[5]中的例子。 2.init.rc添加一个服务,执行安装APK和启动服务的命令。可能需要使用exec或者service来运行shell命令。 3. 确保命令在适当的时机执行,比如在boot_completed阶段之后。 需要注意的是,直接使用pm install和am命令可能需要系统服务已经启动,因此可能需要将服务设置为在late-init或者某个特定的触发器之后执行。例如,在on property:sys.boot_completed=1时触发。 另外,引用[4]提到在init.rc中写入服务,比如: service start_apk_service /system/bin/sh /path/to/script.sh 然后,在script.sh中编写安装和启动命令。或者直接在init.rc中使用exec命令: exec /system/bin/pm install /system/AirPlayer/Airplay.apk exec /system/bin/am startservice ... 但可能需要等待zygote启动完成,因此可能需要设置触发器。 综上,正确的步骤应该是修改init.rc文件,添加一个服务,在合适的时机执行安装APK和启动服务的命令,可能需要使用sh脚本来组合多个命令,或者在服务中直接调用pm和am命令,并设置适当的触发器。</think>### 如何在 init.rc 文件中通过 shell 脚本启动 APK 的服务 #### 步骤说明 1. **预置 APK 文件到系统镜像** 将 APK 文件(如 `Airplay.apk`)放置在系统镜像的 `/system/` 目录下(例如 `/system/AirPlayer/`),需在编译时通过脚本或 `device/` 目录的配置实现文件拷贝[^1][^4]。 2. **修改 init.rc 文件** 在系统源码的 `init.rc` 文件中添加服务定义。建议优先修改设备相关的 `init.*.rc` 文件(如 `device/mediatek/mt67xx/init.mt67xx.rc`)。示例如下: ```bash # 定义安装并启动服务的脚本 service start_apk_service /system/bin/sh /system/AirPlayer/start_apk.sh class main user root oneshot # 仅执行一次 disabled seclabel u:r:system_server:s0 on property:sys.boot_completed=1 # 系统启动完成后触发 start start_apk_service ``` 3. **编写启动脚本** 创建 `/system/AirPlayer/start_apk.sh` 脚本,内容需包含安装 APK 和启动服务的命令: ```bash #!/system/bin/sh pm install -r /system/AirPlayer/Airplay.apk # 安装 APK(-r 表示覆盖安装) am startservice -n com.waxrain.airplayer/com.waxrain.airplayer.WaxPlayService # 启动服务[^5] ``` 4. **设置文件权限** 在编译脚本中确保 APK 和启动脚本的权限正确: ```makefile # 在 Android.mk 或编译脚本中添加 PRODUCT_COPY_FILES += device/your_device/Airplay.apk:system/AirPlayer/Airplay.apk PRODUCT_COPY_FILES += device/your_device/start_apk.sh:system/AirPlayer/start_apk.sh ``` 5. **重新编译并烧写系统** 修改源码后重新编译 ROM,并将镜像烧写到设备[^2][^3]。 #### 注意事项 - **权限问题**:需以 `root` 用户运行脚本,并在 SELinux 策略中允许相关操作(通过 `seclabel` 指定上下文)[^4]。 - **执行时机**:通过 `sys.boot_completed=1` 确保命令在系统完全启动后执行,避免因依赖服务未就绪而失败。 - **命令路径**:使用绝对路径 `/system/bin/pm` 和 `/system/bin/am` 以避免环境变量问题。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苏苏码不动了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值