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:
parent
17932c782e
commit
26f87e266e
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user