Error on freeing memory used by a function in C - c

I have a main that do:
unsigned char *f_hmac = calculate_hmac(output_file_path, mac_key, keyLength);
fwrite(f_hmac, 1, 64, fpout);
free(f_hmac);
and a function (which prototype is:unsigned char *calculate_hmac(const char *filename, const unsigned char *key, size_t keylen)) that do:
unsigned char *hmac = malloc(64);
hmac = gcry_md_read(hd, GCRY_MD_SHA512);
return hmac;
My problem is that when the main do free(f_hmac) i got:
*** glibc detected *** ./polcrypt: free(): invalid pointer: 0x00000000023a8ad8 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7f0fd662db96]
./polcrypt[0x40220f]
./polcrypt[0x401851]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7f0fd65d076d]
./polcrypt[0x4015e9]
and i don't understand why.
OS: GNU/Linux Ubuntu 12.10
GCC 4.7.2/Clang 3.2
cflags -Wall -Wextra -D_FORTIFY_SOURCE=2 -O2 -Wformat -Wformat-security -fstack-protector-all -fmudflap -fPIE

From the docs:
The returned message digest is allocated within the message context and therefore valid until the conext [sic] is released.
So, you need to make sure to release the message context, but you don't need to allocate or free hmac.
If you will release the message context before returning from calculate_hmac, you need to copy the hmac out:
unsigned char *hmac = malloc(64);
unsigned char *m_hmac = gcry_md_read(gd, GCRY_MD_SHA512);
memcpy(hmac, m_hmac, 64);
return hmac;

You're allocating hmac, then overwriting your newly allocated pointer with the result of gcry_md_read:
unsigned char *hmac = malloc(64);
hmac = gcry_md_read(hd, GCRY_MD_SHA512);
The documentation of gcry_md_read states that:
gcry_md_read returns the message digest after finalizing the calculation. This function may be used as often as required but it will alwas return the same value for one handle. The returned message digest is allocated within the message context and therefore valid until the conext is released.
So unless you want to keep the pointer around after the context is released, you don't need to malloc or free anything:
unsigned char *hmac = gcry_md_read(hd, GCRY_MD_SHA512);

Related

Problem with manually allocating memory address for a pointer

