JNI Memory Leak - java-native-interface

I have written a Hello, world program with JNI. Java calls c program with a string, c program prints that string. Here is the java program
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class JNISample {
public native void leakMem(String str);
static {
System.loadLibrary("sample");
}
public static void main(String args[]) throws IOException {
JNISample sample = new JNISample();
sample.leakMem("Hello world!");
}
}
Corresponding c program
#include <stdlib.h>
#include <jni.h>
#include "JNISample.h"
JNIEXPORT void JNICALL Java_JNISample_leakMem(JNIEnv *env, jobject jobj, jstring givenStr) {
const char *javaStr = env->GetStringUTFChars (givenStr, 0);
printf("Received String: %s\n", javaStr);
env->ReleaseStringUTFChars (givenStr, javaStr);
}
When I executed this program with valgrind, with following command
valgrind --trace-children=yes --show-reachable=yes --leak-check=full java -Djava.library.path=. JNISample 10 2> log
I have observed definitely lost bytes in the log, here is the valgrind's memory summery
LEAK SUMMARY:
==5385== definitely lost: 5,246 bytes in 36 blocks
==5385== indirectly lost: 5,072 bytes in 23 blocks
==5385== possibly lost: 154,317 bytes in 131 blocks
==5385== still reachable: 6,164,933 bytes in 831 blocks
==5385== suppressed: 0 bytes in 0 blocks
Why there are definitely lost bytes with such a small program without any memory allocations? Is there any problem with JNI usage or JNI leaks memory? I have used JDK6 on Ubuntu 11.10 64 bit machine.

I cannot answer your question specifically. However, my experience with JNI is that it does a lot of things internally that can confuse valgrind. If the point at which the memory is being lost is inside JNI there wouldn't be a lot you could do about it, anyway. However, it's still a pain in the proverbial, since the number of different suppression needed to give you a clean run is likely to be enormous (hundreds).
Good luck.

Related

sigsegv occured when posix_memalign immediately after free in some devices and compile option in AIX

