linux
Pointer is set to NULL without freeing previously allocated memory
When NUMA is enabled and size > PAGE_SIZE, inet_ehash_locks_free() does not free the memory allocated for `x' but just set this pointer to NULL.
Bug fixed by commit 218ad12f42e
| Type | MemoryLeak |
| Config | "NUMA && (SMP || DEBUG_SPINLOCK || DEBUG_LOCK_ALLOC)" (2nd degree) |
| Fix-in | code |
| Location | include/net/ |
#define ENOMEM 12 /* Out of memory */
#define NULL (void*)0
extern void *malloc (unsigned long __size) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) ;
extern void free (void *__ptr) __attribute__ ((__nothrow__ , __leaf__));
#define PAGE_SIZE 12
int *x = NULL;
unsigned int size = PAGE_SIZE+1;
int inet_ehash_locks_alloc()
{
#ifdef CONFIG_NUMA
if (size > PAGE_SIZE)
x = malloc(size);
else
#endif
x = malloc(size); // (2)
if (!x)
return ENOMEM;
return 0;
}
void inet_ehash_locks_free()
{
if (x) {
#ifdef CONFIG_NUMA
if (size > PAGE_SIZE)
free(x);
else
#else
free(x);
#endif
x = NULL; // (4) ERROR
}
}
int main(void)
{
inet_ehash_locks_alloc(); // (1)
inet_ehash_locks_free(); // (3)
return 0;
}
diff --git a/simple/218ad12.c b/simple/218ad12.c
--- a/simple/218ad12.c
+++ b/simple/218ad12.c
@@ -30,9 +30,8 @@
if (size > PAGE_SIZE)
free(x);
else
-#else
- free(x);
#endif
+ free(x);
x = NULL; // (4) ERROR
}
}
#include <errno.h>
#include <stdlib.h>
#define PAGE_SIZE 12
int *x = NULL;
unsigned int size = PAGE_SIZE+1;
int main(int argc, char** argv)
{
// inet_ehash_locks_alloc();
#ifdef CONFIG_NUMA
if (size > PAGE_SIZE)
x = malloc(size);
else
#endif
x = malloc(size);
if (!x)
return ENOMEM;
// inet_ehash_locks_free();
if (x) {
#ifdef CONFIG_NUMA
if (size > PAGE_SIZE)
free(x);
else
#else
free(x);
#endif
x = NULL; // ERROR
}
return 0;
}
. include/net/inet_hashtables.h:147:inet_ehash_locks_alloc() . 169: hashinfo->ehash_locks = kmalloc(size * sizeof(rwlock_t), GFP_KERNEL); . include/net/inet_hashtables.h:180:inet_ehash_locks_free() . 128: if (hashinfo->ehash_locks) . ERROR 192: hashinfo->ehash_locks = NULL;