概述

在前段时间的工作中,需要开发一个开机自动启动的脚本,现把开发过程记录一下

主要框架

编写一个可以开机自动启动的脚本,方法就是通过rc文件,在boot_complete=1时,去启动这个服务,那么,可以先基于以上思路,创建实现脚本所需要的文件。

通常来说,我这个脚本是要放在vendor分区的,因此将脚本放到vendor目录下,参考其他的脚本,创建3个空的文件如下:

multi_tpinsmod/      //脚本文件夹
├── Android.bp          //bp文件,用于放置编译参数
├── multi_tpinsmod.cpp  //脚本的代码实现
└── multi_tpinsmod.rc   //rc文件,用于启动脚本0 directories, 3 files

接下来,我们就来实现如上框架。

脚本编写

脚本的实现方式有很多,包括c/c++,shell等,基于简单高效的原则,shell是比较好的选择,但是对于Android的开机自启动脚本,个人建议是选择c/c++来编写,如果是用于调试的手动执行脚本,可以使用shell来写,主要原因如下:

  1. Android中有许多权限问题,而以shell脚本来说,会有许多的selinux权限限制(并且许多权限还无法绕过),如果是开机自启动的脚本来说,我们并没有adb那样的权限,因此很容易导致运行失败。
  2. 手动执行脚本,我们可以通过su和setenforce 0来临时获取权限,且shell脚本易于修改。

由于本次是需要进行开机启动的,那么这里笔者选择使用了c++来实现脚本,代码主体不多赘述,依个人实现。

Android.bp

脚本的主要代码编写好后,Android.bp的内容如下:

cc_binary {                          //表示将脚本编译为bin文件name: "multi_tpinsmod",            //模块名字init_rc: ["multi_tpinsmod.rc"], //模块关联的rc文件relative_install_path: "hw",   //是否放在hw路径下vendor:true,                 //表示编译到vendor分区cflags: [                        //flag,用于忽略一下warning"-Wall","-Wextra","-Werror",],shared_libs: [                   //需要使用的共享库"libbase","liblog","libprocessgroup","libcutils","libutils",],srcs: [                           //源文件"multi_tpinsmod.cpp",],
}

rc编写

rc文件的编写则比较简单了,参考如下

on property:sys.boot_completed=1    //在开机启动完成时的动作,这里是启动服务start multi_tpinsmodservice multi_tpinsmod /vendor/bin/hw/multi_tpinsmod    //定义了一个服务,和该服务的执行文件路径disabled                                            //表示不随class自动启动,需要手动启动user root                                          //用户group shell root                                    //分属的用户组oneshot                                             //表示服务退出后不重新启动capabilities SYS_MODULE

rc文件的参考如上,其余rc,可以参考网上资料自行学习。

编译

以上代码都准备好了以后,就可以进行编译了,编译可以通过mm命令直接在源码路径下执行,也可以将其配置到方案里面编译整个sdk。

一. 调试可以在源码目录下通过mm编译,执行mm需要先在top目录执行过lunch等

二.在sdk里面编译的方法如下:

  1. 在方案目录,找一个地方,增加PACKAGE_PRODUCT +=,参考如下
#support multi_tpinsmod
PRODUCT_PACKAGES += \multi_tpinsmod
  1. 编译整个sdk,如果有编译错误,自行解决

  2. 编译完成后,在out目录下,搜索是否有编译出来的产物,如rc文件和bin文件

调试

编译完成后,烧录固件到机器中,然后可以通过手动执行的方式,查看脚本功能是否实现。

如果有权限报错,可以先临时关闭selinux进行调试,临时关闭selinux方式如下:

在adb中执行

setenforce 0

临时关闭selinux权限,然后手动执行脚本,确保脚本功能完成。脚本功能完成后,就可以进行脚本的权限调试了。

权限设置

更改文件的权限类型

一般来说,文件的类型在vendor目录下,是vendor_file,这种类型是没有执行权限,也就是无法通过rc来启动的,查看文件类型可以通过ls -lZ命令查看:

如图所示,通过ls -lZ查看文件的类型,如果看到类型为vendor_file,则表示需要配置文件的类型,以获取执行权限。