I am trying to work with flash memory on MPC5748G - a microcontroller from NXP running FreeRTOS 10.0.1, and I get some behaviour that I can't understand.
I am allocating memory manually, and the assignment seems not to work. However, I can reach the value at the address when using 'printf' - but only from the same function.
(I'm using the copy of a pointer, to make sure that some sore of compiler optimisation doesn't take place)
void vFlashTask(void* pvParameters){
vTaskDelay(1000);
FLASH_DRV_Init();
uint32_t* val_ptr;
uint32_t* val_ptr_cpy;
val_ptr = (uint32_t *)0xFB8000;
val_ptr_cpy = val_ptr;
*val_ptr = 444;
DBGPRINTF("Task| value at xFB8000:%d", *val_ptr_cpy);
getValTest();
vTaskDelay(1500);
vTaskDelete(NULL);
}
void getValTest(){
uint32_t* val_ptr;
val_ptr =(uint32_t *)0xfb8000;
DBGPRINTF("getValTest| value at xFB8000:%d", *val_ptr);
}
Gives back (in UART Terminal):
[../include/flash.c:26]: Task| value at xFB8000:444
[../include/flash.c:37]: getValTest| value at xFB8000:-1
I am attaching also the screenshot from the debugger, which clearly shows that however memory at the xFB8000 is uninitialized (it has the value of 0xffffffff), but still, the printf function manages to print the correct value(?).
My DBGPRINTF macro:
#define DBGPRINTF(f, ...) dbgPrintf("[%s:%d]: " f "\n", __FILE__, __LINE__, __VA_ARGS__)
void dbgPrintf(const char *format, ...){
va_list args;
va_start(args, format);
int len = vsnprintf((char*) uart_buffer, UART_BUFFER_SIZE - 1, format, args);
UART_SendDataBlocking(&uart_pal1_instance, (const char *)uart_buffer, len, UART_TIMEOUT);
va_end(args);
}
I would really appreciate any help or suggestions.
My compiler flags:
\S32DS_Power_v2.1\eclipse\../S32DS/software/S32_SDK_S32PA_RTM_3.0.3/rtos/FreeRTOS_PA/Source/portable/GCC/PowerPC" -I"C:\NXP\S32DS_Power_v2.1\eclipse\../S32DS/software/S32_SDK_S32PA_RTM_3.0.3/middleware/tcpip/tcpip_stack/ports/OS" -I"C:\NXP\S32DS_Power_v2.1\eclipse\../S32DS/software/S32_SDK_S32PA_RTM_3.0.3/middleware/tcpip/tcpip_stack/ports/platform/generic/gcc/setting" -I"C:\NXP\S32DS_Power_v2.1\eclipse\../S32DS/software/S32_SDK_S32PA_RTM_3.0.3/middleware/tcpip/wolfssl/wolfssl" -I"C:\NXP\S32DS_Power_v2.1\eclipse\../S32DS/software/S32_SDK_S32PA_RTM_3.0.3/middleware/tcpip/wolfssl" -I"C:\NXP\S32DS_Power_v2.1\eclipse\../S32DS/software/S32_SDK_S32PA_RTM_3.0.3/rtos/FreeRTOS_PA/Source" -I"C:\NXP\S32DS_Power_v2.1\eclipse\../S32DS/software/S32_SDK_S32PA_RTM_3.0.3/platform/pal/inc" -I"C:\NXP\S32DS_Power_v2.1\eclipse\../S32DS/software/S32_SDK_S32PA_RTM_3.0.3/platform/drivers/src/flash_c55" -O1 -g3 -Wall -c -fmessage-length=0 -msdata=eabi -mlra -funsigned-bitfields -ffunction-sections -fdata-sections -fno-common -Wno-address -mcpu=e200z4 -specs=nosys.specs -mbig -mvle -mregnames -mhard-float --sysroot="C:\NXP\S32DS_Power_v2.1\eclipse\../S32DS/build_tools/powerpc-eabivle-4_9/powerpc-eabivle/newlib"
The problem was writing to FLASH memory - it hasn't been correctly initialized.
The proper way to write to flash on MPC5748g using the SDK 3.0.3 is following:
save flash controller cache
initialise flash
check and protect UT block
unblock an address space
erase a block in this space
check if the space block is blank
program the block
verify if the block is programmed correctly
check sum of the programmed data
restore flash controller cache
The strange behaviour of printf and pointer was due to compiler optimization. After changing the compiler flags to -O0 (no optimization), the error was consistent.
The same consistent error can be achieved when marking the pointers as 'volatile'.

Segmentation Fault, and How to use Unions for types

