【问题标题】:Can native code cause memory corruption in Java code in Android?本机代码会导致 Android 中 Java 代码的内存损坏吗?
【发布时间】:2015-04-30 14:14:35
【问题描述】:

在 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 代码不会被本机代码破坏。

【问题讨论】:

    标签: android android-ndk dalvik memory-corruption


    【解决方案1】:

    本机代码与通过 JNI 交互的 Java 代码在同一进程中运行,所以是的,它非常有能力破坏关键数据结构。大多数情况下,您可能会将此视为实现 VM 本身的库中的崩溃,在从行为不端的本机代码返回后不久,但理论上另一个线程可能会误操作。

    就同一进程的本地代码和虚拟机托管代码之间存在隔离而言,仅仅是有用安全修改实现数据所需的信息在某些 JNI 支持调用下,结构仅在有限程度上可用 - 但如果您的本机代码这样做,它都会暴露在蒙眼戳中。当然,您的代码也有可能通过尝试非法访问本身来使进程崩溃。根据 VM 实现的细节,应用程序的某些“代码”很可能位于只读内存页面中,尝试写入这些页面会导致内存保护错误。但是,数据和任何“即时编译”的 JIT 代码都可能位于可写页面中。并且主动恶意代码可以更改保护设置,如有必要,将只读文件支持的映射交换为具有相同内容的可写匿名页面。

    可以在不同的进程中运行 Android 应用程序的组件,但它会有自己的 VM 包装您在那里使用的任何 JNI 代码 - 像 Activity 和 Service 这样的类基本上是 Java 级别的,即使您使用股票 JNI 胶水在本机版本中完成工作的 Java 代码。例如,一些网络浏览器应用程序可能会这样做,以便在其 javascript 解释器引擎周围增加一点隔离。

    (迄今为止)还可以启动一个独立的纯原生进程并通过 IPC 与其通信,但不鼓励这样做,因为它缺少用于 Android 管理的生命周期挂钩,并且存在一些棘手的问题其中的一部分你必须自己完成。此外,这样的程序不能使用大多数 Java 定义的 Android 平台 API,或者至少不能以可移植的方式使用。从历史上看,人们主要是在被黑设备上使用“su”root shim 来启动以超级用户身份运行的辅助进程,或者偶尔作为移植复杂 Linux 风格工具而不将其重新架构为JNI 库。

    【讨论】:

    • FWIW,DEX 字节码被映射为只读,尽管映射可以更改(特别是用于设置/清除调试断点)。 Dalvik VM 包含一个用于将内部 VM 数据结构存储在只读页面上的功能(如果您好奇,请挖掘“LinearAlloc”),这有时有助于发现损坏,但启用它需要重新编译 VM。最常见的损坏形式是破坏托管堆。 ICS 中 JNI 全局/本地引用从指针切换到索引具有有用的副作用,即通过使指针远离堆栈来停止其中的一些。
    猜你喜欢
    • 2018-06-03
    • 2014-05-04
    • 2020-01-16
    • 2017-05-10
    • 2011-11-26
    • 1970-01-01
    • 2012-01-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多