速发国际365的最新网站-百特365平台可靠吗-日博365投注网

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

概述 在前段时间的工作中,需要开发一个开机自动启动的脚本,现把开发过程记录一下 主要框架 编写一个可以开机自动启动的脚本,方法就是

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

概述

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

主要框架

编写一个可以开机自动启动的脚本,方法就是通过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来写,主要原因如下:

Android中有许多权限问题,而以shell脚本来说,会有许多的selinux权限限制(并且许多权限还无法绕过),如果是开机自启动的脚本来说,我们并没有adb那样的权限,因此很容易导致运行失败。手动执行脚本,我们可以通过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_tpinsmod

service 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里面编译的方法如下:

在方案目录,找一个地方,增加PACKAGE_PRODUCT +=,参考如下

#support multi_tpinsmod

PRODUCT_PACKAGES += \

multi_tpinsmod

编译整个sdk,如果有编译错误,自行解决

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

调试

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

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

在adb中执行

setenforce 0

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

权限设置

更改文件的权限类型

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

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

修改步骤如下:

找到配置selinux权限位置,一般来说,可以通过在Android目录下执行如下命令来获取selinux的配置目录,

get_build_var BOARD_SEPOLICY_DIRS

找到目录后,如笔者的配置位置在

device/softwinner/common/sepolicy/vendor

在目录下,先新建一个与脚本名字相同的te文件,如笔者的脚本名为A,那么可以新建一个文件A_default.te的文件在新建的te文件中,编写如下:

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

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

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

完成后,重新编译固件,烧录固件,再次查看bin文件的类型,查看类型是否已经从vendor_file变成了自己所定义的multi_tpinsmod_exec类型。临时关闭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=1

type=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=1

type=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=1

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

tp_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=1

type=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

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

scontext:谁需要权限,这里表示为tp_module_insmodtcontext:需要的是谁的权限,这里表示需要获取sysfs的权限tclass:需要获取的tcontext中表示的具体的类别,这里为idravc: denied { read }:表示需要获取的是read权限

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

allow tp_module_insmod sysfs:dir read

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

其他的可以自行完成。

使用audit2allow来快速配置权限

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

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

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

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

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

nerverallow处理

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

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

prop的设置

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

获取具体需要进行设置的属性:需要在代码中查看:

persist.vendor.tp.name

persist.vendor.tp.path

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

在te文件的目录下,存在一个property.te文件,在此处创建一个属性类型

+type vendor_tp_prop, property_type, vendor_property_type;

在property_contexts中,将具体的2个属性给到我们创建的vendor_tp_prop,参考如下

在我们自己的te文件中,赋予属性权限,语句如下:

set_prop(multi_tpinsmod, vendor_tp_prop)

实现后,再次编译,没问题,通过。

selinux注意事项

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

← 上一篇: 葸的笔顺(笔画顺序)汉字葸的笔顺动画
下一篇: 正在阅读:剪映激励中心在哪里剪映激励中心在哪里 →

相关推荐

QQ飞车里的徒弟怎么样领取师徒礼包

QQ飞车里的徒弟怎么样领取师徒礼包

智能回答 QQ飞车里的徒弟怎么样领取师徒礼包 展开 没找到满意答案?去问豆包AI智能助手 取消 复制问题 xiaerdong1991 达到等级系统会自动发奖励

书虫系列到底有多少本啊?

书虫系列到底有多少本啊?

“书虫”是外语教学与研究出版社和牛津大学出版社共同出版的双语读物,主要用于英语阅读的启蒙和提高,中英双语对照阅读,提高阅读量,

關於攀岩,你用了多久的時間爬到了5.11這個水平?

關於攀岩,你用了多久的時間爬到了5.11這個水平?

第一次把命交到自己搭的錨點上,嚇得要死 5.10到5.11更是感覺跨了一大步,首先是對一些技術動作的要求變高、其次是跟多指尖力量的介入、最

世界杯半决赛!德国5次泪洒赛场,阿根廷5战全胜封神!

世界杯半决赛!德国5次泪洒赛场,阿根廷5战全胜封神!

世界杯赛场上有一种痛,叫“离冠军只差两步却摔了跟头”。 德国队对这滋味最熟悉,他们12次冲进半决赛,5次栽在最后一道坎上,成了半决赛

“牡”字是什么意思?正确读音、注音及书写笔顺详解

“牡”字是什么意思?正确读音、注音及书写笔顺详解

“牡”字是什么意思?正确读音、注音及书写笔顺详解 关键字: 笔顺笔画写法 汉字「牡」解析 一、基本信息 拼音:mǔ(与“母”同音) 注音

原始传奇道士的嗜血术在哪学习

原始传奇道士的嗜血术在哪学习

在原始传奇游戏中,道士角色的技能获取途径多种多样,每种方法都有其独特之处首先,在游戏开服初期,1至30天内,玩家可以在商城选择充值3