--- src/Makefile.am 2007/03/19 22:15:22 1.1 +++ src/Makefile.am 2007/03/19 22:28:33 @@ -24,6 +24,7 @@ libsandbox_la_SOURCES = \ libsandbox.c \ canonicalize.c \ sandbox_utils.c \ + mmalloc.c \ $(LOCAL_INCLUDES) sandbox_CFLAGS = -DOUTSIDE_LIBSANDBOX --- src/mmalloc.c 2007/10/06 23:20:26 1.1 +++ src/mmalloc.c 2007/10/06 23:44:54 @@ -0,0 +1,147 @@ +/* Minimal mmap-based malloc/free implementation to be used by libsandbox + * internal routines, since we can't trust the current process to have a + * malloc/free implementation that is sane and available at all times. + */ + +#include /* malloc()/free() prototypes */ +#include /* mem*(), strdup() prototype */ + +#include /* mmap() */ +#include +#include + +#include "sandbox.h" + +static int checked_env = 0; +static int env_sandbox_local_malloc = 0; + +#define check_dlsym(_name) \ +{ \ + int old_errno = errno; \ + if (!true_ ## _name) \ + true_ ## _name = get_dlsym(#_name, NULL); \ + errno = old_errno; \ +} + +#define SB_MALLOC_TO_MMAP(ptr) ((void*)(((size_t*)ptr) - 1)) +#define SB_MMAP_TO_MALLOC(ptr) ((void*)(((size_t*)ptr) + 1)) +#define SB_MALLOC_TO_SIZE(ptr) (*((size_t*)SB_MALLOC_TO_MMAP(ptr))) + +static void *(*true_malloc)(size_t size) = NULL; +void *malloc(size_t size) +{ + if (!checked_env) { + env_sandbox_local_malloc = (getenv(ENV_SANDBOX_LOCAL_MALLOC) != NULL); + checked_env = 1; + } + if (!env_sandbox_local_malloc) { + check_dlsym(malloc); + return true_malloc(size); + } else { + size_t *ret; + size += sizeof(size_t); + ret = mmap(0, size, PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + if (ret == MAP_FAILED) + return NULL; + *ret = size; + return SB_MMAP_TO_MALLOC(ret); + } +} + +static void (*true_free)(void *ptr) = NULL; +void free(void *ptr) +{ + if (!checked_env) { + env_sandbox_local_malloc = (getenv(ENV_SANDBOX_LOCAL_MALLOC) != NULL); + checked_env = 1; + } + if (!env_sandbox_local_malloc) { + check_dlsym(free); + true_free(ptr); + } else { + if (ptr == NULL) + return; + munmap(SB_MALLOC_TO_MMAP(ptr), SB_MALLOC_TO_SIZE(ptr)); + } +} + +static void *(*true_calloc)(size_t nmemb, size_t size) = NULL; +void *calloc(size_t nmemb, size_t size) +{ + if (!checked_env) { + env_sandbox_local_malloc = (getenv(ENV_SANDBOX_LOCAL_MALLOC) != NULL); + checked_env = 1; + } + if (!env_sandbox_local_malloc) { + check_dlsym(calloc); + return true_calloc(nmemb, size); + } else { + void *ret; + size_t malloc_size = nmemb * size; + ret = malloc(malloc_size); /* dont care about overflow */ + if (ret == NULL) + return NULL; + memset(ret, 0x00, malloc_size); + return ret; + } +} + +static void *(*true_realloc)(void *ptr, size_t size) = NULL; +void *realloc(void *ptr, size_t size) +{ + if (!checked_env) { + env_sandbox_local_malloc = (getenv(ENV_SANDBOX_LOCAL_MALLOC) != NULL); + checked_env = 1; + } + if (!env_sandbox_local_malloc) { + check_dlsym(realloc); + return true_realloc(ptr, size); + } else { + void *ret; + size_t old_malloc_size; + + if (ptr == NULL) + return malloc(size); + if (size == 0) { + free(ptr); + return ptr; + } + + old_malloc_size = SB_MALLOC_TO_SIZE(ptr); + ret = malloc(size); + if (ret == NULL) + return NULL; + memcpy(ret, ptr, (size < old_malloc_size ? size + : old_malloc_size)); + free(ptr); + return ret; + } +} + +static char *(*true_strdup)(const char *s) = NULL; +#ifdef strdup +#undef strdup +#endif +char *strdup(const char *s) +{ + if (!checked_env) { + env_sandbox_local_malloc = (getenv(ENV_SANDBOX_LOCAL_MALLOC) != NULL); + checked_env = 1; + } + if (!env_sandbox_local_malloc) { + check_dlsym(strdup); + return true_strdup(s); + } else { + size_t len; + char *ret; + + if (s == NULL) + return NULL; + len = strlen(s); + ret = malloc(len + 1); + if (ret == NULL) + return NULL; + return memcpy(ret, s, len + 1); + } +} --- src/sandbox.h 2007/10/06 23:19:48 1.1 +++ src/sandbox.h 2007/10/06 23:38:25 @@ -52,6 +52,8 @@ #define ENV_SANDBOX_ACTIVE "SANDBOX_ACTIVE" #define SANDBOX_ACTIVE "armedandready" +#define ENV_SANDBOX_LOCAL_MALLOC "SANDBOX_LOCAL_MALLOC" + #define DEFAULT_BEEP_COUNT 3 #define SB_BUF_LEN 2048 @@ -110,6 +110,7 @@ char *gbasename (const char *path); char *erealpath(const char *, char *); #ifndef OUTSIDE_LIBSANDBOX char *egetcwd(char *, size_t); +void *get_dlsym(const char *, const char *); #endif #endif /* __SANDBOX_H__ */ --- src/libsandbox.c 2007/10/06 23:19:48 1.1 +++ src/libsandbox.c 2007/10/06 23:30:29 @@ -121,7 +121,6 @@ static int sb_path_size_warning = 0; void __attribute__ ((constructor)) libsb_init(void); void __attribute__ ((destructor)) libsb_fini(void); -static void *get_dlsym(const char *, const char *); static int canonicalize(const char *, char *); static char *resolve_path(const char *, int); static int check_prefixes(char **, int, const char *); @@ -185,7 +184,7 @@ void __attribute__ ((constructor)) libsb errno = old_errno; } -static void *get_dlsym(const char *symname, const char *symver) +void *get_dlsym(const char *symname, const char *symver) { void *symaddr = NULL;