I was assigned to a pointer and it was free immediately, but sigsegv occurs depending on some devices and xlc options.
xlC_r -o cc.o c.c -lhm has sigsegv occurred, but xlC_r -o cc.o c.c works.
( lhm option is linking libhm.a libhu.a. )
( malloc and free works. Only posix_memalign and free sigsegv occurred. )
Source code:
#include<stdlib.h>
#include<stdio.h>
int main()
{
void * sPtr = NULL;
size_t sAlign = 8388608;
size_t sSize = 8388648;
int sRet = 0;
sRet = posix_memalign(&sPtr, sAlign, sSize);
printf( "after malloc : %p return : %d\n", sPtr, sRet );
free(sPtr);
printf( "after free\n" );
return 0;
}
It works:
aix7.1 tl3 IBM XL C/C++ for AIX, V12.1 (5765-J02, 5725-C72) Version: 12.01.0000.0000
aix6.1 tl9 IBM XL C/C++ for AIX, V10.1 Version: 10.01.0000.0008
Result is:
after malloc : 22000000 return : 0
after free
but
aix6.1 tl3 IBM XL C/C++ for AIX, V10.1 Version: 10.01.0000.0008
aix5.3 tl9 IBM XL C/C++ for AIX, V10.1 Version: 10.01.0000.0000
aix5.3 tl1 C for AIX version 6.0.0.0
Version: 10.01.0000.0000
Result is
after malloc : 22000000 return : 0
Segmentation fault (core dumped)
% dbx cc.o core
Type 'help' for help.
[using memory image in core]
reading symbolic information ...
Segmentation fault in _ufree at 0xd3c0fcc4 ($t1)
0xd3c0fcc4 (_ufree+0x44) 80be0000 lwz r5,0x0(r30)
(dbx) where
_ufree(??) at 0xd3c0fcc4
cbase.free(??) at 0xd2b7c048
main(), line 16 in "c.c"
I have not solved this problem although I've been trying for over a week. I searched for a bug report from AIX, but I couldn't find one.
It is not possible to delete both posix_memalign and lhm option.
Do you know a workaround or how to solve it?
libhm and libhmd are debug memory management libraries. They detect errors by keeping extra information after malloc and then checking before free that the block was not previously freed and that it was allocated via malloc. These libraries don't handle posix_memalign and don't keep extra information for it. So when you call free after posix_memalign, they think you're trying to free memory that was not properly allocated. That said, I don't recall that causing a segmentation fault, but a false positive error message. (I'm more used to libhmd than libhm.)
These libraries are no longer maintained. See for example the XLF compiler manual page for them. The official recommendation is to use AIX's native debug malloc tool instead.

Memory issue with threads (tinythread, C++)

I debug a strange memory issue: When a multithreaded algorithm runs in a loop its memory consumption increases with every iteration although the heap checker of of GooglePerformanceTools says there is no leak. Finally I have made a separate minimal program that reproduces the bug. It seems that the threads are the problem:
#include <stdio.h>
#include <iostream>
#include <vector>
#include "tinythread.h"
using namespace std;
int a(0);
void doNothingAtAll(void*)
{
++a;
}
void startAndJoin100()
{
vector<tthread::thread*> vThreads;
for(int i=0;i<100;++i)
{
vThreads.push_back(new tthread::thread(doNothingAtAll,NULL));
}
while(!vThreads.empty())
{
tthread::thread* pThread(vThreads.back());
pThread->join();
delete pThread;
vThreads.pop_back();
}
}
int main()
{
for(int i=0;i<10;++i)
{
cout<<"calling startAndJoin100()"<<endl;
startAndJoin100();
cout<<"all threads joined"<<endl;
cin.get();
}
return 0;
}
main() calls 10 times startAndJoin100(). It waits for a key stroke after each iteration so that one can take the memory consumption which is (under Ubuntu 17.10, 64-bit):
VIRT
2.1 GB
4 GB
5.9 GB
7.8 GB
9.6 GB
11.5 GB
13.4 GB
15.3 GB
17.2 GB
19.0 GB
Note: C++11 can't be used and the program must compile on Linux and Windows, thus tinythread is used. Minimal test code with Makefile:
geom.at/_downloads/testTinyThread.zip
I answer my own question, this may be useful for somebody later:
Conclusion:
1) I'd really like to keep TinyThread because C++11 is unavailable (VS2008 and old Linux Systems must be supported) and no additional library shall be linked (TinyThread consists only of an *.h and *.cpp file while Boost and other solutions I know require linking a DLL).
2) Valgrind and the heap checker of the GooglePerformanceTools do not report memory leaks and I have looked into the code - it seems to be correct although the virtual memory consumption increases drastically in the minimal example posted above. It seems that the system does not re-use the previously assigned memory pages and I have not found an explanation for this behavior. Thus I do not blame TinyThread++ but it works when pthreads are used directly instead.
3) The workaround: There is a C alternative called TinyCThread: https://tinycthread.github.io/ that works also for C++ and it does not cause the problems observed with TinyThread++.

C++ gsoap memory leaks in my computer

I use gsoap client in C++ program, but it has memory leaks when calling the defined functions many times. The main codes are:
for(int i=0;i<1000000;i++){
struct soap* s = soap_new();
char* run;
soap_call_ns__run(s,url,NULL,"123",&run);
soap_destroy(s);
soap_end(s);
soap_done(s);
soap_free(s);
}
when running, the memory will rise up;
I run this on Win7 system; I try it on ubuntu 16.10 and it seems there's no memory leaks.
Can anyone try it and help me ?

Casting a character string as a function

