Let sodium_malloc() and friends work on systems without protected memory.

On these systems, they become simple aliases for malloc() and friends.

Canaries could be added, but adding too much bloat for these rare systems
is probably not worth it, and malloc debuggers are better tools to use.
This commit is contained in:
Frank Denis 2014-12-29 23:09:49 +01:00
parent 17932c782e
commit 26f87e266e

View File

@ -172,6 +172,29 @@ sodium_hex2bin(unsigned char * const bin, const size_t bin_maxlen,
return ret; return ret;
} }
int
_sodium_alloc_init(void)
{
#ifdef HAVE_ALIGNED_MALLOC
# if defined(_SC_PAGESIZE)
long page_size_ = sysconf(_SC_PAGESIZE);
if (page_size_ > 0L) {
page_size = (size_t) page_size_;
}
# elif defined(_WIN32)
SYSTEM_INFO si;
GetSystemInfo(&si);
page_size = (size_t) si.dwPageSize;
# endif
if (page_size < CANARY_SIZE || page_size < sizeof(size_t)) {
abort(); /* LCOV_EXCL_LINE */
}
#endif
randombytes_buf(canary, sizeof canary);
return 0;
}
int int
sodium_mlock(void * const addr, const size_t len) sodium_mlock(void * const addr, const size_t len)
{ {
@ -205,50 +228,14 @@ sodium_munlock(void * const addr, const size_t len)
#endif #endif
} }
int
_sodium_alloc_init(void)
{
#if defined(_SC_PAGESIZE)
long page_size_ = sysconf(_SC_PAGESIZE);
if (page_size_ > 0L) {
page_size = (size_t) page_size_;
}
#elif defined(_WIN32)
SYSTEM_INFO si;
GetSystemInfo(&si);
page_size = (size_t) si.dwPageSize;
#else
page_size = CANARY_SIZE;
if (page_size < sizeof(size_t)) {
page_size = sizeof(size_t);
}
#endif
if (page_size < CANARY_SIZE || page_size < sizeof(size_t)) {
abort(); /* LCOV_EXCL_LINE */
}
randombytes_buf(canary, sizeof canary);
return 0;
}
static inline size_t
_page_round(const size_t size)
{
const size_t page_mask = page_size - 1U;
return (size + page_mask) & ~page_mask;
}
static int static int
_mprotect_noaccess(void *ptr, size_t size) _mprotect_noaccess(void *ptr, size_t size)
{ {
#if defined(HAVE_MPROTECT) && defined(HAVE_PAGE_PROTECTION) #ifdef HAVE_MPROTECT
return mprotect(ptr, size, PROT_NONE); return mprotect(ptr, size, PROT_NONE);
#elif defined(_WIN32) #elif defined(_WIN32)
{ DWORD old;
DWORD old; return -(VirtualProtect(ptr, size, PAGE_NOACCESS, &old) == 0);
return -(VirtualProtect(ptr, size, PAGE_NOACCESS, &old) == 0);
}
#else #else
errno = ENOSYS; errno = ENOSYS;
return -1; return -1;
@ -258,13 +245,11 @@ _mprotect_noaccess(void *ptr, size_t size)
static int static int
_mprotect_readonly(void *ptr, size_t size) _mprotect_readonly(void *ptr, size_t size)
{ {
#if defined(HAVE_MPROTECT) && defined(HAVE_PAGE_PROTECTION) #ifdef HAVE_MPROTECT
return mprotect(ptr, size, PROT_READ); return mprotect(ptr, size, PROT_READ);
#elif defined(_WIN32) #elif defined(_WIN32)
{ DWORD old;
DWORD old; return -(VirtualProtect(ptr, size, PAGE_READONLY, &old) == 0);
return -(VirtualProtect(ptr, size, PAGE_READONLY, &old) == 0);
}
#else #else
errno = ENOSYS; errno = ENOSYS;
return -1; return -1;
@ -274,66 +259,72 @@ _mprotect_readonly(void *ptr, size_t size)
static int static int
_mprotect_readwrite(void *ptr, size_t size) _mprotect_readwrite(void *ptr, size_t size)
{ {
#if defined(HAVE_MPROTECT) && defined(HAVE_PAGE_PROTECTION) #ifdef HAVE_MPROTECT
return mprotect(ptr, size, PROT_READ | PROT_WRITE); return mprotect(ptr, size, PROT_READ | PROT_WRITE);
#elif defined(_WIN32) #elif defined(_WIN32)
{ DWORD old;
DWORD old; return -(VirtualProtect(ptr, size, PAGE_READWRITE, &old) == 0);
return -(VirtualProtect(ptr, size, PAGE_READWRITE, &old) == 0);
}
#else #else
errno = ENOSYS; errno = ENOSYS;
return -1; return -1;
#endif #endif
} }
#ifdef HAVE_ALIGNED_MALLOC
static void static void
_out_of_bounds(void) _out_of_bounds(void)
{ {
#ifdef SIGSEGV # ifdef SIGSEGV
raise(SIGSEGV); raise(SIGSEGV);
#elif defined(SIGKILL) # elif defined(SIGKILL)
raise(SIGKILL); raise(SIGKILL);
#endif # endif
abort(); abort();
} /* LCOV_EXCL_LINE */ } /* LCOV_EXCL_LINE */
static inline size_t
_page_round(const size_t size)
{
const size_t page_mask = page_size - 1U;
return (size + page_mask) & ~page_mask;
}
static __attribute__((malloc)) unsigned char * static __attribute__((malloc)) unsigned char *
_alloc_aligned(const size_t size) _alloc_aligned(const size_t size)
{ {
void *ptr; void *ptr;
#if defined(MAP_ANON) && defined(HAVE_MMAP) # if defined(MAP_ANON) && defined(HAVE_MMAP)
if ((ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, if ((ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE | MAP_NOCORE, -1, 0)) == MAP_FAILED) { MAP_ANON | MAP_PRIVATE | MAP_NOCORE, -1, 0)) == MAP_FAILED) {
ptr = NULL; /* LCOV_EXCL_LINE */ ptr = NULL; /* LCOV_EXCL_LINE */
} /* LCOV_EXCL_LINE */ } /* LCOV_EXCL_LINE */
#elif defined(HAVE_POSIX_MEMALIGN) # elif defined(HAVE_POSIX_MEMALIGN)
if (posix_memalign(&ptr, page_size, size) != 0) { if (posix_memalign(&ptr, page_size, size) != 0) {
ptr = NULL; /* LCOV_EXCL_LINE */ ptr = NULL; /* LCOV_EXCL_LINE */
} /* LCOV_EXCL_LINE */ } /* LCOV_EXCL_LINE */
#elif defined(_WIN32) # elif defined(_WIN32)
ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
#elif !defined(HAVE_ALIGNED_MALLOC) # else
# error Unsupported configuration # error Bug
#else # endif
# error Bug
#endif
return (unsigned char *) ptr; return (unsigned char *) ptr;
} }
static void static void
_free_aligned(unsigned char * const ptr, const size_t size) _free_aligned(unsigned char * const ptr, const size_t size)
{ {
#if defined(MAP_ANON) && defined(HAVE_MMAP) # if defined(MAP_ANON) && defined(HAVE_MMAP)
(void) munmap(ptr, size); (void) munmap(ptr, size);
#elif defined(HAVE_POSIX_MEMALIGN) # elif defined(HAVE_POSIX_MEMALIGN)
free(ptr); free(ptr);
#elif defined(_WIN32) # elif defined(_WIN32)
VirtualFree(ptr, 0U, MEM_RELEASE); VirtualFree(ptr, 0U, MEM_RELEASE);
#else # else
free(ptr); # error Bug
#endif # endif
} }
static unsigned char * static unsigned char *
@ -352,6 +343,15 @@ _unprotected_ptr_from_user_ptr(const void *ptr)
return (unsigned char *) unprotected_ptr_u; return (unsigned char *) unprotected_ptr_u;
} }
#endif /* HAVE_ALIGNED_MALLOC */
#ifndef HAVE_ALIGNED_MALLOC
static __attribute__((malloc)) void *
_sodium_malloc(const size_t size)
{
return malloc(size);
}
#else
static __attribute__((malloc)) void * static __attribute__((malloc)) void *
_sodium_malloc(const size_t size) _sodium_malloc(const size_t size)
{ {
@ -378,9 +378,9 @@ _sodium_malloc(const size_t size)
} }
unprotected_ptr = base_ptr + page_size * 2U; unprotected_ptr = base_ptr + page_size * 2U;
_mprotect_noaccess(base_ptr + page_size, page_size); _mprotect_noaccess(base_ptr + page_size, page_size);
#ifndef HAVE_PAGE_PROTECTION # ifndef HAVE_PAGE_PROTECTION
memcpy(unprotected_ptr + unprotected_size, canary, sizeof canary); memcpy(unprotected_ptr + unprotected_size, canary, sizeof canary);
#endif # endif
_mprotect_noaccess(unprotected_ptr + unprotected_size, page_size); _mprotect_noaccess(unprotected_ptr + unprotected_size, page_size);
sodium_mlock(unprotected_ptr, unprotected_size); sodium_mlock(unprotected_ptr, unprotected_size);
canary_ptr = unprotected_ptr + _page_round(size_with_canary) - canary_ptr = unprotected_ptr + _page_round(size_with_canary) -
@ -393,6 +393,7 @@ _sodium_malloc(const size_t size)
return user_ptr; return user_ptr;
} }
#endif /* !HAVE_ALIGNED_MALLOC */
__attribute__((malloc)) void * __attribute__((malloc)) void *
sodium_malloc(const size_t size) sodium_malloc(const size_t size)
@ -421,6 +422,13 @@ sodium_allocarray(size_t count, size_t size)
return sodium_malloc(total_size); return sodium_malloc(total_size);
} }
#ifndef HAVE_ALIGNED_MALLOC
void
sodium_free(void *ptr)
{
free(ptr);
}
#else
void void
sodium_free(void *ptr) sodium_free(void *ptr)
{ {
@ -442,16 +450,27 @@ sodium_free(void *ptr)
if (sodium_memcmp(canary_ptr, canary, sizeof canary) != 0) { if (sodium_memcmp(canary_ptr, canary, sizeof canary) != 0) {
_out_of_bounds(); _out_of_bounds();
} }
#ifndef HAVE_PAGE_PROTECTION # ifndef HAVE_PAGE_PROTECTION
if (sodium_memcmp(unprotected_ptr + unprotected_size, if (sodium_memcmp(unprotected_ptr + unprotected_size,
canary, sizeof canary) != 0) { canary, sizeof canary) != 0) {
_out_of_bounds(); _out_of_bounds();
} }
#endif # endif
sodium_munlock(unprotected_ptr, unprotected_size); sodium_munlock(unprotected_ptr, unprotected_size);
_free_aligned(base_ptr, total_size); _free_aligned(base_ptr, total_size);
} }
#endif /* HAVE_ALIGNED_MALLOC */
#ifndef HAVE_PAGE_PROTECTION
static int
_sodium_mprotect(void *ptr, int (*cb)(void *ptr, size_t size))
{
(void) ptr;
(void) cb;
errno = ENOSYS;
return -1;
}
#else
static int static int
_sodium_mprotect(void *ptr, int (*cb)(void *ptr, size_t size)) _sodium_mprotect(void *ptr, int (*cb)(void *ptr, size_t size))
{ {
@ -465,6 +484,7 @@ _sodium_mprotect(void *ptr, int (*cb)(void *ptr, size_t size))
return cb(unprotected_ptr, unprotected_size); return cb(unprotected_ptr, unprotected_size);
} }
#endif
int int
sodium_mprotect_noaccess(void *ptr) sodium_mprotect_noaccess(void *ptr)