Skip to content

Commit

Permalink
F_MALLOC: add extra safety checks at runtime
Browse files Browse the repository at this point in the history
The F_MALLOC allocator now properly reports any free() or realloc() operations
which are performed on bogus memory regions, making OpenSIPS immediately abort.

These checks may be skipped by defining F_MALLOC_OPTIMIZATIONS at compile time.
  • Loading branch information
liviuchircu authored and razvancrainea committed Jan 12, 2015
1 parent 74890a9 commit 604c781
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 22 deletions.
1 change: 1 addition & 0 deletions Makefile.conf.template
Expand Up @@ -65,6 +65,7 @@ DEFS+= -DSTATISTICS #Enables the statistics manager
DEFS+= -DHAVE_RESOLV_RES #Support for changing some of the resolver parameters
#DEFS+= -DHP_MALLOC #High performance allocator with fine-grained locking
DEFS+= -DF_MALLOC #An even faster allocator. Not recommended for debugging
#DEFS+= -DF_MALLOC_OPTIMIZATIONS #Remove all internal checks in F_MALLOC
DEFS+= -DUSE_TCP #Compiles in TCP support
#DEFS+= -DUSE_TLS #Compiles in TLS support
#DEFS+= -DUSE_SCTP #Compiles in SCTP support
Expand Down
2 changes: 1 addition & 1 deletion error.h
Expand Up @@ -61,7 +61,7 @@
#define E_BAD_SERVER -500 /*!< error in server */

