Commit 214d2e53 authored by Vivek Das Mohapatra's avatar Vivek Das Mohapatra
Browse files

Replace the free/*alloc cluster inside the capsule

malloc/calloc/realloc/posix_memalign are simply replaced by
their external counterparts.

free() gets a wrapper which route the pointer to the hopefully
correct free() implementation.
parent 1ce69297
......@@ -31,3 +31,14 @@ _int_dlopen (const char *filename, int flag)
}
return capsule_shim_dlopen( cap, filename, flag );
}
// if the libc instances aren't unified (ie > 1 libc) then
// we must try to dispatch the to-be-freed pointer to the one
// that actually allocated it.
// This is far from foolproof:
static void
_wrapped_free (void *ptr)
{
if (ptr)
capsule_shim_free( cap, ptr );
}
......@@ -10,6 +10,8 @@
#include <ctype.h>
#include <sys/param.h>
#include <unistd.h>
#define CAP_ENV_PREFIX "CAPSULE_"
#define DUMP_STRV(what, css) \
......@@ -84,6 +86,12 @@ ptr_list *_capsule_list = NULL;
dlsymfunc _capsule_original_dlsym = NULL;
dlopnfunc _capsule_original_dlopen = NULL;
freefunc _capsule_original_free = NULL;
mallocfunc _capsule_original_malloc = NULL;
callocfunc _capsule_original_calloc = NULL;
rallocfunc _capsule_original_realloc = NULL;
palignfunc _capsule_original_pmalign = NULL;
static int str_equal (const void *a, const void *b)
{
if( a == b )
......@@ -132,6 +140,17 @@ get_namespace (const char *default_prefix, const char *soname)
return ns;
}
static capsule_item alloc_func[] =
{
{ "-" , (capsule_addr) NULL },
{ "-" , (capsule_addr) NULL },
{ "malloc" , (capsule_addr) &_capsule_original_malloc },
{ "calloc" , (capsule_addr) &_capsule_original_calloc },
{ "realloc" , (capsule_addr) &_capsule_original_realloc },
{ "posix_memalign", (capsule_addr) &_capsule_original_pmalign },
{ NULL }
};
static void
get_capsule_metadata (struct link_map *map, const char *only)
{
......@@ -199,6 +218,7 @@ get_capsule_metadata (struct link_map *map, const char *only)
// NOTE: the shim address here isn't used, but we give it the same
// value as the real function address so it's never accidentally
// a value the capsule code will care about:
int i = 0;
static const capsule_item no_wrapper = { NULL };
const capsule_item int_dlopen_wrapper =
{
......@@ -206,6 +226,13 @@ get_capsule_metadata (struct link_map *map, const char *only)
(capsule_addr) meta->int_dlopen,
};
const capsule_item int_free_wrapper =
{
"free",
(capsule_addr) meta->int_free,
(capsule_addr) meta->int_free,
};
cap = xcalloc( 1, sizeof(struct _capsule) );
cap->ns = get_namespace( meta->default_prefix, meta->soname );
DEBUG( DEBUG_CAPSULE,
......@@ -214,8 +241,20 @@ get_capsule_metadata (struct link_map *map, const char *only)
cap->meta = meta;
cap->seen.all = ptr_list_alloc( 32 );
cap->seen.some = ptr_list_alloc( 32 );
cap->int_dlopen_wrappers[0] = int_dlopen_wrapper;
cap->int_dlopen_wrappers[1] = no_wrapper;
cap->internal_wrappers[ 0 ] = int_dlopen_wrapper;
cap->internal_wrappers[ 1 ] = int_free_wrapper;
for( i = 2; alloc_func[ i ].name != NULL; i++ )
{
capsule_item *capi = &cap->internal_wrappers[ i ];
void **slot = (void **) alloc_func[ i ].real;
capi->name = alloc_func[ i ].name;
capi->shim = capi->real = (capsule_addr) *slot;
}
cap->internal_wrappers[ i ] = no_wrapper;
meta->handle = cap;
ptr_list_push_ptr( _capsule_list, cap );
}
......@@ -383,6 +422,13 @@ static void __attribute__ ((constructor)) _init_capsule (void)
set_debug_flags( secure_getenv("CAPSULE_DEBUG") );
// these are needed if there is > 1 libc instance:
_capsule_original_free = dlsym( RTLD_DEFAULT, "free" );
_capsule_original_malloc = dlsym( RTLD_DEFAULT, "malloc" );
_capsule_original_calloc = dlsym( RTLD_DEFAULT, "calloc" );
_capsule_original_realloc = dlsym( RTLD_DEFAULT, "realloc" );
_capsule_original_pmalign = dlsym( RTLD_DEFAULT, "posix_memalign" );
update_metadata( NULL );
_capsule_original_dlsym = dlsym( RTLD_DEFAULT, "dlsym" );
......@@ -521,7 +567,7 @@ capsule_init (const char *soname)
DUMP_STRV( exported, other->ns->combined_export );
}
dso = _capsule_load( cap, cap->int_dlopen_wrappers,
dso = _capsule_load( cap, cap->internal_wrappers,
&capsule_errno, &capsule_error );
if( !dso )
......
......@@ -10,6 +10,11 @@ typedef void * (*dlopnfunc) (const char *file, int flags);
// the capsule so that the memory allocation implementation
// is unified (at least until we can force libc to be shared):
typedef void (*freefunc) (void *ptr);
typedef void * (*mallocfunc) (size_t size);
typedef void * (*callocfunc) (size_t nmem, size_t size);
typedef void * (*rallocfunc) (void *ptr, size_t size);
typedef int (*palignfunc) (void **memptr, size_t alignment, size_t size);
typedef struct _capsule_namespace
{
Lmid_t ns;
......@@ -27,13 +32,19 @@ struct _capsule
struct { ptr_list *all; ptr_list *some; } seen;
capsule_metadata *meta;
capsule_namespace *ns;
capsule_item int_dlopen_wrappers[2];
capsule_item internal_wrappers[7];
};
extern ptr_list *_capsule_list;
extern dlsymfunc _capsule_original_dlsym;
extern dlopnfunc _capsule_original_dlopen;
extern freefunc _capsule_original_free;
extern callocfunc _capsule_original_calloc;
extern mallocfunc _capsule_original_malloc;
extern rallocfunc _capsule_original_realloc;
extern palignfunc _capsule_original_pmalign;
/*
* _capsule_load:
* @capsule: a #capsule handle as returned by capsule_init()
......
......@@ -8,6 +8,8 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <malloc.h>
static int
dso_is_exported (const char *dsopath, char **exported)
......@@ -268,3 +270,74 @@ cleanup:
free( errors );
return res;
}
////////////////////////////////////////////////////////////////////////////
// copy some vodoo out of libc.
// it is to be hoped that this is a temporary hack but, well…
#define SIZE_SZ (sizeof(size_t))
struct malloc_chunk
{
size_t prev_size; /* Size of previous chunk (if free). */
size_t size; /* Size in bytes, including overhead. */
struct malloc_chunk* fd; /* double links -- used only if free. */
struct malloc_chunk* bk;
struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
struct malloc_chunk* bk_nextsize;
};
typedef struct malloc_chunk* mchunkptr;
#define chunk2mem(p) ((void*)((char*)(p) + 2*SIZE_SZ))
#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))
/* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */
#define IS_MMAPPED 0x2
/* check for mmap()'ed chunk */
#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
////////////////////////////////////////////////////////////////////////////
void
capsule_shim_free (const capsule cap, void *ptr)
{
static ElfW(Addr) base = (ElfW(Addr)) NULL;
ElfW(Addr) top;
if( !ptr )
return;
top = (ElfW(Addr)) sbrk( 0 );
if( base == (ElfW(Addr)) NULL )
{
struct mallinfo mi = mallinfo();
base = top - (ElfW(Addr)) mi.arena;
}
// it's from the main heap, comes from the vanilla libc outside
// the capsule
if( (base < (ElfW(Addr)) ptr) && ((ElfW(Addr)) ptr < top) )
{
free( ptr );
return;
}
mchunkptr p = mem2chunk( ptr );
// mmapped pointer/chunk: can't tell whose this is but since we
// override the malloc/free cluster as early as possible we're
// kind of hoping we don't have any of these from inside the capsule
//
// we'd only have such a pointer if the libraries we dlmopen() into
// the capsule allocated large chunks of memory in their initialiser(s):
if (chunk_is_mmapped(p))
{
free( ptr );
return;
}
// probably from the pseudo heap inside the capsule?
cap->ns->free( ptr );
}
......@@ -255,3 +255,15 @@ void capsule_close (capsule cap);
**/
_CAPSULE_PUBLIC
char *capsule_get_prefix(const char *dflt, const char *soname);
/**
* capsule_shim_free:
* @cap: The capsule from which `free` was called
* @ptr: The pointer to be freed
*
* Tries to safely route an allocated pointer to the correct free()
* implementation.
*
*/
_CAPSULE_PUBLIC
void capsule_shim_free (const capsule cap, void *ptr);
......@@ -295,6 +295,7 @@ capsule_metadata capsule_meta =
.export = valid_dlsym_sources,
.items = relocs,
.int_dlopen = _int_dlopen,
.int_free = _wrapped_free,
};
static void __attribute__ ((constructor)) _capsule_init (void)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment