写在前面
本次目的
详细步骤
添加自定义脚本
device/qcom/msm8909/lingump.sh
device/qcom/msm8909/msm8909.mk
system/core/libcutils/fs_config.c
添加自定义服务
system/core/rootdir/init.rc
device/qcom/sepolicy/common/file_contexts
device/qcom/sepolicy/common/lingump.te
device/qcom/sepolicy/common/init.te
device/qcom/sepolicy/common/lingump.te
重新编译
本次小结
SOC:Qualcomm msm8909
Core-Board:SC20-CE QA/PJ
Base-Board:xxx
Linux Kernel:xxx
Android:7.1
给系统添加自定义脚本服务,希望在系统开机的过程中执行。
也许有比这里更简单的方法,不一样的方法都是有不同的优缺点,比如系统跑起来后,通过重新挂载文件系统为可读可写,然后再在系统中编辑脚本等操作,这类操作调试的时候或许方便,但是一来没有集成到系统源码树中,不方便批量生产(试想每次烧录后还要开机去手动修改系统),二来把操作系统挂载成可读可写也不是很符合规范,所以,我这里的做法还是尽量参照安卓系统内部的一些规则进行实现。
首先是创建你自己的脚本文件:
#!/system/bin/sh
echo "[GumpIoT] : starting ... powered by lingump.sh"
echo "[GumpIoT] : endding ... powered by lingump.sh"
注意,如果这个脚本文件编码不对(比如在非类Unix系统下编写的),或者脚本的格式不对(比如没有上述第一行标语或者此标语不能够被目标系统正确识别的),会导致一系列错误,有可能提示你找不到这个脚本文件等等,如下,列出我的情况:
[ 11.881639] init: Starting service 'lingump'...
[ 11.897026] init: cannot execve('/system/etc/lingump.sh'): No such file or directory
[ 12.629945] init: Service 'lingump' (pid 489) exited with status 127
[ 11.539183] init: Starting service 'lingump'...
[ 11.575105] init: cannot execve('/system/etc/lingump.sh'): Exec format error
[ 12.328268] init: Service 'lingump' (pid 488) exited with status 127
接下来就是修改这个文件,在编译系统镜像时可以把该脚本打包到镜像中:
PRODUCT_COPY_FILES += device/qcom/msm8909/lingump.sh:system/etc/lingump.sh
安卓用这个文件管理系统初始化时的一些文件属性,包括一些文件权限设置 ,按照我的情况,我需要这个脚本是可读可运行的,其中“{ 00550, AID_ROOT, AID_SHELL, 0, "system/etc/lingump.sh" },”就是我参考其他文件的设置加上去的:
static const struct fs_path_config android_files[] = {
{ 00440, AID_ROOT, AID_SHELL, 0, "system/etc/init.goldfish.rc" },
{ 00550, AID_ROOT, AID_SHELL, 0, "system/etc/init.goldfish.sh" },
{ 00550, AID_ROOT, AID_SHELL, 0, "system/etc/init.ril" },
{ 00550, AID_ROOT, AID_SHELL, 0, "system/etc/lingump.sh" },
...
这里有一个小插曲,就是之前的一些安卓系统中,应在“system/core/include/private/android_filesystem_config.h” 中修改对应内容,但是我打开这个文件发现并没有相关的设置项,取而代之的是一条注释内容:
/* Rules for directories and files has moved to system/code/libcutils/fs_config.c */
哈哈,非常有意思,也就是告诉我们相关设置内容搬家了,但是告诉我们的新家地址却是错的,因为你无法找到这个地址,我也迷路了一段时间,我想肯定是留下这个字条的人犯困了,把“core”写成了“code”。
在该文件中添加新的服务项,具体内容含义可以自行上网了解:
service lingump /system/etc/lingump.sh
class main
user root
group root
oneshot
其实在有些时候这样子就算完成了,但是往往有些系统使用了SELinux,导致该服务无法正常运行,各种权限不足之类的,如果你遇到了类似问题,你还需要参照后续步骤,完成SELinux权限规则设置,这里直接给出步骤,如果需要,请自行上网了解SELinux相关的内容。
值得一提的是,我的系统之前做过了“ROOT权限的获取”,其中就设置了SELinux为“permissive”,有需要了解的朋友可以参考下面两个链接:
https://blog.csdn.net/uestc_ganlin/article/details/90673527
https://blog.csdn.net/uestc_ganlin/article/details/83377528
[ 12.318339] init: Service lingump does not have a SELinux domain defined.
如果遇到了上面的问题你首先需要:
添加以下内容,其中“lingump_exec”就是我们将要设定的规则类型:
/system/etc/lingump.sh u:object_r:lingump_exec:s0
添加该SELinux规则定义文件,参考以下内容,这里我们就定义了上面用到的规则类型“lingump_exec”:
type lingump, domain;
type lingump_exec, exec_type, file_type;
init_daemon_domain(lingump)
好了,配置完成SELinux的基本规则之后,再去尝试开机启动脚本,你可能还会遇到一些SELinux规则引发的一些拒绝行为,如下:
[ 12.344682] type=1400 audit(5832.459:3): avc: denied { getattr } for pid=1 comm="init" path="/system/etc/lingump.sh" dev="mmcblk0p21" ino=8
65 scontext=u:r:init:s0 tcontext=u:object_r:lingump_exec:s0 tclass=file permissive=1
根据SELinux规则设置,我们需要加入相关允许条件,该条规则参考格式为“allow
添加以下内容:
allow init lingump_exec:file getattr
接下来尝试的时候,我们又发现了新的拒绝行为:
[ 11.137184] init: Starting service 'lingump'...
[ 11.268677] type=1400 audit(19.379:3): avc: denied { getattr } for pid=478 comm="lingump.sh" path="/system/bin/sh" dev="mmcblk0p21" ino=59
3 scontext=u:r:lingump:s0 tcontext=u:object_r:shell_exec:s0 tclass=file permissive=1
[ 11.269595] type=1400 audit(19.379:4): avc: denied { getattr } for pid=478 comm="lingump.sh" path="/vendor" dev="rootfs" ino=6909 scontext
=u:r:lingump:s0 tcontext=u:object_r:rootfs:s0 tclass=lnk_file permissive=1
[ 11.432588] type=1400 audit(19.379:5): avc: denied { read } for pid=478 comm="lingump.sh" path="/system/bin/sh" dev="mmcblk0p21" ino=593 s
context=u:r:lingump:s0 tcontext=u:object_r:shell_exec:s0 tclass=file permissive=1
[ 12.611101] init: Service 'lingump' (pid 478) exited with status 0
同理,参考SELinux规则设置,我们为这些拒绝条件放行:
添加如下内容:
allow lingump shell_exec:file { getattr read };
allow lingump rootfs:lnk_file { getattr };
接下来继续尝试,没有了之前的问题,一切看起来那么正常:
[ 11.043634] init: Starting service 'lingump'...
[ 11.651394] init: Service 'lingump' (pid 496) exited with status 0
看起来没有异常日志,但是脚本中打印的内容为何没有输出呢,我猜测应该是控制台输出级别等原因导致的,不在本次探讨,目前看起来脚本服务运行是正常的,Over。
本次操作步骤中涉及的多次重新编译,建议完全重新编译所有内容后,再尝试相关操作。
这个人很懒,什么也没有留下!