mirror of
https://github.com/GrapheneOS/hardened_malloc.git
synced 2025-04-20 06:20:20 +02:00
Compare commits
2 commits
fc042d5daa
...
a73585cc39
Author | SHA1 | Date | |
---|---|---|---|
|
a73585cc39 | ||
|
b5a8849fc8 |
16 changed files with 8 additions and 169 deletions
2
CREDITS
2
CREDITS
|
@ -23,7 +23,7 @@ h_malloc.c open-addressed hash table (regions_grow, regions_insert, regions_find
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
memcpy.c, memccpy.c, memmove.c, memset.c, wmemset.c:
|
memcpy.c, memmove.c, memset.c, wmemset.c:
|
||||||
Copyright © 2005-2020 Rich Felker, et al.
|
Copyright © 2005-2020 Rich Felker, et al.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
|
6
Makefile
6
Makefile
|
@ -41,7 +41,7 @@ LDFLAGS := $(LDFLAGS) -Wl,-O1,--as-needed,-z,defs,-z,relro,-z,now,-z,nodlopen,-z
|
||||||
|
|
||||||
SOURCES := chacha.c h_malloc.c memory.c pages.c random.c util.c
|
SOURCES := chacha.c h_malloc.c memory.c pages.c random.c util.c
|
||||||
ifeq ($(CONFIG_BLOCK_OPS_CHECK_SIZE),true)
|
ifeq ($(CONFIG_BLOCK_OPS_CHECK_SIZE),true)
|
||||||
SOURCES += memcpy.c memccpy.c memmove.c memset.c wmemset.c
|
SOURCES += memcpy.c memmove.c memset.c wmemset.c
|
||||||
BOSC_EXTRAS := musl.h
|
BOSC_EXTRAS := musl.h
|
||||||
endif
|
endif
|
||||||
OBJECTS := $(SOURCES:.c=.o)
|
OBJECTS := $(SOURCES:.c=.o)
|
||||||
|
@ -135,15 +135,13 @@ $(OUT)/new.o: new.cc include/h_malloc.h util.h $(CONFIG_FILE) | $(OUT)
|
||||||
$(COMPILE.cc) $(OUTPUT_OPTION) $<
|
$(COMPILE.cc) $(OUTPUT_OPTION) $<
|
||||||
$(OUT)/pages.o: pages.c pages.h memory.h util.h $(CONFIG_FILE) | $(OUT)
|
$(OUT)/pages.o: pages.c pages.h memory.h util.h $(CONFIG_FILE) | $(OUT)
|
||||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||||
$(OUT)/random.o: random.c random.h chacha.h $(BOSC_EXTRAS) util.h $(CONFIG_FILE) | $(OUT)
|
$(OUT)/random.o: random.c random.h chacha.h util.h $(CONFIG_FILE) | $(OUT)
|
||||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||||
$(OUT)/util.o: util.c util.h $(CONFIG_FILE) | $(OUT)
|
$(OUT)/util.o: util.c util.h $(CONFIG_FILE) | $(OUT)
|
||||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||||
|
|
||||||
$(OUT)/memcpy.o: memcpy.c musl.h $(CONFIG_FILE) | $(OUT)
|
$(OUT)/memcpy.o: memcpy.c musl.h $(CONFIG_FILE) | $(OUT)
|
||||||
$(COMPILE.c) -Wno-cast-align $(OUTPUT_OPTION) $<
|
$(COMPILE.c) -Wno-cast-align $(OUTPUT_OPTION) $<
|
||||||
$(OUT)/memccpy.o: memccpy.c musl.h $(CONFIG_FILE) | $(OUT)
|
|
||||||
$(COMPILE.c) -Wno-cast-align $(OUTPUT_OPTION) $<
|
|
||||||
$(OUT)/memmove.o: memmove.c musl.h $(CONFIG_FILE) | $(OUT)
|
$(OUT)/memmove.o: memmove.c musl.h $(CONFIG_FILE) | $(OUT)
|
||||||
$(COMPILE.c) -Wno-cast-align $(OUTPUT_OPTION) $<
|
$(COMPILE.c) -Wno-cast-align $(OUTPUT_OPTION) $<
|
||||||
$(OUT)/memset.o: memset.c musl.h $(CONFIG_FILE) | $(OUT)
|
$(OUT)/memset.o: memset.c musl.h $(CONFIG_FILE) | $(OUT)
|
||||||
|
|
|
@ -277,8 +277,8 @@ The following boolean configuration options are available:
|
||||||
this feature is enabled, the metadata is all contained within an isolated
|
this feature is enabled, the metadata is all contained within an isolated
|
||||||
memory region with high entropy random guard regions around it.
|
memory region with high entropy random guard regions around it.
|
||||||
* `CONFIG_BLOCK_OPS_CHECK_SIZE`: `true` or `false` (default) to ensure length
|
* `CONFIG_BLOCK_OPS_CHECK_SIZE`: `true` or `false` (default) to ensure length
|
||||||
parameter of the memcpy/memccpy/memmove/memset block operations and their
|
parameter of the memcpy/memmove/memset block operations and their wide
|
||||||
wide variants are within approximate bounds to minimize buffer overflows.
|
variants are within approximate bounds to minimize buffer overflows.
|
||||||
|
|
||||||
The following integer configuration options are available:
|
The following integer configuration options are available:
|
||||||
|
|
||||||
|
|
16
h_malloc.c
16
h_malloc.c
|
@ -1895,22 +1895,6 @@ EXPORT void *memcpy(void *restrict dst, const void *restrict src, size_t len) {
|
||||||
return musl_memcpy(dst, src, len);
|
return musl_memcpy(dst, src, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT void *memccpy(void *restrict dst, const void *restrict src, int value, size_t len) {
|
|
||||||
if (unlikely(dst == src || len == 0)) {
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
if (unlikely(dst < (src + len) && (dst + len) > src)) {
|
|
||||||
fatal_error("memccpy overlap");
|
|
||||||
}
|
|
||||||
if (unlikely(len > malloc_object_size(src))) {
|
|
||||||
fatal_error("memccpy read overflow");
|
|
||||||
}
|
|
||||||
if (unlikely(len > malloc_object_size(dst))) {
|
|
||||||
fatal_error("memccpy buffer overflow");
|
|
||||||
}
|
|
||||||
return musl_memccpy(dst, src, value, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPORT void *memmove(void *dst, const void *src, size_t len) {
|
EXPORT void *memmove(void *dst, const void *src, size_t len) {
|
||||||
if (unlikely(dst == src || len == 0)) {
|
if (unlikely(dst == src || len == 0)) {
|
||||||
return dst;
|
return dst;
|
||||||
|
|
|
@ -57,7 +57,6 @@ void h_free(void *ptr);
|
||||||
|
|
||||||
#if CONFIG_BLOCK_OPS_CHECK_SIZE && !defined(HAS_ARM_MTE)
|
#if CONFIG_BLOCK_OPS_CHECK_SIZE && !defined(HAS_ARM_MTE)
|
||||||
void *memcpy(void *dst, const void *src, size_t len);
|
void *memcpy(void *dst, const void *src, size_t len);
|
||||||
void *memccpy(void *dst, const void *src, int value, size_t len);
|
|
||||||
void *memmove(void *dst, const void *src, size_t len);
|
void *memmove(void *dst, const void *src, size_t len);
|
||||||
void *memset(void *dst, int value, size_t len);
|
void *memset(void *dst, int value, size_t len);
|
||||||
wchar_t *wmemcpy(wchar_t *dst, const wchar_t *src, size_t len);
|
wchar_t *wmemcpy(wchar_t *dst, const wchar_t *src, size_t len);
|
||||||
|
|
38
memccpy.c
38
memccpy.c
|
@ -1,38 +0,0 @@
|
||||||
#include "musl.h"
|
|
||||||
|
|
||||||
/* Copied from musl libc version 1.2.5 licensed under the MIT license */
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <limits.h>
|
|
||||||
|
|
||||||
#define ALIGN (sizeof(size_t)-1)
|
|
||||||
#define ONES ((size_t)-1/UCHAR_MAX)
|
|
||||||
#define HIGHS (ONES * (UCHAR_MAX/2+1))
|
|
||||||
#define HASZERO(x) (((x)-ONES) & ~(x) & HIGHS)
|
|
||||||
|
|
||||||
void *musl_memccpy(void *restrict dest, const void *restrict src, int c, size_t n)
|
|
||||||
{
|
|
||||||
unsigned char *d = dest;
|
|
||||||
const unsigned char *s = src;
|
|
||||||
|
|
||||||
c = (unsigned char)c;
|
|
||||||
#ifdef __GNUC__
|
|
||||||
typedef size_t __attribute__((__may_alias__)) word;
|
|
||||||
word *wd;
|
|
||||||
const word *ws;
|
|
||||||
if (((uintptr_t)s & ALIGN) == ((uintptr_t)d & ALIGN)) {
|
|
||||||
for (; ((uintptr_t)s & ALIGN) && n && (*d=*s)!=c; n--, s++, d++);
|
|
||||||
if ((uintptr_t)s & ALIGN) goto tail;
|
|
||||||
size_t k = ONES * c;
|
|
||||||
wd=(void *)d; ws=(const void *)s;
|
|
||||||
for (; n>=sizeof(size_t) && !HASZERO(*ws^k);
|
|
||||||
n-=sizeof(size_t), ws++, wd++) *wd = *ws;
|
|
||||||
d=(void *)wd; s=(const void *)ws;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
for (; n && (*d=*s)!=c; n--, s++, d++);
|
|
||||||
tail:
|
|
||||||
if (n) return d+1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
1
musl.h
1
musl.h
|
@ -3,7 +3,6 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
void *musl_memcpy(void *dst, const void *src, size_t len);
|
void *musl_memcpy(void *dst, const void *src, size_t len);
|
||||||
void *musl_memccpy(void *restrict dest, const void *restrict src, int c, size_t n);
|
|
||||||
void *musl_memmove(void *dst, const void *src, size_t len);
|
void *musl_memmove(void *dst, const void *src, size_t len);
|
||||||
void *musl_memset(void *dst, int value, size_t len);
|
void *musl_memset(void *dst, int value, size_t len);
|
||||||
wchar_t *musl_wmemset(wchar_t *dst, wchar_t value, size_t len);
|
wchar_t *musl_wmemset(wchar_t *dst, wchar_t value, size_t len);
|
||||||
|
|
10
random.c
10
random.c
|
@ -5,10 +5,6 @@
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#if CONFIG_BLOCK_OPS_CHECK_SIZE && !defined(HAS_ARM_MTE)
|
|
||||||
#include "musl.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/random.h>
|
#include <sys/random.h>
|
||||||
|
|
||||||
static void get_random_seed(void *buf, size_t size) {
|
static void get_random_seed(void *buf, size_t size) {
|
||||||
|
@ -69,7 +65,7 @@ void get_random_bytes(struct random_state *state, void *buf, size_t size) {
|
||||||
|
|
||||||
size_t remaining = RANDOM_CACHE_SIZE - state->index;
|
size_t remaining = RANDOM_CACHE_SIZE - state->index;
|
||||||
size_t copy_size = min(size, remaining);
|
size_t copy_size = min(size, remaining);
|
||||||
h_memcpy_internal(buf, state->cache + state->index, copy_size);
|
memcpy(buf, state->cache + state->index, copy_size);
|
||||||
state->index += copy_size;
|
state->index += copy_size;
|
||||||
|
|
||||||
buf = (char *)buf + copy_size;
|
buf = (char *)buf + copy_size;
|
||||||
|
@ -83,7 +79,7 @@ u16 get_random_u16(struct random_state *state) {
|
||||||
if (remaining < sizeof(value)) {
|
if (remaining < sizeof(value)) {
|
||||||
refill(state);
|
refill(state);
|
||||||
}
|
}
|
||||||
h_memcpy_internal(&value, state->cache + state->index, sizeof(value));
|
memcpy(&value, state->cache + state->index, sizeof(value));
|
||||||
state->index += sizeof(value);
|
state->index += sizeof(value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -110,7 +106,7 @@ u64 get_random_u64(struct random_state *state) {
|
||||||
if (remaining < sizeof(value)) {
|
if (remaining < sizeof(value)) {
|
||||||
refill(state);
|
refill(state);
|
||||||
}
|
}
|
||||||
h_memcpy_internal(&value, state->cache + state->index, sizeof(value));
|
memcpy(&value, state->cache + state->index, sizeof(value));
|
||||||
state->index += sizeof(value);
|
state->index += sizeof(value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
6
random.h
6
random.h
|
@ -22,10 +22,4 @@ u16 get_random_u16_uniform(struct random_state *state, u16 bound);
|
||||||
u64 get_random_u64(struct random_state *state);
|
u64 get_random_u64(struct random_state *state);
|
||||||
u64 get_random_u64_uniform(struct random_state *state, u64 bound);
|
u64 get_random_u64_uniform(struct random_state *state, u64 bound);
|
||||||
|
|
||||||
#if CONFIG_BLOCK_OPS_CHECK_SIZE && !defined(HAS_ARM_MTE)
|
|
||||||
#define h_memcpy_internal musl_memcpy
|
|
||||||
#else
|
|
||||||
#define h_memcpy_internal memcpy
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
4
test/.gitignore
vendored
4
test/.gitignore
vendored
|
@ -45,10 +45,6 @@ memcpy_buffer_overflow
|
||||||
memcpy_read_overflow
|
memcpy_read_overflow
|
||||||
memcpy_valid_same
|
memcpy_valid_same
|
||||||
memcpy_valid_mismatched
|
memcpy_valid_mismatched
|
||||||
memccpy_buffer_overflow
|
|
||||||
memccpy_read_overflow
|
|
||||||
memccpy_valid_same
|
|
||||||
memccpy_valid_mismatched
|
|
||||||
memmove_buffer_overflow
|
memmove_buffer_overflow
|
||||||
memmove_read_overflow
|
memmove_read_overflow
|
||||||
memmove_valid_same
|
memmove_valid_same
|
||||||
|
|
|
@ -72,10 +72,6 @@ EXECUTABLES := \
|
||||||
memcpy_read_overflow \
|
memcpy_read_overflow \
|
||||||
memcpy_valid_same \
|
memcpy_valid_same \
|
||||||
memcpy_valid_mismatched \
|
memcpy_valid_mismatched \
|
||||||
memccpy_buffer_overflow \
|
|
||||||
memccpy_read_overflow \
|
|
||||||
memccpy_valid_same \
|
|
||||||
memccpy_valid_mismatched \
|
|
||||||
memmove_buffer_overflow \
|
memmove_buffer_overflow \
|
||||||
memmove_read_overflow \
|
memmove_read_overflow \
|
||||||
memmove_valid_same \
|
memmove_valid_same \
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "test_util.h"
|
|
||||||
|
|
||||||
OPTNONE int main(void) {
|
|
||||||
char *firstbuffer = malloc(16);
|
|
||||||
char *secondbuffer = malloc(32);
|
|
||||||
if (!firstbuffer && !secondbuffer) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
memset(secondbuffer, 'a', 32);
|
|
||||||
memccpy(firstbuffer, secondbuffer, 'b', 32);
|
|
||||||
return 1;
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "test_util.h"
|
|
||||||
|
|
||||||
OPTNONE int main(void) {
|
|
||||||
char *firstbuffer = malloc(32);
|
|
||||||
char *secondbuffer = malloc(16);
|
|
||||||
if (!firstbuffer && !secondbuffer) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
memset(secondbuffer, 'a', 16);
|
|
||||||
memccpy(firstbuffer, secondbuffer, 'b', 32);
|
|
||||||
return 1;
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "test_util.h"
|
|
||||||
|
|
||||||
OPTNONE int main(void) {
|
|
||||||
char *firstbuffer = malloc(32);
|
|
||||||
char *secondbuffer = malloc(16);
|
|
||||||
if (!firstbuffer && !secondbuffer) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
memset(secondbuffer, 'a', 16);
|
|
||||||
memccpy(firstbuffer, secondbuffer, 'b', 16);
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "test_util.h"
|
|
||||||
|
|
||||||
OPTNONE int main(void) {
|
|
||||||
char *firstbuffer = malloc(16);
|
|
||||||
char *secondbuffer = malloc(16);
|
|
||||||
if (!firstbuffer && !secondbuffer) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
memset(secondbuffer, 'a', 16);
|
|
||||||
memccpy(firstbuffer, secondbuffer, 'b', 16);
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -262,31 +262,6 @@ class TestSimpleMemoryCorruption(unittest.TestCase):
|
||||||
"memcpy_valid_mismatched")
|
"memcpy_valid_mismatched")
|
||||||
self.assertEqual(returncode, 0)
|
self.assertEqual(returncode, 0)
|
||||||
|
|
||||||
#def test_memccpy_buffer_overflow(self):
|
|
||||||
# _stdout, stderr, returncode = self.run_test(
|
|
||||||
# "memccpy_buffer_overflow")
|
|
||||||
# self.assertEqual(returncode, -6)
|
|
||||||
# self.assertEqual(stderr.decode(
|
|
||||||
# "utf-8"), "fatal allocator error: memccpy buffer overflow\n")
|
|
||||||
|
|
||||||
#def test_memccpy_read_overflow(self):
|
|
||||||
# _stdout, stderr, returncode = self.run_test(
|
|
||||||
# "memccpy_read_overflow")
|
|
||||||
# self.assertEqual(returncode, -6)
|
|
||||||
# self.assertEqual(stderr.decode(
|
|
||||||
# "utf-8"), "fatal allocator error: memccpy read overflow\n")
|
|
||||||
|
|
||||||
def test_memccpy_valid_same(self):
|
|
||||||
_stdout, _stderr, returncode = self.run_test(
|
|
||||||
"memccpy_valid_same")
|
|
||||||
self.assertEqual(returncode, 0)
|
|
||||||
|
|
||||||
def test_memccpy_valid_mismatched(self):
|
|
||||||
_stdout, _stderr, returncode = self.run_test(
|
|
||||||
"memccpy_valid_mismatched")
|
|
||||||
self.assertEqual(returncode, 0)
|
|
||||||
|
|
||||||
|
|
||||||
#def test_memmove_buffer_overflow(self):
|
#def test_memmove_buffer_overflow(self):
|
||||||
# _stdout, stderr, returncode = self.run_test(
|
# _stdout, stderr, returncode = self.run_test(
|
||||||
# "memmove_buffer_overflow")
|
# "memmove_buffer_overflow")
|
||||||
|
|
Loading…
Add table
Reference in a new issue