最近项目碰到一个奇怪的问题,wifi组报告说自己的rc脚本创建目录不成功,提示如下错误

11-19 18:40:57.855  1000 12091 13106 E WifiApBackupRestore: FileWriter exception java.io.FileNotFoundException: /data/misc/wifi_hostapd/backup.conf: open failed: ENOENT (No such file or directory)

说原因是因为rc脚本在开机的时候,创建/data/misc/wifi_hostapd目录失败

   Line 44430: <14>[   14.878830]  [7:           init:    1] init: Command 'mkdir /data/misc/wifi_hostapd 0771 wifi system' action=post-fs-data (/vendor/etc/init/wifi.rc:8) took 0ms and failed: mkdir() failed: Permission denied   Line 44430: <14>[   14.878830]  [7:           init:    1] init: Command 'mkdir /data/misc/wifi_hostapd 0771 wifi system' action=post-fs-data (/vendor/etc/init/wifi.rc:8) took 0ms and failed: mkdir() failed: Permission denied

创建目录的操作在/vendor/etc/init/wifi.rc里面,开机的时候被init进程load进来执行

android/system/core/init/init.cppstatic void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {147            parser.ParseConfig("/init.rc");...160            if (!parser.ParseConfig("/vendor/etc/init")) {161                late_import_paths.emplace_back("/vendor/etc/init");162            }

整个/vendor/etc/init目录下的rc文件都会被加载进来。

执行的时机是action=post-fs-data,在文件系统加载成功之后,理论上不应该有问题,毕竟init进程具有root权限,在data分区创建目录也不太可能被selinux拦截,因为其他rc里面也要创建目录,但只看到wifi.rc出现没有权限的情况。但是log的确打印了init无权限创建,显得很矛盾。

保险起见还是打印下内核态创建/data/misc/wifi_hostapd的一些状态,把进程号打印出来

结果发现虽然main log打印的是init 1号进程无权限创建目录,但是内核显示是另外一个进程

<6>[   16.733758]  [4:           init:  572] [SYSC_mkdirat:3951] mkdirat found target wifi_hostapd<6>[   16.733852]  [4:           init:  572] [vfs_mkdir2:3899] error:-13<6>[   16.733893]  [4:           init:  572] [SYSC_mkdirat:3964] error:-13<6>[   16.733934]  [4:           init:  572] pid:572 process:init<6>[   16.733970]  [4:           init:  572] [SYSC_mkdirat:3973] return error:-13

进程572是个什么东西?

starqltechn:/ # ps -ATZ | grep initu:r:init:s0                    root             1     1     0   96364   5980 SyS_epoll_wait      0 S initu:r:vendor_init:s0             root           572   572     1   41796   3280 poll_schedule_timeout 0 S initu:r:vendor_init:s0             root           573   573     1   40452   3044 poll_schedule_timeout 0 S init

看出来,进程572和573都是init进程1的子进程,全新进程,但是最关键的是selinux标签不一样了,这完全可以解释572进程没有/data目录的mkdir权限,显然是selinux限制了。

但是vendor_init是什么东西?通过检索谷歌,发现原来vendor init是init进程分化出来的一个受限进程,专门用来执行vendor的rc脚本,防止vendor的rc脚本里面越权做一些非法的事情。因为wifi.rc属于vendor rc,因此其不能创建目录也就在理了。

搜索init的代码发现,init初始化的时候会创建这两个子进程,一个专门处理vendor的rc,另外一个专门处理/odm

/android/system/core/init/subcontext.cppconst std::string kVendorContext = "u:r:vendor_init:s0";53const char* const paths_and_secontexts[2][2] = {54    {"/vendor", kVendorContext.c_str()},55    {"/odm", kVendorContext.c_str()},56};

静态数组kVendorContext在初始化过程会被转换成一个进程,具体流程可以自行参考代码。

那解决这个问题的办法就有两种

1. 在非vendor的rc脚本里面创建/data目录下的需要的子目录

2. 修改vendor init的te策略文件,授权mkdir操作。

看起来还是方案1比较安全。

最后剩下一个问题,为什么main log里面打印的进程号是init 1号进程,不是init 572。

原因是因为init 572的log都传回给了init 1号进程去打印,导致误以为init 1进程没权限。

更多相关文章

  1. 一款霸榜 GitHub 的开源 Linux 资源监视器!
  2. Android获取应用信息判断网络连接返回桌面及卸载apk结束进程等的
  3. Android学习-HelloWorldAndroid
  4. 缓存统一管理工具类--android
  5. zygote服务启动
  6. Andorid利用sserver/runtime实现java执行linux程序或脚本
  7. android java 拷贝数据库文件到U盘,从U盘拷贝文件到私有目录下实
  8. Android(安卓)解压中文乱码(压缩包内中文乱码)
  9. 学习Android(一)

随机推荐

  1. flutter与android混合开发一:Android原生
  2. Android程序员指南(3)
  3. android之调用webservice 实现图片上传下
  4. 如何上传应用软件到 Android(安卓)Market
  5. Android之网络丢包事件
  6. Android开发艺术探索——第十章:Android的
  7. Android面试系列文章2018之Android部分之
  8. 在Android中创建和使用数据库
  9. android扫描二维码(zxing)附带小例子
  10. Android防止内存溢出浅析