I'm trying to learn to execute shellcode from within a program, but I can't get even the most basic code to run. The following code is just supposed to exit the terminal when it's run:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/mman.h>
char exitcode[] = "\xb0\x01\x31\xdb\xcd\x80";
int main() {
int (*func)();
func = (int (*)())exitcode;
(int)(*func)();
return 0;
}
But all I get is a segfault. GDB says it's happening when the program accesses the memory location of exitcode [at (int)(*func)(); ], but I'm not sure why this is causing a problem. I'm running a 64-bit Linux Mint OS. Any help is greatly appreciated.
Modern operating systems use memory protection. Pages of memory have access rights just like files: readable, writable, executable. Your data segment of your program is typically in a non-executable page, trying to execute it results in a segfault.
If you want to execute dynamically written binary code from your program on linux, you first have to map a page using mmap() that you can write to, then place your code there, and then change it to read only, executable using mprotect(). THEN you can jump there.
You could for example read this article for details.
EDIT: If this is about security breaches, note that the stack typically is non-executable nowadays, too ... so all these old "hacking tutorials" won't work any more. If you're interested in newer techniques, read about return oriented programming.
The code must be marked as executable code. One way to do it is to copy this binary machine code into executable buffer.
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
char exitcode[] = "\xb0\x01\x31\xdb\xcd\x80";
int main(int argc, char **argv)
{
void *buf;
/* copy code to executable buffer */
buf = mmap (0,sizeof(exitcode),PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANON,-1,0);
memcpy (buf, exitcode, sizeof(code));
/* run code */
int i = ((int (*) (void))buf)();
printf("OK. returned: %d", i);
return 0;
}
Your shellcode is:
mov $0x1,%al
xor %ebx,%ebx
int $0x80
There are two problems:
Syscall 0x1 is a sys_write on 64-bit (but on 32-bit it's sys_exit)
You should assign to %rax, not %al. %rax will contain leftovers in high bits.
I had this problem and searched a lot to solve it.
You must use this code to compile your C code (To disable stack protection and make it executable):
gcc -fno-stack-protector -z execstack -o hello hello.c
Tested in Kali 32/64 bit. No segfault anymore.
Good luck

Segmentation Fault in Constructor

This happens with EVERY class I try to make in C++. Migrating from java, I find problems mainly in making classes. I run valgrind and it's in the constructor, it appears to be.
==30214== Memcheck, a memory error detector
==30214== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==30214== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==30214== Command: ./CoC
==30214==
==30214==
==30214== Process terminating with default action of signal 11 (SIGSEGV)
==30214== Bad permissions for mapped region at address 0x404B4F
==30214== at 0x4C2B9EC: strcat (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30214== by 0x404220: Model::Model(std::string) (in /home/kronus/Apollo/CoC)
==30214== by 0x402617: main (in /home/kronus/Apollo/CoC)
As you can see I'm trying to call the constructor of this model class into the main method. Here's the code for the constructor
Model::Model(std::string filename)
{
m_TotalFaces = 0;
m_model = lib3ds_file_load(filename.c_str());
// If loading the model failed, we throw an exception
if(!m_model)
{
throw strcat("Unable to load ", filename.c_str());
}
}
When it's called it closes with a segmentation fault. Important: I have declared the class inside the header file. This is when I get the error. I put the class inside the source file and it runs fine. What am I doing wrong?
strcat attempts to write the string pointed to by the second argument at the end of the string pointed to by the first argument. Since the first argument is a string literal (which should be considered read only), you get a nasty segfault.
I suggest learning C++ as though it's an entirely different language to Java, because otherwise you may think that similar features function the same. That's dangerous. A monkey can learn Java by mashing it's face on the keyboard. C++ has undefined behaviour which may appear to function correctly on your machine, but launch nuclear missiles on another.
You are appending to a constant string that is wrong:
strcat("Unable to load ", filename.c_str());
^ you can't append to constant
Read this: c++ exception : throwing std::string
You may want to avoid using strings as exception classes because they themselves can throw an exception during use.
second: What type should I catch if I throw a string literal?