Memory leak & invalid memory deallocation detection in the Linux kernel for modules using exclusively Operating System Abstraction Layer
The header file
OSAL APIs need to be analyzed and a list of those that allocate or free
memory need to be identified. The list needs to be further decomposed
in the type of memory that they allocate/deallocate (memory buffer,
thread, mutex etc).
Let us assume for the sake of an example the following APIs are the
memory manipulating ones. This is would be just a subset of the whole
OSAL memory allocating/deallocating API, since except for memory
allocations and frees, also occurs for other OS components such as
threads, semaphores etc.:
void *osal_mem_alloc(int size)
void osal_mem_free(void *memBuffer)
int osal_mutex_init(*Osal_Mutex)
int osal_mutex_destroy(*Osal_Mutex)
After analysis a header file needs to be created. All the above
identified and classified APIs should be redefined in this header file
as macros.
Those macros, with the help of an inline function, as described
before, will call the original function to allocate/deallocate memory
and provide any functionality it was required to offer (for example
allocate the buffer itself), and then log this to using the kernel
function printk().
In order to get the minimum performance impact, the system should be
configured so printk() does not print on the screen, only logs and does
not ouput in STDOUT or STDERR). For example assuming a function:
void *osal_mem_alloc(int size)
This would correspond to the following macro:
#define osal_mem_alloc(memsize)
__osal_mem_alloc(memsize,__FILE__,__LINE__)
And there would be a definition of the inline function
__osal_memAlloc() like this:
static inline void * __osal_mem_alloc(
UINT32 size,
char * filename,
int linenb)
{
void * addr = (void*) osal_mem_alloc(size);
DPRINT_MEMLEAK("MEM_DETECT_ALLOC:%p:%d:%d:%s:%d:%d\n",addr,size,OSAL_MEM_GUARD_A
LLOC_TYPE_MEMORY, filename, linenb ,current->pid);
return addr;
}
For the sake of portability please note that the following macro
needs to be included:
#define DPRINT_MEMLEAK printk
This is done in order to cater for another operating system where
printk() might not exist or not be a suitable logging solution. In the
case of Linux using printk() is safe for logging as it can be called
from any context and anytime. (For more details how printk() works
the reader can refer to [5]).
Now let us assume the following snippet of code in an imaginary
snippet:
/* Declarations of the mutex and array of buffers */
Osal_Mutex myMutex;
Osal_Mem_Buffer *myBuffer[10];
/* Initialize the mutex i.e. allocate space for it */
if (osal_mutex_init(myMutex) !=
OSAL_MUTEX_INITED_OK)
{
return ERR_MUTEX_INIT;
}
/* Lock the mutex */
osal_lock_mutex(myMutex);
/* LOOP 1: Allocate memory for the 5 first buffers in the
array */
for (int i=0 ; i<5; i++)
{
myBuffer[i] = (Osal_Mem_Buffer)
osal_mem_alloc(1024);
}
/* Allocations complete, so unlock the mutex
*/
osal_unlock_mutex(myMutex);
.
.
.
/* Lock again the mutex */
osal_lock_mutex(myMutex);
/* LOOP 2: Deallocate the 5 first buffers */
for (int i=0 ; i<5; i++)
{
osal_mem_free(myBuffer[i]);
}
/* Unlock the mutex */
osal_unlock_mutex(myMutex);
/* Destroy (free) the mutex */
osal_destroy_mutex(myMutex);
If the above code is compiled with the OsalMemLeak.h header file,
the following example logs will be generated when the binary runs:
MEM_ALLOCATION:e2000000:4:2:/home/myuser/allocations.c:4:8423
MEM_ALLOCATION:e2abfe00:1024:3:/home/myuser/allocations.c:13:8423
MEM_ALLOCATION:e2ac0200:1024:3:/home/myuser/allocations.c:13:8423
MEM_ALLOCATION:e2ac0600:1024:3:/home/myuser/allocations.c:13:8423
MEM_ALLOCATION:e2ac0a00:1024:3:/home/myuser/allocations.c:13:8423
MEM_ALLOCATION:e2ac0e00:1024:3:/home/myuser/allocations.c:13:8423
MEM_DEALLOCATION:e2abfe00::3:/home/myuser/allocations.c:28:8423
MEM_DEALLOCATION:e2ac0200::3:/home/myuser/allocations.c:28:8423
MEM_DEALLOCATION:e2ac0600::3:/home/myuser/allocations.c:28:8423
MEM_DEALLOCATION:e2ac0a00::3:/home/myuser/allocations.c:28:8423
MEM_DEALLOCATION:e2ac0e00::3:/home/myuser/allocations.c:28:8423
MEM_DEALLOCATION:e2000000::2/home/myuser/allocations.c:31:8423