#define report_programming_bug(format, args...) \
LM_CRIT("\n!!! " format " !!!\nIt seems you have hit a programming bug.\n" \
LM_CRIT("\n>>> " format"\nIt seems you have hit a programming bug.\n" \
"Please help us make OpenSIPS better by reporting it at " \
"https://github.com/OpenSIPS/opensips/issues\n\n", ##args);
#define LM_BUG report_programming_bug
Expand Down
45 changes: 45 additions & 0 deletions mem/common.h
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2014 OpenSIPS Solutions
*
* This file is part of opensips, a free SIP server.
*
* opensips is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
*
* opensips is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* History:
* --------
*/

#ifndef mem_common_h
#define mem_common_h

# ifdef VQ_MALLOC
# include "vq_malloc.h"
extern struct vqm_block* mem_block;
extern struct vqm_block* shm_block;
# elif defined F_MALLOC
# include "f_malloc.h"
extern struct fm_block* mem_block;
extern struct fm_block* shm_block;
# elif defined HP_MALLOC
# include "hp_malloc.h"
extern struct hp_block* mem_block;
extern struct hp_block* shm_block;
# else
# include "q_malloc.h"
extern struct qm_block* mem_block;
extern struct qm_block* shm_block;
# endif

#endif
55 changes: 39 additions & 16 deletions mem/mem.h
Expand Up @@ -37,6 +37,7 @@

#include "../config.h"
#include "../dprint.h"
#include "../stdlib.h"

/* fix debug defines, DBG_F_MALLOC <=> DBG_QM_MALLOC */
#ifdef F_MALLOC
Expand All @@ -50,22 +51,9 @@
#endif

#ifdef PKG_MALLOC
# ifdef VQ_MALLOC
# include "vq_malloc.h"
extern struct vqm_block* mem_block;
# elif defined F_MALLOC
# include "f_malloc.h"
extern struct fm_block* mem_block;
# elif defined HP_MALLOC
# include "hp_malloc.h"
extern struct hp_block* mem_block;
# else
# include "q_malloc.h"
extern struct qm_block* mem_block;
# endif

extern char *mem_pool;
#include "common.h"

extern char *mem_pool;

#ifdef STATISTICS
#define PKG_TOTAL_SIZE_IDX 0
Expand Down Expand Up @@ -114,11 +102,46 @@ void set_pkg_stats(pkg_status_holder*);
# ifdef VQ_MALLOC
# define pkg_malloc(s) vqm_malloc(mem_block, (s))
# define pkg_free(p) vqm_free(mem_block, (p))

# elif defined F_MALLOC
# include "../error.h"
# define pkg_malloc(s) fm_malloc(mem_block, (s))
# ifdef F_MALLOC_OPTIMIZATIONS
# define pkg_realloc(p, s) fm_realloc(mem_block, (p), (s))
# define pkg_free(p) fm_free(mem_block, (p))
# define pkg_free(p) fm_free(mem_block, (p))
# else
# define pkg_free(p) \
do { \
if (shm_block && \
((void *)p >= (void *)shm_block->first_frag && \
(void *)p <= (void *)shm_block->last_frag)) { \
LM_BUG("pkg_free() on shm ptr %p - aborting!\n", p); \
abort(); \
} else if (p && ((void *)p < (void *)mem_block->first_frag || \
(void *)p > (void *)mem_block->last_frag)) { \
LM_BUG("pkg_free() on non-pkg ptr %p - aborting!\n", p); \
abort(); \
} \
fm_free(mem_block, (p)); \
} while (0)

# define pkg_realloc(p, s) \
({ \
if (shm_block && \
((void *)p >= (void *)shm_block->first_frag && \
(void *)p <= (void *)shm_block->last_frag)) { \
LM_BUG("pkg_realloc(%lu) on shm ptr %p - aborting!\n", \
(unsigned long)s, p); \
abort(); \
} else if (p && ((void *)p < (void *)mem_block->first_frag || \
(void *)p > (void *)mem_block->last_frag)) { \
LM_BUG("pkg_realloc(%lu) on non-pkg ptr %p - abort!\n", \
(unsigned long)s, p); \
abort(); \
} \
fm_realloc(mem_block, (p), (s)); \
})
# endif
# define pkg_info(i) fm_info(mem_block,i)
# elif defined HP_MALLOC
# define pkg_malloc(s) hp_pkg_malloc(mem_block, (s))
Expand Down
30 changes: 25 additions & 5 deletions mem/shm_mem.h
Expand Up @@ -31,10 +31,12 @@
#ifdef SHM_MEM

#include "../statistics.h"
#include "../error.h"

#ifndef shm_mem_h
#define shm_mem_h

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
Expand Down Expand Up @@ -65,18 +67,17 @@

#include "../dprint.h"
#include "../lock_ops.h" /* we don't include locking.h on purpose */
#include "common.h"

#ifdef VQ_MALLOC
# include "vq_malloc.h"
extern struct vqm_block* shm_block;
# define MY_MALLOC vqm_malloc
# define MY_FREE vqm_free
# define MY_STATUS vqm_status
# define shm_malloc_init vqm_malloc_init
# warn "no proper vq_realloc implementation, try another memory allocator"
#elif defined F_MALLOC
# include "f_malloc.h"
extern struct fm_block* shm_block;
# define MY_MALLOC fm_malloc
# define MY_FREE fm_free
# define MY_REALLOC fm_realloc
Expand All @@ -96,7 +97,6 @@
# define MY_REALLOC_UNSAFE MY_REALLOC
#elif defined HP_MALLOC
# include "hp_malloc.h"
extern struct hp_block* shm_block;
# define MY_MALLOC hp_shm_malloc
# define MY_MALLOC_UNSAFE hp_shm_malloc_unsafe
# define MY_FREE hp_shm_free
Expand All @@ -118,7 +118,6 @@
# define update_mem_pattern_file hp_update_mem_pattern_file
#else
# include "q_malloc.h"
extern struct qm_block* shm_block;
# define MY_MALLOC qm_malloc
# define MY_FREE qm_free
# define MY_REALLOC qm_realloc
Expand Down Expand Up @@ -315,7 +314,6 @@ void* _shm_resize(void* ptr, unsigned int size, const char* f, const char* fn,

#else /*DBQ_QM_MALLOC*/


inline static void* shm_malloc_unsafe(unsigned int size)
{
void *p;
Expand Down Expand Up @@ -351,6 +349,17 @@ inline static void* shm_realloc(void *ptr, unsigned int size)

#ifndef HP_MALLOC
shm_lock();
#if (defined F_MALLOC) && !(defined F_MALLOC_OPTIMIZATIONS)
if (ptr >= (void *)mem_block->first_frag &&
ptr <= (void *)mem_block->last_frag) {
LM_BUG("shm_realloc(%u) on pkg ptr %p - aborting!\n", size, ptr);
abort();
} else if (ptr && (ptr < (void *)shm_block->first_frag ||
ptr > (void *)shm_block->last_frag)) {
LM_BUG("shm_realloc(%u) on non-shm ptr %p - aborting!\n", size, ptr);
abort();
}
#endif
#endif

p = MY_REALLOC(shm_block, ptr, size);
Expand Down Expand Up @@ -386,6 +395,17 @@ inline static void shm_free(void *_p)
{
#ifndef HP_MALLOC
shm_lock();
#if defined(F_MALLOC) && !defined(F_MALLOC_OPTIMIZATIONS)
if (_p >= (void *)mem_block->first_frag &&
_p <= (void *)mem_block->last_frag) {
LM_BUG("shm_free() on pkg ptr %p - aborting!\n", _p);
abort();
} else if (_p && (_p < (void *)shm_block->first_frag ||
_p > (void *)shm_block->last_frag)) {
LM_BUG("shm_free() on non-shm ptr %p - aborting!\n", _p);
abort();
}
#endif
#endif

#ifdef HP_MALLOC
Expand Down

0 comments on commit 604c781

Please sign in to comment.