本机代码会导致 Android 中 Java 代码的内存损坏吗?
Can native code cause memory corruption in Java code in Android?
在Android中,当我们通过JNI调用本机代码时,它是否会破坏Dalvik VM,以及其中的Java代码运行?
例如,假设我们有这个 C 方法并通过 JNI 调用它:
JNIEXPORT void JNICALL Java_MemoryCorruptor_corruptMemory()
{
while (1) {
char *p = randomAddress();
*p = randomChar();
}
}
如果 VM 只加载 .so 文件并且本机代码是 运行 在 与 VM 相同 context/address space ,然后我假设 VM 可能会损坏。
另一方面,如果 VM 创建一个子进程来保存 .so 文件并使用某种形式的 IPC 来调用方法,那么 Java 代码就不会被本机代码破坏.
本机代码 运行 与它通过 JNI 交互的 Java 代码在同一进程中,所以是的,它非常能够破坏关键数据结构。大多数情况下,您可能会将此视为实现 VM 本身的库内的崩溃,在 return 因本机代码行为不当后不久,但理论上另一个线程可能会误操作。
就同一进程的本机代码和 VM 托管代码之间存在隔离而言,仅仅是有用和安全所需的信息 修改实现数据结构在某些 JNI 支持调用下仅在有限程度上可用 - 但如果您的本机代码这样做,它就会全部暴露给蒙住眼睛的戳戳。当然,您的代码也有可能通过尝试非法访问本身而使进程崩溃。根据 VM 实现的细节,应用程序的某些 "code" 可能位于只读内存页面中,尝试写入这些页面会导致内存保护错误。但是,数据和任何 JIT "compiled on the fly" 代码可能会位于可写页面中。恶意代码可以更改保护设置,必要时将只读文件支持的映射交换为具有相同内容的可写匿名页面。
可以在不同的进程中 运行 应用程序的 Android 组件,但是它将有自己的 VM 包装您在那里使用的任何 JNI 代码 - 类 比如 Activity 和服务基本上是 Java 级别,即使您使用普通 JNI 胶水 Java 代码在本机版本中完成工作。例如,某些 Web 浏览器应用程序可能会这样做,以便在其 javascript 解释器引擎周围放置更多隔离。
(迄今为止)也可以启动一个独立的纯本机进程并通过 IPC 与之对话,但是不鼓励这样做,因为它缺少 Android 管理的生命周期挂钩,其中有一些棘手的部分你必须自己完成。此外,这样的程序不能使用大多数 Java 定义的 Android 平台 API,或者至少不能以可移植的方式使用。从历史上看,人们主要是在被黑设备上使用 "su" root shim 以超级用户身份启动辅助进程 运行 时,或者偶尔作为移植复杂 Linux 风格的工具,无需将其重新构建为 JNI 库。
在Android中,当我们通过JNI调用本机代码时,它是否会破坏Dalvik VM,以及其中的Java代码运行?
例如,假设我们有这个 C 方法并通过 JNI 调用它:
JNIEXPORT void JNICALL Java_MemoryCorruptor_corruptMemory()
{
while (1) {
char *p = randomAddress();
*p = randomChar();
}
}
如果 VM 只加载 .so 文件并且本机代码是 运行 在 与 VM 相同 context/address space ,然后我假设 VM 可能会损坏。
另一方面,如果 VM 创建一个子进程来保存 .so 文件并使用某种形式的 IPC 来调用方法,那么 Java 代码就不会被本机代码破坏.
本机代码 运行 与它通过 JNI 交互的 Java 代码在同一进程中,所以是的,它非常能够破坏关键数据结构。大多数情况下,您可能会将此视为实现 VM 本身的库内的崩溃,在 return 因本机代码行为不当后不久,但理论上另一个线程可能会误操作。
就同一进程的本机代码和 VM 托管代码之间存在隔离而言,仅仅是有用和安全所需的信息 修改实现数据结构在某些 JNI 支持调用下仅在有限程度上可用 - 但如果您的本机代码这样做,它就会全部暴露给蒙住眼睛的戳戳。当然,您的代码也有可能通过尝试非法访问本身而使进程崩溃。根据 VM 实现的细节,应用程序的某些 "code" 可能位于只读内存页面中,尝试写入这些页面会导致内存保护错误。但是,数据和任何 JIT "compiled on the fly" 代码可能会位于可写页面中。恶意代码可以更改保护设置,必要时将只读文件支持的映射交换为具有相同内容的可写匿名页面。
可以在不同的进程中 运行 应用程序的 Android 组件,但是它将有自己的 VM 包装您在那里使用的任何 JNI 代码 - 类 比如 Activity 和服务基本上是 Java 级别,即使您使用普通 JNI 胶水 Java 代码在本机版本中完成工作。例如,某些 Web 浏览器应用程序可能会这样做,以便在其 javascript 解释器引擎周围放置更多隔离。
(迄今为止)也可以启动一个独立的纯本机进程并通过 IPC 与之对话,但是不鼓励这样做,因为它缺少 Android 管理的生命周期挂钩,其中有一些棘手的部分你必须自己完成。此外,这样的程序不能使用大多数 Java 定义的 Android 平台 API,或者至少不能以可移植的方式使用。从历史上看,人们主要是在被黑设备上使用 "su" root shim 以超级用户身份启动辅助进程 运行 时,或者偶尔作为移植复杂 Linux 风格的工具,无需将其重新构建为 JNI 库。