在预置包含react native 的Android app 预置到mtk 6739的系统中,此app 具体 platform 签名。此app启动会加载一些 facebook的so库
发现此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.<clinit>(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就是本篇文章中,有谁知道的可以把这个方法列出来?