Im constructing A Vertex Library in C, and for some reason i get a Segmentation Fault. Im going to first show the code and ask question:
Vertex.h:
#ifndef _VERTEX_AM_H_LB
#define _VERTEX_AM_H_LB 1
#pragma once
#include<stdint.h>
/**
* Vertex Library C
*
* GCC C99 <Vertex.h>
*
* #author Amanuel Bogale
* #copyright 2016 Amanuel Bogale
* #license http://www.opensource.org/licenses/mit-license.html MIT License
*
*/
//#union for storing
//data types supported
//for vertex
typedef union
{
char ch; //1 byte
unsigned char uch;//1 byte
signed char sch;// 1 byte
int in;//2 or 4bytes
unsigned int uin;//2 or 4bytes
long ln;// 4byte
unsigned long uln; //4byte
long long lnln; //8byte
short sh;// 2byte
unsigned short ush; //2bytes
float fl;//4byte
double db; //8byte
long double ldb; //10byte
}type;
/*
* #struct for defining
* vertex. Initalize First
*/
struct vertex_am
{
size_t current_size;
type type;
long long size_contents;
void **contents; //Array Of Void Pointers
//Add to the end of array
void (*add)(struct vertex_am *self,void*val);
};
typedef struct vertex_am vertex_am;
vertex_am* init_vertex(size_t size, vertex_am* vertex);
void end_vertex(vertex_am* vertex);
long long get_elements_num(vertex_am vert);
void add_end(vertex_am vert, void* val);
void* get_val(vertex_am vert,long long index);
#endif
Vertex.c:
#include<stdlib.h>
#include<stdio.h>
#include "../includes/Vertex.h"
/**
* Vertex Library C
*
* GCC C99 <Vertex.c>
*
* #author Amanuel Bogale
* #copyright 2016 Amanuel Bogale
* #license http://www.opensource.org/licenses/mit-license.html MIT License
*
*/
vertex_am* init_vertex(size_t size, vertex_am* vertex)
{
vertex = malloc(size);
vertex->current_size = size;
vertex->size_contents = 0;
return vertex;
}
long long get_elements_num(vertex_am vert)
{
return(vert.size_contents);
}
void add_end(vertex_am vert, void* val)
{
vert.contents[vert.size_contents] = val;
vert.size_contents++;
}
void* get_val(vertex_am vert,long long index)
{
return (vert.contents[index]);
}
void end_vertex(vertex_am* vertex)
{
free(vertex);
}
main.c:
#include<stdlib.h>
#include<stdio.h>
#include<stdint.h>
#include "includes/Vertex.h"
int main()
{
printf("In");
vertex_am *vert = NULL;
vert = init_vertex(sizeof(*vert), vert);
add_end(*vert,(void *)34);
// printf ("%d", *((int*)get_val(*vert, 0) ));
end_vertex(vert);
return 0;
}
Makefile:
C = gcc
TARGETS = main
SUB_TARGETS = sources/Vertex.c
CFLAGS = -Wall -g -std=c99 -pthread -Werror -o exec -g -Q -O0
all: clean $(TARGETS)
$(TARGETS):
$(C) $(CFLAGS) $#.c $(SUB_TARGETS) -o $#
clean:
rm -f $(TARGETS)
Ok i have couple questions.
I have a segmentation Fault above. And i cant locate where it is. Help Please
Any Segmentation Fault Debugger for gcc and linux enviorment
How would i go about using unions to manupliate types. By that i mean like this vector_am vec . How would i go so i get what the user wants as a type using union. Or is the void* already a better idea?
Help would be appreciated. Thanks for reading.
I have a segmentation Fault above. And i cant locate where it is
execute the code with gdb
gdb ./exec
then type 'run' and gdb will do his magic and tell you exactly where the segmentation fault is and you will be able to understand why.
From reading your code it looks like you are accessing vert.contents pointer without allocate memory for it...
vert.contents[vert.size_contents]
vert.contents is a double pointer that hasn't been allocated/initialized
Any Segmentation Fault Debugger for gcc and linux enviorment
gdb is, by far, the best I ever known..
You can find the segmentation fault location by doing the following:
Compile with gcc -g to add debugging information
Run your program with gdb ./yourprogram
In the GDB prompt, press r to run the program
When it crashes, write bt to get the backtrace.
For the crash itself, it looks like you don't allocate memory for vertex_am's contents member so accessing it will lead to a crash.

C binary reaches 1.2G memory limit

