堆腐败 - Android原生代码中的SEGV_MAPERR

时间:2014-03-26 13:20:50

标签: android c encryption openssl java-native-interface

我正在尝试为流AES加密创建一个小型库,我开始基于Facebook Conceal项目(https://github.com/facebook/conceal)开展我的工作,只是更改了一些内容并改进了本机的包装以支持带填充的密码。

它正在工作,它可以解密文件而不会出现问题,但是当我处理大流时,我会得到随机堆内存损坏,经过大量时间调试后,我无法找到错误。

这是我的代码:
https://gist.github.com/frisco82/9782725

我试图找到内存分配或免费问题,但几乎没有malloc或free,而jni调用应该是安全的,openssl也是如此(我编译了自己但隐藏提供的也失败了)

CheckJni没有警告任何事情,虽然上下文处理有点开箱即用,但它似乎没有被破坏(事实上,Android密码似乎使用类似的东西)。

此外,如果有人可以将我指向Android原生AES多步骤(多个更新调用)库,我将切换到那个并忘记这一点。

错误时常变化,但通常与他的相似:

03-26 10:33:02.065: A/dalvikvm(2475): @@@ ABORTING: DALVIK: HEAP MEMORY CORRUPTION IN mspace_malloc addr=0x0
03-26 10:33:02.065: A/libc(2475): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 2494 (AsyncTask #1)
03-26 10:33:02.205: I/DEBUG(933): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
03-26 10:33:02.205: I/DEBUG(933): Build fingerprint: 'generic_x86/google_sdk_x86/generic_x86:4.4.2/KK/999428:eng/test-keys'
03-26 10:33:02.205: I/DEBUG(933): Revision: '0'
03-26 10:33:02.205: I/DEBUG(933): pid: 2475, tid: 2494, name: AsyncTask #1  >>> com.proton <<<
03-26 10:33:02.205: I/DEBUG(933): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadbaad

完整堆栈跟踪:
http://pastebin.com/f6mDuQEj

2 个答案:

答案 0 :(得分:1)

  

它正在工作,它可以解密文件没有问题,但我明白了   当我处理大流时,随机堆内存损坏。

从上面看,我看到你的程序明显覆盖了代码隐式或显式分配的内存。我试图理解你的代码,但我不清楚。但我试图从内存损坏情况看,并发​​现你的程序确实有malloc / free调用,这可能会导致内存溢出。

EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX*) malloc(sizeof(EVP_CIPHER_CTX));
EVP_CIPHER_CTX_init(ctx);

EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX*) malloc(sizeof(EVP_CIPHER_CTX));
EVP_CIPHER_CTX_init(ctx);

我尝试检查 EVP_CIPHER_CTX结构的布局,但是代码中没有。但我看到这些指针在程序中的各种上下文中被使用。现在您应该检查在哪种情况下您的缓冲区可以被覆盖,因为您使用了不同的 keyLength ,并且根据此情况,您的程序正在执行不同的功能。我想你可能想查看这些代码,看看溢出是否可能!!! ....

由于您的应用程序将在基于Android的系统上运行,我们无法运行任何动态工具(Valgrind / WinDBG / Pageheap ..)所以我猜您需要通过在重要位置放置一些日志来查看您的代码并查看您的位置被覆盖。

希望以上信息对您理解您的问题很有用。

答案 1 :(得分:1)

毕竟我能够解决这个问题,EVP_CipherUpdate(或jni ReleaseByteArrayElements)有时溢出输出缓冲区导致堆损坏,我的代码中没有任何错误,也不是调用者使用EVP_CipherUpdate调用替换memcpy并使用相同的参数按预期工作并且没有堆损坏的问题。

因此解决方案是向发送到nativeUpdate的输出缓冲区添加一些额外的长度,错误消失了。

我已经为其他人创建了该库的完整工作版本,用于: https://github.com/frisco82/conceal