mirror of
https://github.com/GrapheneOS/hardened_malloc.git
synced 2025-11-04 17:56:33 +01:00
Compare commits
2 commits
5d22d91964
...
bf211cd9e4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf211cd9e4 | ||
|
|
4461652d45 |
8 changed files with 53 additions and 67 deletions
|
|
@ -279,7 +279,7 @@ The following boolean configuration options are available:
|
|||
* `CONFIG_BLOCK_OPS_CHECK_SIZE`: `true` or `false` (default) to ensure length
|
||||
parameter of the memcpy/memmove/memset block operations are within
|
||||
approximate bounds to minimize buffer overflows. Note, memset override is
|
||||
currently disabled due to being broken.
|
||||
currently disabled due to improper behavior.
|
||||
|
||||
The following integer configuration options are available:
|
||||
|
||||
|
|
|
|||
86
h_malloc.c
86
h_malloc.c
|
|
@ -528,7 +528,7 @@ static void set_canary(UNUSED const struct slab_metadata *metadata, UNUSED void
|
|||
}
|
||||
#endif
|
||||
|
||||
h_memcpy_real((char *)p + size - canary_size, &metadata->canary_value, canary_size);
|
||||
memcpy((char *)p + size - canary_size, &metadata->canary_value, canary_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -541,7 +541,7 @@ static void check_canary(UNUSED const struct slab_metadata *metadata, UNUSED con
|
|||
#endif
|
||||
|
||||
u64 canary_value;
|
||||
h_memcpy_real(&canary_value, (const char *)p + size - canary_size, canary_size);
|
||||
memcpy(&canary_value, (const char *)p + size - canary_size, canary_size);
|
||||
|
||||
#ifdef HAS_ARM_MTE
|
||||
if (unlikely(canary_value == 0)) {
|
||||
|
|
@ -831,7 +831,7 @@ static inline void deallocate_small(void *p, const size_t *expected_size) {
|
|||
#endif
|
||||
|
||||
if (ZERO_ON_FREE && !skip_zero) {
|
||||
h_memset_real(p, 0, size - canary_size);
|
||||
memset(p, 0, size - canary_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1502,7 +1502,7 @@ EXPORT void *h_calloc(size_t nmemb, size_t size) {
|
|||
total_size = adjust_size_for_canary(total_size);
|
||||
void *p = alloc(total_size);
|
||||
if (!ZERO_ON_FREE && likely(p != NULL) && total_size && total_size <= max_slab_size_class) {
|
||||
h_memset_real(p, 0, total_size - canary_size);
|
||||
memset(p, 0, total_size - canary_size);
|
||||
}
|
||||
#ifdef HAS_ARM_MTE
|
||||
// use an assert instead of adding a conditional to memset() above (freed memory is always
|
||||
|
|
@ -1624,7 +1624,7 @@ EXPORT void *h_realloc(void *old, size_t size) {
|
|||
mutex_unlock(&ra->lock);
|
||||
|
||||
if (memory_remap_fixed(old, old_size, new, size)) {
|
||||
h_memcpy_real(new, old, copy_size);
|
||||
memcpy(new, old, copy_size);
|
||||
deallocate_pages(old, old_size, old_guard_size);
|
||||
} else {
|
||||
memory_unmap((char *)old - old_guard_size, old_guard_size);
|
||||
|
|
@ -1646,7 +1646,7 @@ EXPORT void *h_realloc(void *old, size_t size) {
|
|||
if (copy_size > 0 && copy_size <= max_slab_size_class) {
|
||||
copy_size -= canary_size;
|
||||
}
|
||||
h_memcpy_real(new, old_orig, copy_size);
|
||||
memcpy(new, old_orig, copy_size);
|
||||
if (old_size <= max_slab_size_class) {
|
||||
deallocate_small(old, NULL);
|
||||
} else {
|
||||
|
|
@ -1874,8 +1874,8 @@ EXPORT size_t h_malloc_object_size_fast(const void *p) {
|
|||
return SIZE_MAX;
|
||||
}
|
||||
|
||||
#if CONFIG_BLOCK_OPS_CHECK_SIZE
|
||||
inline void *h_memcpy_real(void *dst, const void *src, size_t len) {
|
||||
#if CONFIG_BLOCK_OPS_CHECK_SIZE && !defined(HAS_ARM_MTE)
|
||||
char *p_dst = (char *)dst;
|
||||
char const *p_src = (char const *)src;
|
||||
|
||||
|
|
@ -1884,16 +1884,27 @@ inline void *h_memcpy_real(void *dst, const void *src, size_t len) {
|
|||
}
|
||||
|
||||
return dst;
|
||||
#else
|
||||
return memcpy(dst, src, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
EXPORT void *h_memcpy(void *dst, const void *src, size_t len) {
|
||||
if (len > malloc_object_size_fast(src)) {
|
||||
fatal_error("memcpy read overflow");
|
||||
}
|
||||
if (len > malloc_object_size_fast(dst)) {
|
||||
fatal_error("memcpy buffer overflow");
|
||||
}
|
||||
|
||||
return h_memcpy_real(dst, src, len);
|
||||
}
|
||||
|
||||
inline void *h_memmove_real(void *dst, const void *src, size_t len) {
|
||||
#if CONFIG_BLOCK_OPS_CHECK_SIZE && !defined(HAS_ARM_MTE)
|
||||
char *p_dst = (char *)dst;
|
||||
char const *p_src = (char const *)src;
|
||||
|
||||
if(dst == src) {
|
||||
return dst;
|
||||
}
|
||||
|
||||
if(p_src < p_dst) {
|
||||
p_dst += len;
|
||||
p_src += len;
|
||||
|
|
@ -1901,17 +1912,24 @@ inline void *h_memmove_real(void *dst, const void *src, size_t len) {
|
|||
*--p_dst = *--p_src;
|
||||
}
|
||||
} else {
|
||||
dst = h_memcpy_real(dst, src, len);
|
||||
dst = h_memcpy(dst, src, len);
|
||||
}
|
||||
|
||||
return dst;
|
||||
#else
|
||||
return memmove(dst, src, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
EXPORT void *h_memmove(void *dst, const void *src, size_t len) {
|
||||
if (len > malloc_object_size_fast(src)) {
|
||||
fatal_error("memmove read overflow");
|
||||
}
|
||||
if (len > malloc_object_size_fast(dst)) {
|
||||
fatal_error("memmove buffer overflow");
|
||||
}
|
||||
|
||||
return h_memmove_real(dst, src, len);
|
||||
}
|
||||
|
||||
inline void *h_memset_real(void *dst, int value, size_t len) {
|
||||
#if CONFIG_BLOCK_OPS_CHECK_SIZE && !defined(HAS_ARM_MTE)
|
||||
char *p_dst = (char *)dst;
|
||||
|
||||
while(len--) {
|
||||
|
|
@ -1919,45 +1937,13 @@ inline void *h_memset_real(void *dst, int value, size_t len) {
|
|||
}
|
||||
|
||||
return dst;
|
||||
#else
|
||||
return memset(dst, value, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_BLOCK_OPS_CHECK_SIZE && !defined(HAS_ARM_MTE)
|
||||
EXPORT void *h_memcpy(void *dst, const void *src, size_t len) {
|
||||
if(dst == src || len == 0) {
|
||||
return dst;
|
||||
}
|
||||
if (len > malloc_object_size(src)) {
|
||||
fatal_error("memcpy read overflow");
|
||||
}
|
||||
if (len > malloc_object_size(dst)) {
|
||||
fatal_error("memcpy buffer overflow");
|
||||
}
|
||||
return h_memcpy_real(dst, src, len);
|
||||
}
|
||||
|
||||
EXPORT void *h_memmove(void *dst, const void *src, size_t len) {
|
||||
if(dst == src || len == 0) {
|
||||
return dst;
|
||||
}
|
||||
if (len > malloc_object_size(src)) {
|
||||
fatal_error("memmove read overflow");
|
||||
}
|
||||
if (len > malloc_object_size(dst)) {
|
||||
fatal_error("memmove buffer overflow");
|
||||
}
|
||||
return h_memmove_real(dst, src, len);
|
||||
}
|
||||
|
||||
EXPORT void *h_memset(void *dst, int value, size_t len) {
|
||||
if(len == 0) {
|
||||
return dst;
|
||||
}
|
||||
if (len > malloc_object_size(dst)) {
|
||||
if (len > malloc_object_size_fast(dst)) {
|
||||
fatal_error("memset buffer overflow");
|
||||
}
|
||||
|
||||
return h_memset_real(dst, value, len);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ extern "C" {
|
|||
#define h_realloc realloc
|
||||
#define h_aligned_alloc aligned_alloc
|
||||
#define h_free free
|
||||
#if CONFIG_BLOCK_OPS_CHECK_SIZE && !defined(HAS_ARM_MTE)
|
||||
#if CONFIG_BLOCK_OPS_CHECK_SIZE
|
||||
#define h_memcpy memcpy
|
||||
#define h_memmove memmove
|
||||
//#define h_memset memset
|
||||
|
|
@ -59,12 +59,12 @@ __attribute__((alloc_size(2))) void *h_realloc(void *ptr, size_t size);
|
|||
__attribute__((malloc)) __attribute__((alloc_size(2))) __attribute__((alloc_align(1)))
|
||||
void *h_aligned_alloc(size_t alignment, size_t size);
|
||||
void h_free(void *ptr);
|
||||
#if CONFIG_BLOCK_OPS_CHECK_SIZE
|
||||
void *h_memcpy_real(void *dst, const void *src, size_t len);
|
||||
void *h_memmove_real(void *dst, const void *src, size_t len);
|
||||
void *h_memset_real(void *dst, int value, size_t len);
|
||||
#if CONFIG_BLOCK_OPS_CHECK_SIZE && !defined(HAS_ARM_MTE)
|
||||
void *h_memcpy(void *dst, const void *src, size_t len);
|
||||
void *h_memmove_real(void *dst, const void *src, size_t len);
|
||||
void *h_memmove(void *dst, const void *src, size_t len);
|
||||
void *h_memset_real(void *dst, int value, size_t len);
|
||||
void *h_memset(void *dst, int value, size_t len);
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ OPTNONE int main(void) {
|
|||
if (!firstbuffer && !secondbuffer) {
|
||||
return 1;
|
||||
}
|
||||
memset(secondbuffer, 'a', 32);
|
||||
memset(secondbuffer, 'a', 16);
|
||||
memcpy(firstbuffer, secondbuffer, 32);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@
|
|||
#include "test_util.h"
|
||||
|
||||
OPTNONE int main(void) {
|
||||
char *firstbuffer = malloc(32);
|
||||
char *secondbuffer = malloc(16);
|
||||
char *firstbuffer = malloc(16);
|
||||
char *secondbuffer = malloc(8);
|
||||
if (!firstbuffer && !secondbuffer) {
|
||||
return 1;
|
||||
}
|
||||
memset(secondbuffer, 'a', 16);
|
||||
memcpy(firstbuffer, secondbuffer, 16);
|
||||
memset(secondbuffer, 'a', 8);
|
||||
memcpy(firstbuffer, secondbuffer, 8);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ OPTNONE int main(void) {
|
|||
if (!firstbuffer && !secondbuffer) {
|
||||
return 1;
|
||||
}
|
||||
memset(secondbuffer, 'a', 32);
|
||||
memset(secondbuffer, 'a', 16);
|
||||
memmove(firstbuffer, secondbuffer, 32);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@
|
|||
#include "test_util.h"
|
||||
|
||||
OPTNONE int main(void) {
|
||||
char *firstbuffer = malloc(32);
|
||||
char *secondbuffer = malloc(16);
|
||||
char *firstbuffer = malloc(16);
|
||||
char *secondbuffer = malloc(8);
|
||||
if (!firstbuffer && !secondbuffer) {
|
||||
return 1;
|
||||
}
|
||||
memset(secondbuffer, 'a', 16);
|
||||
memmove(firstbuffer, secondbuffer, 16);
|
||||
memset(secondbuffer, 'a', 8);
|
||||
memmove(firstbuffer, secondbuffer, 8);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@
|
|||
#include "test_util.h"
|
||||
|
||||
OPTNONE int main(void) {
|
||||
char *buffer = malloc(32);
|
||||
char *buffer = malloc(16);
|
||||
if (!buffer) {
|
||||
return 1;
|
||||
}
|
||||
memset(buffer, 'a', 16);
|
||||
memset(buffer, 'a', 8);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue