Android:安卓开机后自动执行指定shell脚本(含SELinux权限问题解决)

1、编写自己的shell脚本

以RK3399 安卓Q为例,device/rockchip/rk3399/myscript.sh

#!/vendor/bin/sh

while true;do
        echo "++++++This is a test script !++++++" > /dev/console
        sleep 5
done

2、修改安卓源文件

2.1 修改device.mk编译时将脚本拷贝到镜像中

device/rockchip/rk3399/device.mk

@@ -59,6 +59,7 @@ PRODUCT_COPY_FILES += \
 PRODUCT_COPY_FILES += \
     $(LOCAL_PATH)/init.rk3399.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/init.rk3399.rc \
     $(LOCAL_PATH)/init.rk3399.usb.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/init.rk3399.usb.rc \
+    $(LOCAL_PATH)/myscript.sh:$(TARGET_COPY_OUT_VENDOR)/bin/myscript.sh \
     $(LOCAL_PATH)/wake_lock_filter.xml:system/etc/wake_lock_filter.xml \
     device/rockchip/rk3399/package_performance.xml:$(TARGET_COPY_OUT_ODM)/etc/package_performance.xml \
2.2 修改init.xxx.rc添加服务并启动

device/rockchip/rk3399/init.rk3399.rc

@@ -7,6 +7,7 @@ on property:sys.boot_completed=1
     chmod 0664 /sys/class/devfreq/ff9a0000.gpu/max_freq
     chown root system /sys/class/devfreq/dmc/governor
     chmod 0664 /sys/class/devfreq/dmc/governor
+    start myscript

 
@@ -51,3 +52,9 @@ on post-fs-data
     chown root system /sys/class/graphics/fb0/cabc
     chmod 0664 /sys/class/graphics/fb0/cabc
 
+service myscript /vendor/bin/myscript.sh
+    class main
+    user root
+    group root
+    disabled
+    oneshot

另外需要注意service的名称不要超过16个字符。

2.3 新建xxx.te文件声明运行域

device/rockchip/common/sepolicy/vendor/myscript.te

type myscript, domain;
type myscript_exec, exec_type, vendor_file_type, file_type;

init_daemon_domain(myscript)

allow myscript vendor_shell_exec:file rx_file_perms;
allow myscript vendor_toolbox_exec:file rx_file_perms;
2.4 修改file_contexts文件绑定te文件

device/rockchip/common/sepolicy/vendor/file_contexts

@@ -107,6 +107,7 @@
 /vendor/bin/hw/rk_wifi_hal                      u:object_r:rk_wifi_hal_exec:s0
 /vendor/bin/hw/rockchip\.hardware\.outputmanager@1\.0-service           u:object_r:rk_output_hal_exec:s0
 /vendor/bin/abc                                 u:object_r:abc_exec:s0
+/vendor/bin/myscript\.sh                        u:object_r:myscript_exec:s0
 /vendor/lib(64)?/libdrm.so                      u:object_r:same_process_hal_file:s0
 /vendor/lib(64)?/libdrm_rockchip.so             u:object_r:same_process_hal_file:s0
 /vendor/lib(64)?/libIMGegl.so                   u:object_r:same_process_hal_file:s0

至此,在系统没有开启SELinux权限情况下,以上步骤一般已经能正常执行了。但如果开启了SELinux,则需要继续下面第3步进行权限的配置。(SELinux权限可以adb或串口执行getenforce查询,Enforcing为开启、Permissive为关闭)

3、SELinux权限问题解决

3.1 解决方法1:添加相应的权限

① 查看所缺乏的权限

推荐使用命令“setenforce 0”先将SELinux权限暂时关闭后再执行命令“start 服务名”手动启动服务来抓取log,因为在SELinux权限开启时,缺乏的权限并不是一次性提示所有,而是添加完成一项后才会提示下一项权限,工作量会比较大。

adb shell "dmesg | grep avc" > avc_log.txt

permissive=0说明缺乏某项权限;permissive=1则代表只是提示,但不会造成影响。

例如提示以下log:

type=1400 audit(1611044417.518:29): avc: denied {
    
     write } for comm="myscript.sh" name="console" dev="tmpfs" ino=20774 scontext=u:r:myscript:s0 tcontext=u:object_r:console_device:s0 tclass=chr_file permissive=1
type=1400 audit(1611044417.518:29): avc: denied {
    
     write } for comm="myscript.sh" name="console" dev="tmpfs" ino=20774 scontext=u:r:myscript:s0 tcontext=u:object_r:console_device:s0 tclass=chr_file permissive=1
type=1400 audit(1611044417.518:30): avc: denied {
    
     open } for comm="myscript.sh" path="/dev/console" dev="tmpfs" ino=20774 scontext=u:r:myscript:s0 tcontext=u:object_r:console_device:s0 tclass=chr_file permissive=1

② 修改te文件添加权限

按照公式allow + scontext + tcontext + “:” + tclass + { permission };手动编写或使用audit2allow -i avc_log.txt命令自动生成相应规则,然后添加到对应文件中。

根据上一步抓取的log来编写相应的权限:

allow myscript console_device:chr_file {
    
     open write };

所以添加相关权限后的device/rockchip/common/sepolicy/vendor/myscript.te内容为:

type myscript, domain;
type myscript_exec, exec_type, vendor_file_type, file_type;

init_daemon_domain(myscript)

allow myscript vendor_shell_exec:file rx_file_perms;
allow myscript vendor_toolbox_exec:file rx_file_perms;
allow myscript console_device:chr_file {
    
     open write };
3.2 解决方法2:源码里关闭SELinux权限

system/core/init/selinux.cpp

@@ -97,6 +97,7 @@ EnforcingStatus StatusFromCmdline() {
    
    
 }
 
 bool IsEnforcing() {
    
    
+       return false;
     if (ALLOW_PERMISSIVE_SELINUX) {
    
    
         return StatusFromCmdline() == SELINUX_ENFORCING;
     }

参考资料

如有错误,希望大家不吝赐教。

猜你喜欢

转载自blog.csdn.net/weixin_44498318/article/details/112692310