修改步骤如下:

  1. 找到配置selinux权限位置,一般来说,可以通过在Android目录下执行如下命令来获取selinux的配置目录,
get_build_var BOARD_SEPOLICY_DIRS
  1. 找到目录后,如笔者的配置位置在
device/softwinner/common/sepolicy/vendor
  1. 在目录下,先新建一个与脚本名字相同的te文件,如笔者的脚本名为A,那么可以新建一个文件A_default.te的文件
  2. 在新建的te文件中,编写如下:

表示新建一个名字为multi_tpinsmod的domian域

  1. 在同目录下的file_contexts中,增加如下

其中,前面为bin文件的路径,后面为固件格式,中间的为刚才新建的multi_tpinsmod_defalut.te中的执行类型。

  1. 完成后,重新编译固件,烧录固件,再次查看bin文件的类型,查看类型是否已经从vendor_file变成了自己所定义的multi_tpinsmod_exec类型。
  2. 临时关闭selinux权限,然后手动执行bin文件,查看串口(或者dmesg),查看是否有类似的报错信息
type=1400 audit(1629099780.612:406): avc: denied { write } for comm="tp_module_insmo" name="property_service" dev="tmpfs" ino=11726 scontext=u:r:tp_module_insmod:s0 tcontext=u:object_r:property_socket:s0 tclass=sock_file permissive=1
type=1400 audit(1629099780.612:407): avc: denied { connectto } for comm="tp_module_insmo" path="/dev/socket/property_service" scontext=u:r:tp_module_insmod:s0 tcontext=u:r:init:s0 tclass=unix_stream_socket permissive=1type=1107 audit(1629099780.616:408): uid=0 auid=4294967295 ses=4294967295 subj=u:r:init:s0 msg='avc: denied { set } for property=persist.vendor.tp.name pid=1056 uid=0 gid=2000 scontext=u:r:tp_module_insmod:s0 tcontext=u:object_r:vendor_default_prop:s0 tclass=property_service permissive=1'type=1400 audit(1629099780.632:409): avc: denied { sys_module } for comm="tp_module_insmo" capability=16 scontext=u:r:tp_module_insmod:s0 tcontext=u:r:tp_module_insmod:s0 tclass=capability permissive=1type=1400 audit(1629099780.632:410): avc: denied { module_load } for comm="tp_module_insmo" path="/vendor_dlkm/lib/modules/gslX680new.ko" dev="overlay" ino=48232 scontext=u:r:tp_module_insmod:s0 tcontext=u:object_r:vendor_file:s0 tclass=system permissive=1type=1400 audit(1629099780.832:411): avc: denied { read } for comm="tp_module_insmo" name="input" dev="sysfs" ino=8803 scontext=u:r:tp_module_insmod:s0 tcontext=u:object_r:sysfs:s0 tclass=dir permissive=1tp_module_insmo (1056) used greatest stack depth: 9936 bytes left
type=1400 audit(1629099780.840:412): avc: denied { open } for comm="tp_module_insmo" path="/sys/class/input" dev="sysfs" ino=8803 scontext=u:r:tp_module_insmod:s0 tcontext=u:object_r:sysfs:s0 tclass=dir permissive=1type=1400 audit(1629099780.840:413): avc: denied { read } for comm="tp_module_insmo" name="name" dev="sysfs" ino=39538 scontext=u:r:tp_module_insmod:s0 tcontext=u:object_r:sysfs:s0 tclass=file permissive=1
type=1400 audit(1629099780.840:414): avc: denied { open } for comm="tp_module_insmo" path="/sys/devices/platform/soc@2900000/5002000.twi/i2c-0/0-0040/input/input7/name" dev="sysfs" ino=39538 scontext=u:r:tp_module_insmod:s0 tcontext=u:object_r:sysfs:s0 tclass=file permissive=1

说明脚本已经基本完成,只剩余selinux权限问题,下一步就是配置权限问题。

配置selinux权限

手动配置权限

回到我们刚才创建的multi_tpinsmod_defalut.te,权限的配置则需要在该文件来完成。

解析selinux信息

我们拿一条selinux权限来看,例如:

