MTK Android 8.1下新增开机服务
Android在启动过程中,第一个启动的用户态进程init会读取的启动脚本文件,主要完成一些初级的初始化,这些脚本文件以rc作为后缀名,它是"run commands"的缩写。并在/system/core/init/init.c中解析。rc文件被拆分成了各种类型,主文件为init.rc,其余根据功能还有设备进行了拆分,比如init.zygote32.rc和init.mt6763.rc。如果想要配置开机启动服务,需要修改rc文件。常用的方法有两种,常见的就是在源码里修改,然后重新编译。不想重新编译源码的话就使用boot image的解包和打包工具直接编辑image中的文件。
1 添加可执行文件
本文的场景是需要在系统中添加一个prebuilt可执行文件httpshell,向外暴露http服务,并需要实现开启自启动。首先在system/core下新建httpshell文件夹,将可执行文件拷入文件夹内,然后新建Android.mk文件,添加如下内容:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := httpshell LOCAL_MODULE := httpshell LOCAL_MODULE_PATH := $(TARGET_OUT)/bin LOCAL_MODULE_CLASS := EXECUTABLES include $(BUILD_PREBUILT)
然后执行make snod命令,重新生成system.img文件,在手机的system/bin目录下会看到我们添加的httpshell文件。现在完成了文件的添加,接下来还需要修改启动脚本文件,完成开机自启动。
2 修改rc文件
这里使用第一种方式,也就是在源码中修改。我这里的平台为mtk6763,可以选择修改主文件init.rc或者device/mtk/mt6763下的init.mt6763.rc文件。区别在于前者的改动体现在boot.img,后者的改动体现在vendor.img。在选定的rc文件中添加如下内容。然后重新编译boot.img或者vendor.img,烧录即可。
service httpshell /system/bin/httpshell class main user root group root disabled seclabel u:r:httpshell:s0
直接重启手机,发现提示 Service xxx does not have a SELinux domain defined 错误,表明需要指定selinux domain。
3 配置selinux权限
重新开机,使用dmesg命令查看kernel log,会提示以下错误。这种错误一般就两种情况,第一,可执行文件不存在,例如上面的案例中的/system/bin/httpshell不存在。就需要要查看手机里面改文件是否存在,对应的权限是否正确;第二,新增service的sepolicy配置不当。
init: cannot setexeccon('u:r:httpshell:s0'): Invalid argument
经过核查,发现httpshell没有配置正确的selinux配置文件。需要添加配置内容,需要注意的是android 8.0之后对权限做了分离,Sepolicy权限发生了变化,device/XXX/YYY/sepolicy存储在vendor.img中,假设修改的权限在该目录中,就要重新编译然后刷入vendor.img到手机中。
创建文件夹
在device/mtk/mt6763/sepolicy下创建httpshell文件夹
创建file_contexts
在httpshell文件夹内新建file_contexts文件,添加以下内容:
/system/bin/httpshell u:object_r:httpshell_exec:s0
添加te文件
在文件夹中新增httpshell.te文件,并添加以下内容
type httpshell, domain; type httpshell_exec, exec_type, file_type; init_daemon_domain(httpshell)
完成以上步骤之后,如果手机的selinux工作模式为enforce的话,服务仍然会启动失败,但是在permissive模式下,服务依然正常运行,但是会在kernel log下打印授权信息。可以通过 dmesg | grep avc > /sdcard/avc_log.txt 命令截取授权失败的信息,然后通过 policycoreutils 工具执行 audit2allow -i avc_log.txt 对日志进行解析,把解析出来的条目增加到httpshell.te中。然后再编辑/system/sepolicy/domain.te文件,添加 neverallow { -httpshell } { file_type -exec_type -postinstall_file }:file entrypoint; 即可。