I am dealing with a C program that reads in from a file with many
lines of about 60 characters each and allocates the string in memory
by requesting more memory as it reads the file in. After each malloc
request, it checks with a function OOM() if the request for more
memory was successful.
I have tested the program with an increasingly larger input file, and
OOM() reports an "Out of memory" more or less when the memory
usage reaches 1.2G when looking at the top command while the program
is running. This is on a 64bit linux machine with plenty more memory
available. Output from file /my/binary/program:
ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
My question is: why is it reaching the 1.2G limit? I remember my
sysadmin used to say that certain binaries would only be able to use
up to 1.2G, which coincidentally is what I am seeing here.
When I run qsub the same execution on a node of the same 64bit Linux
SGE grid reserving 50GB of memory, it reports that also goes "Out of
memory" and the following SGE log memory footprint:
Max vmem = 2.313G
Any ideas why the program is reaching this memory limit? Are there any
compilation flags I should be aware of which could cause/solve this?
Find below the relevant flags in the current Makefile:
CC = gcc
CFLAGS = -Wall -O3 -funroll-loops -DNDEBUG -fomit-frame-pointer -std=gnu99 -msse2 -Wno-unused-function -Wno-unused-result
CFLAGSSFMT = -msse2 -DHAVE_SSE2 -O9 -finline-functions -fomit-frame-pointer \
-DNDEBUG -fno-strict-aliasing --param max-inline-insns-single=1800 -std=c99
LD = ld
LDFLAGS = -lm -lc -lblas -llapack
INCFLAGS =
DEFINES = -D_GNU_SOURCE -DUSE_BLAS
Some of the relevant code belo:w
in mystring.h:
#ifndef _MYSTRING_H_
#define _MYSTRING_H_
struct __mystring_struct {
char * string;
int len, maxlen;
};
typedef struct __mystring_struct * Mystring;
#define Mystring_size sizeof(struct __mystring_struct)
Mystring new_mystring (const int len);
void free_mystring (Mystring string);
void append_char_to_mystring ( const char c, Mystring string);
char * cstring_of_mystring(const Mystring string);
Mystring mystring_of_cstring (const char * str);
#endif
in mystring.c:
#include <string.h>
#include "mystring.h"
#define OOM(A) { if (NULL==(A) ){fputs("Out of memory\n",stderr); exit(EXIT_FAILURE);} }
static void check_is_mystring (const Mystring string);
static void double_length_of_mystring ( Mystring string);
Later on:
static void double_length_of_mystring (Mystring string){
char * new_mem;
check_is_mystring(string);
new_mem = malloc(string->maxlen * 2 * sizeof(char)); OOM(new_mem);
memcpy (new_mem,string->string,string->len * sizeof(char));
free(string->string);
string->string = new_mem;
string->maxlen *= 2;
check_is_mystring (string);
}
It seems you use int to keep size of your string. In GCC (and in most other PC platform compilers) this type is 32b even on 64b platform. You should use size_t instead.
The mechanism of the failed allocation is as follows:
1.2 GB ~= 1288490189
2 * 1.2 GB ~= 2576980378, which is over 2^31 (2147483648), after overflow you get -1717986918 in 2nd complement arithmetics
When calling malloc, -1717986918 is sign extended to a 64 b, and then casted to unsigned 64b, which gives you 2^64 - 1717986918, which is only marginally less than 2^64, and definitely more than the memory you have in the system.

Buffer overflow example working on Windows, but not on Linux