type=1400 audit(1629099780.832:411): avc: denied { read } for comm="tp_module_insmo" name="input" dev="sysfs" ino=8803 scontext=u:r:tp_module_insmod:s0 tcontext=u:object_r:sysfs:s0 tclass=dir permissive=1

那么该语句表示需要配置的权限如下:

  1. scontext:谁需要权限,这里表示为tp_module_insmod
  2. tcontext:需要的是谁的权限,这里表示需要获取sysfs的权限
  3. tclass:需要获取的tcontext中表示的具体的类别,这里为idr
  4. avc: denied { read }:表示需要获取的是read权限

那么组合起来就是:tp_module_insmod需要获取sysfs中dir的read权限,那么,权限配置语句则为如下:

allow tp_module_insmod sysfs:dir read

以上语句就表示运行tp_module_insmod去读sysfs中的文件夹权限。

其他的可以自行完成。

使用audit2allow来快速配置权限

除了通过手动的方式配置权限,也可以通过使用在Android源码中的audit2allow工具来快速完成权限的配置。工具的使用步骤如下:

  1. 将所有相关的selinux的报错复制到一个文本中,此操作最好在selinux关闭的情况下,去完成收集,这样收集的比较全面
  2. 将log中的时间打印去除,语句以type=1400开头。
  3. 将selinux报错文件放在android的top目录中,然后执行audit2allow -i a.txt,执行结果如下:

可以看到,selinux语句被解析了出来,将其复制到对应的te文件下,重新编译,看是否会有报错(audit2allow仅进行解析,部分权限是无法获取的)。

  1. 重新编译,可能会有如下报错提示:nerverallow···

可以看到,编译提示,不允许vendor去获取属性的设置权限,这时可以先将报错的语句给注释掉,验证其他的权限是否还存在问题。

nerverallow处理

一般来说,出现了nerverallow是比较头疼的事情,出现的原因主要是使用了google不允许的权限导致的,那么解决办法一般有2个:

  1. 在出现报错的地方,强行注释掉google不允许的权限,这样可能会造成google的gms测试无法通过
  2. 通过其他办法绕过该权限,如vendor访问system是没办法实现的,那就可以将需要访问的资源再编译一份放到vendor

prop的设置

在上面出现的vendor_default_prop是可以通过其他办法进行绕过的,一般来说google不允许一个服务区获取所有的vendor的属性设置权限,但是允许获取特定的属性组的权限,以上述的属性设置为例,设置方法如下:

  1. 获取具体需要进行设置的属性:需要在代码中查看:
persist.vendor.tp.name
persist.vendor.tp.path

可以找到是对这2个属性进行了设置和读取。

  1. 在te文件的目录下,存在一个property.te文件,在此处创建一个属性类型
+type vendor_tp_prop, property_type, vendor_property_type;
  1. 在property_contexts中,将具体的2个属性给到我们创建的vendor_tp_prop,参考如下

  1. 在我们自己的te文件中,赋予属性权限,语句如下:
set_prop(multi_tpinsmod, vendor_tp_prop)
  1. 实现后,再次编译,没问题,通过。

selinux注意事项

  1. 不要跨分区调用,如system调用vendor里的文件
  2. 部分无法执行的方法可以通过属性的方式让更高权限的init来执行:如在服务里设置某个属性,然后由init在init.rc中触发相应的动作,以此来绕过权限的限制

