Function Interposition in C with an example of user defined malloc()
Function interposition is the concept of replacing calls to functions in dynamic libraries with calls to user-defined wrappers.
What are applications?
- We can count number of calls to function.
- Store caller’s information and arguments passed to function to track usage.
- Detect memory leak, we can override malloc() and keep track of allocated spaces.
- We can add our own security policies. For example, we can add a policy that fork cannot be called with more that specified recursion depth.
How to do function interposition?
The task is to write our own malloc() and make sure our own malloc() is called inplace of library malloc(). Below is a driver program to test different types of interpositions of malloc().
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
int main( void )
{
void *ptr = malloc (4);
printf ( "Hello World\n" );
return 0;
}
|
- Compile time : Replace library call with our own function when the source code is compiled.
#include <stdio.h>
#include <malloc.h>
void *mymalloc( size_t s)
{
printf ( "My malloc called" );
return NULL;
}
|
#define malloc(size) mymalloc(size)
void *mymalloc( size_t size);
|
Steps to execute above on Linux:
// Compile the file containing user defined malloc()
:~$ gcc -c mymalloc.c
// Compile hello.c with output file name as helloc.
// -I. is used to include current folder (.) for header
// files to make sure our malloc.h is becomes available.
:~$ gcc -I. -o helloc hello.c mymalloc.o
// Run the generated executable
:~$ ./helloc
My malloc called
Hello World
.
- Link time : When the relocatable object files are statically linked to form an executable object file.
#include <stdio.h>
void *__real_malloc( size_t size);
void *__wrap_malloc( size_t size)
{
printf ( "My malloc called" );
return NULL;
}
|
Steps to execute above on Linux:
// Compile the file containing user defined malloc()
:~$ gcc -c mymalloc.c
// Compile hello.c with output name as hellol
// "-Wl,--wrap=malloc" is used tell the linker to use
// malloc() to call __wrap_malloc(). And to use
// __real_malloc() to actual library malloc()
:~$ gcc -Wl,--wrap=malloc -o hellol hello.c mymalloc.o
// Run the generated executable
:~$ ./hellol
My malloc called
Hello World
.
- Load/run time : When an executable object file is loaded into memory, dynamically linked, and then executed.
The environment variable LD_PRELOAD gives the loader a list of libraries to load be loaded before a command or executable.
We make a dynamic library and make sure it is loaded before our executable for hello.c.
#define _GNU_SOURCE
#include <stdio.h>
void * malloc ( size_t s)
{
printf ( "My malloc called\n" );
return NULL;
}
|
Steps to execute above on Linux:
// Compile hello.c with output name as helloc
:~$ gcc -o hellor hello.c
// Generate a shared library myalloc.so. Refer
// https://www.geeksforgeeks.org/working-with-shared-libraries-set-2/
// for details.
:~$ gcc -shared -fPIC -o mymalloc.so mymalloc.c
// Make sure shared library is loaded and run before .
:~$ LD_PRELOAD=./mymalloc.so ./hellor
My malloc called
Hello World
.
The code for user defined malloc is kept small for better readability. Ideally, it should allocate memory by making a call to library malloc().
Source:
https://www.utdallas.edu/~zxl111930/spring2012/public/lec18-handout.pdf
Last Updated :
29 May, 2017
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...