In the book I am reading, Software Exorcism, has this example code for a buffer overflow:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 4
void victim(char *str)
{
char buffer[BUFFER_SIZE];
strcpy(buffer,str);
return;
}
void redirected()
{
printf("\tYou've been redirected!\n");
exit(0);
return;
}
void main()
{
char buffer[]=
{
'1','2','3','4',
'5','6','7','8',
'\x0','\x0','\x0','\x0','\x0'
};
void *fptr;
unsigned long *lptr;
printf("buffer = %s\n", buffer);
fptr = redirected;
lptr = (unsigned long*)(&buffer[8]);
*lptr = (unsigned long)fptr;
printf("main()\n");
victim(buffer);
printf("main()\n");
return;
}
I can get this to work in Windows with Visual Studio 2010 by specifying
Basic Runtime Checks -> Uninitialized variables
Buffer Security Check -> No
With those compile options, I get this behavior when running:
buffer = 12345678
main()
You've been redirected!
My question is about the code not working on Linux. Is there any clear reason why it is so?
Some info on what I've tried:
I've tried to run this with 32-bit Ubuntu 12.04 (downloaded from here), with these options:
[09/01/2014 11:46] root#ubuntu:/home/seed# sysctl -w kernel.randomize_va_space=0
kernel.randomize_va_space = 0
Getting:
[09/01/2014 12:03] seed#ubuntu:~$ gcc -fno-stack-protector -z execstack -o overflow overflow.c
[09/01/2014 12:03] seed#ubuntu:~$ ./overflow
buffer = 12345678
main()
main()
Segmentation fault (core dumped)
And with 64-bit CentOS 6.0, with these options:
[root]# sysctl -w kernel.randomize_va_space=0
kernel.randomize_va_space = 0
[root]# sysctl -w kernel.exec-shield=0
kernel.exec-shield = 0
Getting:
[root]# gcc -fno-stack-protector -z execstack -o overflow overflow.c
[root]# ./overflow
buffer = 12345678
main()
main()
[root]#
Is there something fundamentally different in Linux environment, which would cause the example not working, or am I missing something simple here?
Note: I've been through the related questions such as this one and this one, but haven't been able to find anything that would help on this. I don't think this is a duplicate of previous questions even though there are a lot of them.
Your example overflows the stack, a small and predictable memory layout, in an attempt to modify the return address of the function void victim(), which would then point to void redirected() instead of coming back to main().
It works with Visual. But GCC is a different compiler, and can use some different stack allocation rule, making the exploit fail. C doesn't enforce a strict "stack memory layout", so compilers can make different choices.
A good way to view this hypothesis is to test your code using MinGW (aka GCC for Windows), proving the behavior difference is not related strictly to the OS.
#define BUFFER_SIZE 4
void victim(char *str)
{
char buffer[BUFFER_SIZE];
strcpy(buffer,str);
return;
}
There is another potential problem here if optimizations are enabled. buffer is 12 bytes, and its called as victim(buffer). Then, within victim, you try to copy 12 bytes into a 4 byte buffer with strcpy.
FORTIFY_SOURCES should cause the program to seg fault on the call to strcpy. If the compiler can deduce the destination buffer size (which it should in this case), then the compiler will replace strcpy with a "safer" version that includes the destination buffer size. If the bytes to copy exceeds the destination buffer size, then the "safer" strcpy will call abort().
To turn off FORTIFY_SOURCES, then compile with -U_FORTIFY_SOURCE or -D_FORTIFY_SOURCE=0.

Does gcc compiler have any option to recognize memory corruption at compile time?

#include <stdio.h>
#include <string.h>
int main()
{
char arrDst[5] = {0};
char arrSrc[10] = "123456";
memcpy( arrDst, arrSrc, sizeof( arrSrc ) );
return 0;
}
Here in this program it is clear that there is a memory corruption.
Is there any option in gcc compiler by which I can recognize this problem at compile time?
Note: I used valgrind --leak-check=full, but it doesn't help.
$ gcc -Wall -O1 t.c
In file included from /usr/include/string.h:642:0,
from t.c:3:
In function ‘memcpy’,
inlined from ‘main’ at t.c:13:9:
/usr/include/bits/string3.h:52:3: warning: call to __builtin___memcpy_chk
will always overflow destination buffer [enabled by default]
GCC can recognize some of these. That generally requires turning on optimizations (at least -01) and warnings (-Wall, add -Wextra too).
It may not scale to the large program you are really interested in, but you can find this error with Frama-C:
$ frama-c -cpp-command "gcc -C -E -I`frama-c -print-share-path`/libc/ -nostdinc" mem.c `frama-c -print-share-path`/libc/fc_runtime.c -val
...
[value] computing for function memcpy <- main.
Called from mem.c:13.
.../libc/string.h:54:[value] Function memcpy: precondition got status invalid.
This message means that you are calling memcpy() with arguments that do not satisfy its contract. In this case the pre-condition that fails is the first in the list, about the validity of the destination for writing:
/*# requires \valid(((char*)dest)+(0..n - 1));
# requires \valid_read(((char*)src)+(0..n - 1));
# requires \separated(((char *)dest)+(0..n-1),((char *)src)+(0..n-1));
# assigns ((char*)dest)[0..n - 1] \from ((char*)src)[0..n-1];
# assigns \result \from dest;
# ensures memcmp((char*)dest,(char*)src,n) == 0;
# ensures \result == dest;
#*/
extern void *memcpy(void *restrict dest,
const void *restrict src, size_t n);

Resources