在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代码就不会被本机代码破坏。
答案 0 :(得分:6)
本机代码在与通过JNI交互的Java代码相同的进程中运行,所以是的,它非常能够破坏密钥数据结构。大多数情况下,您可能会在实施VM本身的库中看到这种情况,在行为不当的本机代码返回后不久,但理论上另一个线程可能会误操作。
如果同一进程的本机代码和VM托管代码之间存在隔离,那么有用地和安全地修改实现数据所需的信息在某些JNI支持调用下,结构仅在有限的程度上可用 - 但如果您的本机代码执行此操作,则它们都会被蒙上眼睛戳。当然,您的代码也可能通过尝试非法访问本身来使进程崩溃。根据VM实现的细节,一些"代码"应用程序可能在只读内存页面中,并尝试写入那些将导致内存保护错误。但是,数据和任何JIT"即时编译"代码可能是在可写页面中。并且主动恶意代码可以更改保护设置,在必要时交换具有相同内容的可写匿名页面的只读文件支持映射。
可以在不同的进程中运行Android应用程序的组件,但是它将拥有自己的VM包装您在那里使用的任何JNI代码 - 活动和服务等类基本上都是Java级别,即使您使用库存JNI胶水用于在本机版本中完成工作的Java代码。例如,某些网络浏览器应用程序可能会这样做,以便在其JavaScript解释器引擎周围增加一些隔离。
也有可能(迄今为止)启动一个独立的纯原生过程并通过IPC与之交谈,但不鼓励这样做,因为它缺乏Android管理的生命周期钩子,而且有一些棘手的问题部分内容你必须自己完成。此外,这样的程序不能使用大多数Java定义的Android平台API,或者至少不能以便携方式使用。从历史上看,人们主要是在使用" su" root shim在被黑客入侵的设备上启动以超级用户身份运行的帮助程序进程,或偶尔作为移植复杂Linux风格工具的途径,而无需将其重新构建为JNI库。