[Android]开机自启动脚本和selinux权限配置相关推荐

  1. 开机自启动脚本_Linux配置开机自启动执行脚本的两种方法

    代码来源:oschina 原文作者:醉生梦死zsms 原文链接:https://my.oschina.net/u/3285916/blog/1622358 本文版权归原作者所有,如有侵权请立即与我联系 ...

  2. linux开发板开机自启动脚本,linux 添加开机自启动脚本

    Linux设置服务开机自动启动的方式有好多种,这里介绍一下通过chkconfig命令添加脚本为开机自动启动的方法. 1. 编写脚本autostart.sh(这里以开机启动redis服务为例),脚本内容 ...

  3. Android开机自启动C程序调试

    Android开机自启动C程序调试 本次记录是关于如何在rk3566的Android11版本下将led时钟显示添加成开机自启动的C程序. 首先,当然是在sdk中会被执行到的.rc文件中将我们所需要执行 ...

  4. 迅为RK3399开发板Debian系统设置开机自启动脚本

    如果想要开机运行某程序,需要在开发板上编辑"/etc/rc.local"文件,在此文件添加你想开机运行的命令即可.这里给大家做一个示范,我们的需求是开机自启动 hello.sh 脚 ...

  5. bash 脚本中激活conda环境_ubuntu18.10目标检测算法环境部署+开机自启动脚本创建screen下的web服务...

    内容概要 cuda+cudnn+python环境安装 ubuntu18的开机自启动脚本 screen服务开启 以我个人的实践来看,把python开发的算法封装成webserver的服务供前端程序调用是 ...

  6. CentOS7 开机自启动脚本 chkconfig方式

    Linux设置自启动 sysv-rc-conf - Linux设置开机自动启动 CentOS7 开机自启动脚本 chkconfig方式 chkconfig 设置开机自启动 注意点 自启动脚本放置路径: ...

  7. 树莓派Raspberry Pi OS开机自启动脚本

    树莓派Raspberry Pi OS开机自启动脚本 1. 需求和来源 2. 后台运行Python 3. 运行Terminal 1. 需求和来源 想让设备开机后就要运行Python工程文件 那么需设置l ...

  8. 【记录】我的一个Centos开机自启动脚本的制作

    原文地址: http://www.2cto.com/os/201306/220559.html 我的一个Centos开机自启动脚本的制作 一.切换到/etc/init.d/ 二.制作sh脚本 vi a ...

  9. Linux定时任务与开机自启动脚本(cron与crontab)

    开机自启动脚本 网上常见的脚本开机自启方法是: 假设要自启的脚本位于 /home/user/test.sh 给脚本可执行的权限 sudo chmod +x /home/user/test.sh 将脚本 ...

最新文章

  1. vs2005中文的,可是有180天的适用期,哪位高手能破了啊
  2. ios 获取一个枚举的所有值_凯哥带你从零学大数据系列之Java篇---第十一章:枚举...
  3. c oracle帮助类,C#DbHelperOra,Oracle数据库帮助类
  4. 腾讯、百度、小米等7家互联网各大厂的中台建设怎么样了?
  5. MySQL buffer pool里的三种链表和三种page
  6. font-familly:' 阿里巴巴-普惠体 '【永久免费 】 - 下载与使用
  7. Oracle_忘记密码
  8. oc 协议 回调 静态成员_ios – 在一个块中,__block变量和静态变量之间的实际区别是什么?...
  9. 腾讯云VP王龙:与英特尔的合作将加速AI落地,硬件的灵活性要变得更强
  10. mysql select_type
  11. C++ Primer Plus 第六版课后习题答案(第五章)
  12. 怎样限制Word文档被复制粘贴?word限制编辑的使用技巧
  13. [转]关于Gmail打不开的解决办法
  14. outlook2013邮箱找不到服务器,outlook发邮件总提示找不到服务器,不知哪里设置不对,请哪位大侠指点一下...
  15. 学习计划 -- 实时更新
  16. 信息收集的方法有哪些
  17. CCL: Cross-modal Correlation Learning With Multigrained Fusion by Hierarchical Network 论文笔记
  18. 官方文档——AlwaysOn AG的先决条件、限制和建议
  19. TIME_WAIT状态和FIN_WAIT_2状态
  20. android gps 卫星数据格式,Gps开发实战——卫星数量获取

热门文章

  1. 记一次放内存切图|BytesIO|PIL库
  2. 最新版centos7下git安装教程
  3. linux网卡配置多个IP详解
  4. powerbi 服务主体认证
  5. 全局路径规划:图搜索算法介绍4(RRT/RRT*)
  6. 关于Windows Server 2008安全防护
  7. 网络历史之坑道的作用01
  8. C语言差缺补漏,补充一些容易遗忘忽视的知识点(一)
  9. 微信新玩法!这些关键词可触发表情雨
  10. MP3TAG:ID3V2