Android 10 系统库不可读的坑点
最近做项目的时候遇到一个神奇的崩溃。
这个崩溃都集中发生在 Android 10
的机器上。
崩溃堆栈类似下面:
|
|
通过 Bugly 上报的数据发现,这个 SEGV_ACCERR
的崩溃(无访问权限)发生在读取 libc.so
的代码段(.text
)内存的时候。
观察其他信息发现,libc.so
的代码段权限只剩下 --xp
。
怪不得我们一访问就崩溃,是因为代码段没有可读权限了!
同样的问题也发生在其他系统库上。
当时的解决方案是,通过读取 /proc/self/maps
避开系统库无可读权限的用户。
直到我不小心看到了这个文档……
只执行内存违规(仅限 Android 10)
仅对于 Android 10 中的 arm64,二进制文件和库的可执行部分会映射到只执行(不可读取)内存,作为防范代码重用攻击的一种安全强化技术。此缓解方法与其他缓解方法产生了不良互动,后已被移除。
将代码设为不可读会导致故意或意外读入已标记为只执行的内存段抛出 SIGSEGV,并且代码为 SEGV_ACCERR。这可能是因为错误、漏洞、混合了代码的数据(例如文字池)或故意进行的内存自省导致的。
编译器会假设代码和数据不是混合在一起的,但是手写程序集会导致出现问题。在许多情况下,只需将常量移动到 .data 部分,即可解决这些问题。如果可执行代码段绝对有必要进行代码内省,应首先调用 mprotect(2) 以将该代码标记为可读,然后在操作完成后重新将该代码标记为不可读。
寻思这不是Android系统你在搞事情啊!
Android 官方提供的解决方案是访问之前先 mprotect
一下需要读的内存,给他们加上可读权限。
提供一个伪代码:
|
|
亲测该方案是有效的。
不过为了保守,我们用完了记得把权限设置回去只可执行,以避免一些未知的意外崩溃。
除非注明,麦麦小家文章均为原创,转载请以链接形式标明本文地址。
版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
本文地址:https://blog.micblo.com/2022/04/26/Android-10-系统库不可读的坑点/