Android 8.0 system app加载so Permission denied 解决

在预置包含react native 的Android app 预置到mtk 6739的系统中,此app 具体 platform 签名。此app启动会加载一些 facebook的so库
Android 8.0 system app加载so Permission denied 解决_第1张图片
发现此app 如果预置到system/app下,启动会报错。开始以为是没有把相关的so库 放到 system/app/xx/lib 下。在Android 6.0我都是可以正常启动的。发现在8.0 仍然会报错。
报错如下

2010-01-01 08:27:30.951 1887-1887/xxx W/Thread-2: type=1400 audit(0.0:19): avc: denied { execute } for path="/data/data/xxx/lib-main/libgnustl_shared.so" dev="dm-0" ino=1733 scontext=u:r:system_app:s0 tcontext=u:object_r:system_app_data_file:s0 tclass=file permissive=0
2010-01-01 08:27:30.957 1887-1915/xxx E/AndroidRuntime: FATAL EXCEPTION: Thread-2
    Process: xxx, PID: 1887
    java.lang.UnsatisfiedLinkError: dlopen failed: couldn't map "/data/data/xxx/lib-main/libgnustl_shared.so" segment 2: Permission denied
        at java.lang.Runtime.load0(Runtime.java:928)
        at java.lang.System.load(System.java:1621)
        at com.facebook.soloader.DirectorySoSource.loadLibraryFrom(DirectorySoSource.java:71)
        at com.facebook.soloader.DirectorySoSource.loadLibrary(DirectorySoSource.java:42)
        at com.facebook.soloader.SoLoader.loadLibraryBySoName(SoLoader.java:299)
        at com.facebook.soloader.DirectorySoSource.loadLibraryFrom(DirectorySoSource.java:65)
        at com.facebook.soloader.DirectorySoSource.loadLibrary(DirectorySoSource.java:42)
        at com.facebook.soloader.SoLoader.loadLibraryBySoName(SoLoader.java:299)
        at com.facebook.soloader.DirectorySoSource.loadLibraryFrom(DirectorySoSource.java:65)
        at com.facebook.soloader.DirectorySoSource.loadLibrary(DirectorySoSource.java:42)
        at com.facebook.soloader.SoLoader.loadLibraryBySoName(SoLoader.java:299)
        at com.facebook.soloader.DirectorySoSource.loadLibraryFrom(DirectorySoSource.java:65)
        at com.facebook.soloader.DirectorySoSource.loadLibrary(DirectorySoSource.java:42)
        at com.facebook.soloader.SoLoader.loadLibraryBySoName(SoLoader.java:299)
        at com.facebook.soloader.SoLoader.loadLibrary(SoLoader.java:247)
        at com.facebook.react.bridge.ReactBridge.staticInit(ReactBridge.java:18)
        at com.facebook.react.bridge.NativeMap.(NativeMap.java:19)
        at com.facebook.react.bridge.JSCJavaScriptExecutorFactory.create(JSCJavaScriptExecutorFactory.java:21)
        at com.facebook.react.ReactInstanceManager$5.run(ReactInstanceManager.java:912)
        at java.lang.Thread.run(Thread.java:764)
2010-01-01 08:27:30.958 1887-1887/xxx D/Surface: Surface::allocateBuffers(this=0x9820a800)
2010-01-01 08:27:30.962 651-673/system_process I/WindowManager: Focus moving from null to Window{52abab1 u0 xxx/xxx.MainActivity}
2010-01-01 08:27:30.964 651-662/system_process W/ActivityManager:   Force finishing activity xxx/.MainActivity
2010-01-01 08:27:30.970 651-1917/system_process W/AES: Exception Log handling...

之后把libgnustl_shared.so 放到 /system/lib下。这个错误仍然出现。
通过报错的log可以知道 react 不是通过System.loadLibrary加载libgnustl_shared.so,而是动态的通过dlopen 加载so。如果通过System.loadLibrary 加载 ,我已经把libgnustl_shared.so 放到 /system/lib下,就不会报这个错误。
System.loadLibrary()装载一个库是在Dalvik虚拟机中,而dlopen()只在你的本地进程中装载库
个人猜测 包含react native的app 在安装的时候会把 相关的so解压到/data/data/xxx/lib/下,然后dlopen("/data/data/xxx/lib")
通过adb 进入到/data/data/xxx/lib/下 发现 so文件都存在。

couldn't map "/data/data/xxx/lib-main/libgnustl_shared.so" segment 2: Permission denied

报错的意思并不是文件不存在。而是load加载失败,失败原因是Permission denied。
那为什么Permission denied ?

avc: denied { execute } for path="/data/data/xxx/lib-main/libgnustl_shared.so" dev="dm-0" ino=1733 scontext=u:r:system_app:s0 tcontext=u:object_r:system_app_data_file:s0 tclass=file permissive=0

因为 libgnustl_shared.so 在system_app_data_file域目录下。system_app 对system_app_data_file 是没有execute 权限。
system_app_data_file 是什么鬼,
在external/sepolicy/file.te 下

type system_app_data_file, file_type, data_file_type, mlstrustedobject;

data_file_type 就是data分区下文件。
说白了就是 system权限的app 无法执行data分区下文件。读写应该没有问题。应该是防止有些流氓软件在data分区下隐藏可以执行文件。
所以给systemapp加可执行权限

device/mediatek/sepolicy/basic/non_plat/system_app.te
allow system_app system_app_data_file:dir {getattr search };
allow system_app system_app_data_file:file {read getattr execute };

加完之后编译发现报错,原因是

libsepol.report_failure: neverallow on line 528 of system/sepolicy/private/app.te (or line 21726 of policy.conf) violated by allow system_app system_app_data_file:file { execute };

//system_data_file
/system/sepolicy/private/app.te

neverallow {
  bluetooth
  isolated_app
  nfc
  radio
  shared_relro
  system_app
} {
  data_file_type
  -dalvikcache_data_file
  -system_data_file # shared libs in apks
  -apk_data_file
}:file no_x_file_perms;

禁止system_app no_x_file_perms(执行) data_file_type(system_app_data_file)下的文件。
所以我修改app.te文件中的system_app去掉

neverallow {
  bluetooth
  isolated_app
  nfc
  radio
  shared_relro
} {
  data_file_type
  -dalvikcache_data_file
  -system_data_file # shared libs in apks
  -apk_data_file
}:file no_x_file_perms;

这个存在一个问题就是过不了谷歌cts测试。另外还有一种方法绕过这种过不了谷歌测试cts问题,我不想写了,修改system_app_data_file的type,这个 type就是本篇文章中,有谁知道的可以把这个方法列出来?

你可能感兴趣的:(android)