在Android中,当我们通过JNI调用本机代码时,它是否会破坏Dalvik VM以及在其中运行的Java代码?
例如,假设我们有这个C方法,我们通过JNI调用它:
JNIEXPORT void JNICALL Java_MemoryCorruptor_corruptMemory()
{
while (1) {
char *p = randomAddress();
*p = randomChar();
}
}
如果VM只加载.so文件并且本机代码在与VM相同的上下文/地址空间中运行,那么我认为VM可能已损坏.
另一方面,如果VM创建一个子进程来保存.so文件并使用某种形式的IPC来调用方法,那么Java代码就不会被本机代码破坏.
解决方法:
本机代码在与通过JNI交互的Java代码相同的进程中运行,所以是的,它非常能够破坏密钥数据结构.大多数情况下,您可能会在实施VM本身的库中看到这种情况,在从行为不当的本机代码返回后不久,但理论上另一个线程可能会误操作.
如果同一进程的本机代码和VM托管代码之间存在隔离,那么只有在某些JNI支持调用下,有效且安全地修改实现数据结构所需的信息才能在有限的程度上可用 – 但它是所有暴露于蒙住眼睛的戳,如果你的本地代码那样做.当然,您的代码也可能通过尝试非法访问本身来使进程崩溃.根据VM实现的细节,应用程序的某些“代码”可能位于只读内存页面中,尝试写入这些代码会导致内存保护错误.但是,数据和任何JIT“即时编译”代码可能都在可写页面中.并且主动恶意代码可以更改保护设置,在必要时交换具有相同内容的可写匿名页面的只读文件支持映射.
可以在不同的进程中运行Android应用程序的组件,但是它将拥有自己的VM包装您在那里使用的任何JNI代码 – 活动和服务等类基本上都是Java级别,即使您使用库存JNI粘合Java代码在本机版本中完成工作.例如,一些网络浏览器应用可能会这样做,以便在他们的javascript解释器引擎周围增加一些隔离.
它(迄今为止)也可能启动一个独立的纯原生过程并通过IPC与它交谈,但不鼓励这样做,因为它缺乏Android管理的生命周期钩子,并且它有一些棘手的部分你必须完成自己.此外,这样的程序不能使用大多数Java定义的Android平台API,或者至少不能以便携方式使用.从历史上看,人们主要是在黑客设备上使用“su”根填充程序来启动以超级用户身份运行的辅助进程,或偶尔作为移植复杂Linux风格工具的途径而不将其重新设计为JNI图书馆.