记录一个文件节点权限未生效的问题

作者 by adtxl / 2021-11-18 / 暂无评论 / 498 个足迹

问题说明:

在VTS测试时,armeabi-v7a VtsHalThermalV1_0TargetTest测试case报错,thermal hal测试报错。如下所示
image.png

测试错误很明显,无法获取温度节点。Thernal HAL也提示无法读取温度,查看thermal的sys文件节点,用户和用户组权限为root,如下图所示

imagef55f1292fcbe18d8.png

直接使用chown命令修改/sys/devieces/virtual/thermal/thermal_zone*/下文件节点的用户和用户组权限为system,thermal hal可以获取温度,故决定在init rc文件中使用chown设置thermal相关文件节点用户权限为system。

修改好相关rc文件后,重新烧写,重启,相关节点确实改为system.
但是,vts测试时,烧写原生system.img后,再run armeabi-v7a VtsHalThermalV1_0TargetTest,发现依旧报错。
查看/sys/devieces/virtual/thermal/thermal_zone*/下节点权限又变成root.
也就是说,虽然我在相关的rc文件中添加了chown,但烧写了原生的system.img后,文件节点权限被改变了,这是为什么呢?

分析原因

一开始,我将chown添加到了init.eswin.tv.rc,其中init.eswin.tv.rc的import顺序如下
system/core/rootdir/init.rc文件中,如下所示:

import /init.environ.rc
import /system/etc/init/hw/init.usb.rc
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /system/etc/init/hw/init.usb.configfs.rc
import /system/etc/init/hw/init.${ro.zygote}.rc

其中ro.hardware=sc1401aj1
然后import顺序如下:

init.rc--->init.sc1401aj1.rc--->init.ld60_evb.rc--->init.eswin.tv.rc

其中,他们的位置如下:

vendor/etc/init/hw/init.sc1401aj1.rc
vendor/etc/init/hw/init.ld60_evb.rc
vendor/etc/init/hw/init.eswin.tv.rc

实际上,在init.sc1401aj1.rc文件中,是这样的,如下所示

import /vendor/etc/init/hw/init.${ro.hardware}.usb.rc
import /vendor/etc/init/hw/init.${ro.product.model}.rc

这个ro.product.model正常情况下就是ld60_evb,查看system/build.prop文件,发现ro.product.model在里面,这就解释通了,因为烧写system.img后该文件就变为google原生的,无该文件,也就import不到了。

console:/ # cat /system/build.prop | grep product
ro.product.system.brand=Eswin
ro.product.system.device=ld60_evb
ro.product.system.manufacturer=Eswin
ro.product.system.model=ld60_evb
ro.product.system.name=ld60_evb
# ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete,
# use ro.product.cpu.abilist instead.
ro.product.cpu.abi=armeabi-v7a
ro.product.cpu.abi2=armeabi
ro.product.cpu.abilist=armeabi-v7a,armeabi
ro.product.cpu.abilist32=armeabi-v7a,armeabi
ro.product.cpu.abilist64=
ro.product.locale=zh-CN
# ro.build.product is obsolete; use ro.product.device
ro.build.product=ld60_evb

实际上,在烧写了原生system,img后,该属性为

console:/ # getprop ro.product.model
AOSP on ARM32

继续分析,在init进程的启动过程中,在SecondStageMain中,会解析rc文件

int SecondStageMain(int argc, char** argv)---> LoadBootScripts(am, sm)

看下这个函数,如下所示,如果ro.boot.init_rc为空,实际上在我们这里也确实为空。它只会解析/vendor/etc/init,并不会直接解析/vendor/etc/init/hw路径,所以init.ld60_evb.rc以及init.eswin.tv.rc等rc文件均不会生效。

static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
    Parser parser = CreateParser(action_manager, service_list);

    std::string bootscript = GetProperty("ro.boot.init_rc", "");
    if (bootscript.empty()) {
        parser.ParseConfig("/system/etc/init/hw/init.rc");
        if (!parser.ParseConfig("/system/etc/init")) {
            late_import_paths.emplace_back("/system/etc/init");
        }
        // late_import is available only in Q and earlier release. As we don't
        // have system_ext in those versions, skip late_import for system_ext.
        parser.ParseConfig("/system_ext/etc/init");
        if (!parser.ParseConfig("/product/etc/init")) {
            late_import_paths.emplace_back("/product/etc/init");
        }
        if (!parser.ParseConfig("/odm/etc/init")) {
            late_import_paths.emplace_back("/odm/etc/init");
        }
        if (!parser.ParseConfig("/vendor/etc/init")) {
            late_import_paths.emplace_back("/vendor/etc/init");
        }
    } else {
        parser.ParseConfig(bootscript);
    }
}

解决方案

当时没搞清楚,把chown加到了init.sc1401aj1.rc,这样肯定是可以的。

实际上,这里可能使用ro.product.vendor.model属性更好,因为这个在vendor/build.prop下面。当然,由于没有实际测试,有没有其它问题就不好说了。

独特见解