android第三方apk找不到/system/lib64/里面的系统库
平台
RK3288 + Android 9
问题
- 官方原文:
"从 Android 7.0 开始,系统将阻止应用动态链接非公开 NDK 库,这种库可能会导致您的应用崩溃。此行为变更旨在为跨平台更新和不同设备提供统一的应用体验。即使您的代码可能不会链接私有库,但您的应用中的第三方静态库可能会这么做。因此,所有开发者都应进行相应检查,确保他们的应用不会在运行 Android 7.0 的设备上崩溃。如果您的应用使用原生代码,则只能使用公开 NDK API。" - 这样会有什么问题?
很多使用JNI的APP将无法像低版本SDK一样, 正常使用, 在使用7.1的时候, 系统会有相关的提示, 到使用9.0时, 直接崩溃报错.java.lang.UnsatisfiedLinkError: dlopen failed: library "/system/lib/libserial_port.so" needed or dlopened by "/system/lib/libnativeloader.so" is not accessible for the namespace "classloader-namespace"at java.lang.Runtime.loadLibrary0(Runtime.java:1016)at java.lang.System.loadLibrary(System.java:1669)
- 1
- 2
- 3
常见:UnsatisfiedLinkError
解决方案
方案 1修改APP端
见下文记录7.0加载so文件失败:java.lang.UnsatisfiedLinkError: dlopen failed: library “libsqlite.so” not found
方案 2 修改系统SDK
|-- 错误输出部分代码: bionic/linker/linker.cpp
static bool load_library(android_namespace_t* ns,LoadTask* task,LoadTaskList* load_tasks,int rtld_flags,const std::string& realpath,bool search_linked_namespaces) {off64_t file_offset = task->get_file_offset();const char* name = task->get_name();const android_dlextinfo* extinfo = task->get_extinfo();
if ((file_offset % PAGE_SIZE) != 0) {
DL_ERR(“file offset for the library “%s” is not page-aligned: %” PRId64, name, file_offset);
return false;
}
if (file_offset < 0) {
DL_ERR(“file offset for the library “%s” is negative: %” PRId64, name, file_offset);
return false;
}
struct stat file_stat;
if (TEMP_FAILURE_RETRY(fstat(task->get_fd(), &file_stat)) != 0) {
DL_ERR(“unable to stat file for the library “%s”: %s”, name, strerror(errno));
return false;
}
if (file_offset >= file_stat.st_size) {
DL_ERR(“file offset for the library “%s” >= file size: %” PRId64 " >= %" PRId64,
name, file_offset, file_stat.st_size);
return false;
}
// Check for symlink and other situations where
// file can have different names, unless ANDROID_DLEXT_FORCE_LOAD is set
if (extinfo nullptr || (extinfo->flags & ANDROID_DLEXT_FORCE_LOAD) 0) {
soinfo* si = nullptr;
if (find_loaded_library_by_inode(ns, file_stat, file_offset, search_linked_namespaces, &si)) {
TRACE("library “%s” is already loaded under different name/path “%s” - "
“will return existing soinfo”, name, si->get_realpath());
task->set_soinfo(si);
return true;
}
}
if ((rtld_flags & RTLD_NOLOAD) != 0) {
DL_ERR(“library “%s” wasn’t loaded and RTLD_NOLOAD prevented it”, name);
return false;
}
struct statfs fs_stat;
if (TEMP_FAILURE_RETRY(fstatfs(task->get_fd(), &fs_stat)) != 0) {
DL_ERR(“unable to fstatfs file for the library “%s”: %s”, name, strerror(errno));
return false;
}
// do not check accessibility using realpath if fd is located on tmpfs
// this enables use of memfd_create() for apps
if ((fs_stat.f_type != TMPFS_MAGIC) && (!ns->is_accessible(realpath))) {
// TODO(dimitry): workaround for http://b/26394120 - the grey-list
<span class="token comment">// TODO(dimitry) before O release: add a namespace attribute to have this enabled</span>
<span class="token comment">// only for classloader-namespaces</span>
<span class="token keyword">const</span> soinfo<span class="token operator">*</span> needed_by <span class="token operator">=</span> task<span class="token operator">-</span><span class="token operator">></span><span class="token function">is_dt_needed</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">?</span> task<span class="token operator">-</span><span class="token operator">></span><span class="token function">get_needed_by</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">is_greylisted</span><span class="token punctuation">(</span>ns<span class="token punctuation">,</span> name<span class="token punctuation">,</span> needed_by<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token comment">// print warning only if needed by non-system library</span><span class="token keyword">if</span> <span class="token punctuation">(</span>needed_by <span class="token operator">==</span> <span class="token keyword">nullptr</span> <span class="token operator">||</span> <span class="token operator">!</span><span class="token function">is_system_library</span><span class="token punctuation">(</span>needed_by<span class="token operator">-</span><span class="token operator">></span><span class="token function">get_realpath</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">const</span> soinfo<span class="token operator">*</span> needed_or_dlopened_by <span class="token operator">=</span> task<span class="token operator">-</span><span class="token operator">></span><span class="token function">get_needed_by</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> <span class="token keyword">char</span><span class="token operator">*</span> sopath <span class="token operator">=</span> needed_or_dlopened_by <span class="token operator">==</span> <span class="token keyword">nullptr</span> <span class="token operator">?</span> <span class="token string">"(unknown)"</span> <span class="token operator">:</span>needed_or_dlopened_by<span class="token operator">-</span><span class="token operator">></span><span class="token function">get_realpath</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token function">DL_WARN_documented_change</span><span class="token punctuation">(</span>__ANDROID_API_N__<span class="token punctuation">,</span><span class="token string">"private-api-enforced-for-api-level-24"</span><span class="token punctuation">,</span><span class="token string">"library \"%s\" (\"%s\") needed or dlopened by \"%s\" "</span><span class="token string">"is not accessible by namespace \"%s\""</span><span class="token punctuation">,</span>name<span class="token punctuation">,</span> realpath<span class="token punctuation">.</span><span class="token function">c_str</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> sopath<span class="token punctuation">,</span> ns<span class="token operator">-</span><span class="token operator">></span><span class="token function">get_name</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token function">add_dlwarning</span><span class="token punctuation">(</span>sopath<span class="token punctuation">,</span> <span class="token string">"unauthorized access to"</span><span class="token punctuation">,</span> name<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span><span class="token comment">// do not load libraries if they are not accessible for the specified namespace.</span><span class="token keyword">const</span> <span class="token keyword">char</span><span class="token operator">*</span> needed_or_dlopened_by <span class="token operator">=</span> task<span class="token operator">-</span><span class="token operator">></span><span class="token function">get_needed_by</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token keyword">nullptr</span> <span class="token operator">?</span><span class="token string">"(unknown)"</span> <span class="token operator">:</span>task<span class="token operator">-</span><span class="token operator">></span><span class="token function">get_needed_by</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span><span class="token function">get_realpath</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token function">DL_ERR</span><span class="token punctuation">(</span><span class="token string">"library \"%s\" needed or dlopened by \"%s\" is not accessible for the namespace \"%s\""</span><span class="token punctuation">,</span>name<span class="token punctuation">,</span> needed_or_dlopened_by<span class="token punctuation">,</span> ns<span class="token operator">-</span><span class="token operator">></span><span class="token function">get_name</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// do not print this if a library is in the list of shared libraries for linked namespaces</span><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">maybe_accessible_via_namespace_links</span><span class="token punctuation">(</span>ns<span class="token punctuation">,</span> name<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token function">PRINT</span><span class="token punctuation">(</span><span class="token string">"library \"%s\" (\"%s\") needed or dlopened by \"%s\" is not accessible for the"</span><span class="token string">" namespace: [name=\"%s\", ld_library_paths=\"%s\", default_library_paths=\"%s\","</span><span class="token string">" permitted_paths=\"%s\"]"</span><span class="token punctuation">,</span>name<span class="token punctuation">,</span> realpath<span class="token punctuation">.</span><span class="token function">c_str</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>needed_or_dlopened_by<span class="token punctuation">,</span>ns<span class="token operator">-</span><span class="token operator">></span><span class="token function">get_name</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>android<span class="token operator">::</span>base<span class="token operator">::</span><span class="token function">Join</span><span class="token punctuation">(</span>ns<span class="token operator">-</span><span class="token operator">></span><span class="token function">get_ld_library_paths</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">':'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">c_str</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>android<span class="token operator">::</span>base<span class="token operator">::</span><span class="token function">Join</span><span class="token punctuation">(</span>ns<span class="token operator">-</span><span class="token operator">></span><span class="token function">get_default_library_paths</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">':'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">c_str</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>android<span class="token operator">::</span>base<span class="token operator">::</span><span class="token function">Join</span><span class="token punctuation">(</span>ns<span class="token operator">-</span><span class="token operator">></span><span class="token function">get_permitted_paths</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token string">':'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">c_str</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
}
soinfo* si = soinfo_alloc(ns, realpath.c_str(), &file_stat, file_offset, rtld_flags);
if (si == nullptr) {
return false;
}
task->set_soinfo(si);
// Read the ELF header and some of the segments.
if (!task->read(realpath.c_str(), file_stat.st_size)) {
soinfo_free(si);
task->set_soinfo(nullptr);
return false;
}
// find and set DT_RUNPATH and dt_soname
// Note that these field values are temporary and are
// going to be overwritten on soinfo::prelink_image
// with values from PT_LOAD segments.
const ElfReader& elf_reader = task->get_elf_reader();
for (const ElfW(Dyn)* d = elf_reader.dynamic(); d->d_tag != DT_NULL; ++d) {
if (d->d_tag DT_RUNPATH) {
si->set_dt_runpath(elf_reader.get_string(d->d_un.d_val));
}
if (d->d_tag DT_SONAME) {
si->set_soname(elf_reader.get_string(d->d_un.d_val));
}
}
for_each_dt_needed(task->get_elf_reader(), [&](const char* name) {
load_tasks->push_back(LoadTask::create(name, si, ns, task->get_readers_map()));
});
return true;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
错误输出:
DL_ERR("library \"%s\" needed or dlopened by \"%s\" is not accessible for the namespace \"%s\"",name, needed_or_dlopened_by, ns->get_name());
- 1
- 2
修改的思路是, 不走报错这部分分支的代码, 切入点 is_greylisted
diff --git a/bionic/linker/linker.cpp b/bionic/linker/linker.cpp
old mode 100644
new mode 100755
index c78b9ab..0aa83bc
--- a/bionic/linker/linker.cpp
+++ b/bionic/linker/linker.cpp
@@ -200,12 +200,14 @@ static bool is_greylisted(android_namespace_t* ns, const char* name, const soinf"libui.so","libutils.so","libvorbisidec.so",
+ "libserial_port.so",nullptr};
// If you’re targeting N, you don’t get the greylist.
if (g_greylist_disabled || get_application_target_sdk_version() >= ANDROID_API_N) {
- return false;
+ //make system lib can be loaded.
+ //return false;
}
// if the library needed by a system library - implicitly assume it
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
修改点:
- 将调用的SO加入灰名单列表, 这里加了一个libserial_port.so
- 注释判断SDK和灰名单使能判断的返回, 当然, 也可以强制返回 true, 看需求办事
修改后有Warning提示, 忽略:
Warning: library "/system/lib/libserial_port.so" ("/system/lib/libserial_port.so") needed or dlopened by "/system/lib/libnativeloader.so" is not accessible by namespace "classloader-namespace" and will not work when the app moves to API level 24 or later (https://android.googlesource.com/platform/bionic/+/master/private-api-enforced-for-api-level-24) (allowing for now because this app's target API level is still 26)
- 1
已上传资源: linker
使用:
adb root
adb remount
adb push linker /system/bin/
adb reboot
- 1
- 2
- 3
- 4
随着而来的第二个问题:
java.lang.UnsatisfiedLinkError: dlopen failed: library "libc++.so" not foundat java.lang.Runtime.loadLibrary0(Runtime.java:1016)at java.lang.System.loadLibrary(System.java:1669)
- 1
- 2
- 3
|–bionic/linker/linker.cpp
@@ -2342,6 +2344,10 @@ android_namespace_t* create_namespace(const void* caller_addr,
parse_path(ld_library_path, “:”, &ld_library_paths);
parse_path(default_library_path, “:”, &default_library_paths);
+ if(strcmp(name, “classloader-namespace”) == 0){
+ parse_path("/system/lib", “:”, &default_library_paths);
+ }
parse_path(permitted_when_isolated_path, “:”, &permitted_paths);
android_namespace_t* ns = new (g_namespace_allocator.alloc()) android_namespace_t();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
解决!!
完整补丁: linker_patch.tar.gz
相关
- Android 7.0 NDK 行为变更
- 记录7.0加载so文件失败:java.lang.UnsatisfiedLinkError: dlopen failed: library “libsqlite.so” not found
android第三方apk找不到/system/lib64/里面的系统库相关推荐
- android内置第三方APP为系统应用,第三方APP内置到/system/app目录下报错java.lang.UnsatisfiedLinkError,so文件不加载
项目场景: 在无系统签名的情况下,将第三方APP内置到/system/app目录下,可以将第三方应用变为系统应用,用户无法直接卸载.不过前提是手机需要root. 问题描述 使用es文件管理工具将第三方 ...
- 【Android 12 AOSP学习】Android内置第三方apk到系统
这篇文章将介绍如何在Android系统中内置第三方apk 一.准备工作 编译好的Android源码 Android apk文件:也就是安卓应用安装包 二.步骤 (1)在源码packages/apps目 ...
- android预置第三方apk,android 内置APK成系统应用
一. 这种方法必须要自己编写Android.mk文件(关于Android.mk可以参考),在研发中,自己有源码时,可以将APK的源码包置于Android源码中(比如:alps/package/apps ...
- Android 系统预装添加第三方apk到data/app
对于第三方apk预装入系统时如果将apk装入system/app目录下,由于第三方apk带有自己的.so文件,此时会出现apk无法打开的情况. 解决方法: 1:解压apk,将里面的.so文件放入dev ...
- Android O发生crash,提示/system/bin/linker64(备忘)
错误提示: 2010-01-01 08:24:29.913 20251-20251/com.anwsdk.service W/linker: library "libsqlite.so&qu ...
- android打包apk时混淆遇到的问题
android打包apk的时候一般会选择混淆,而在eclipse中常使用的是proguard来混淆.有很多时候引用了第三方包的时候会导致打包不成功,或者打包成功不能运行的情况. 首先看看正常的prog ...
- 第三方APK如何隐藏虚拟按键
全面屏时代,android设备已经很少有键盘的存在了,为了便捷,虚拟按键应运而生,当然iphone的手势控制也有一部分厂商移植到了android系统中. 本文主要是关于底部的三个虚拟按键RECENT. ...
- Unity3D接入Android第三方SDK流程
目录 一.SDK调用Unity3D 二.Unity3D调用SDK 1.在Unity中新建一个脚本,调用MySDkPlatform中的方法 四.打包 1.方式一:SDK打成plugins给Unity(u ...
- 【Android 安全】Android 应用 APK 加固总结 ( 加固原理 | 应用加固完整的实现方案 | 源码资源 )
文章目录 一. APK 加固原理 1. Android 应用反编译 2. ProGuard 混淆 3. 多 dex 加载原理 4. 代理 Application 开发 5.Java 工具开发 6.Ap ...
- Android第三方QQ登录、获取个人信息、分享实现
昨天调试了一下午终于成功 第三方QQ登录.获取个人信息,分享 QQ官方API文档写的太乱 并且很多地方没有更新 这里总结一下 方便记录和回看 实现结果图 首先进入腾讯开放平台 下载QQ的SDK 地址 ...
最新文章
- 自动化测试报告(ReportNG)手把手教你
- Windows 技术篇-cmd强制关闭端口、解除端口占用方法,cmd查询端口相关的进程pid并杀死进程实例演示
- C语言中变量的链接属性
- boost::make_connected用法的测试程序
- 最小步长移动word表格标尺
- php为什么要使用变量,为什么在PHP或其他语言中使用动态变量(变量变量)
- scp带密码后台传输
- 安装服务器选择什么系统盘,云服务器ecs选择什么系统盘
- vue-router如何参数传递
- 背包问题九讲笔记_01背包
- 电子计算机最早的应用,电子计算机的最早应用领域是什么?
- 函数信号发生器的功能介绍
- docker the input device is not a TTY. If you are using mintty, try prefixing the command with ‘winp
- 用spark统计50年美国最常见的20个名字
- Proteus,keil5仿真运行stm32程序,流水灯详细教程
- 你未必知的拼音打字快打十招
- 常见的中间件有哪些?
- Mybatis错误 Result Maps collection already contains value for xxx
- 线上nacos命名空间误删如何找回 实践笔记
- OpenX系列标准介绍(5):OpenDRIVE和OpenSCENARIO的中文版本