Compare commits

...

10 Commits

Author SHA1 Message Date
Daniel Micay d3152b8e8f preserve errno for free calls
This is a future POSIX requirement recently implemented by musl and
glibc.
2023-02-17 13:07:26 -05:00
Daniel Micay 2e9daf3122 merge fprintf/fputs calls in malloc_info 2023-02-17 13:07:26 -05:00
Daniel Micay 6038030d0b no need to check for -fstack-clash-protection
This is supported by the compiler versions listed as minimum
requirements in the README.
2023-02-17 13:07:26 -05:00
Daniel Micay 4d23fa37ad enable Intel CET support 2023-02-17 13:07:26 -05:00
Daniel Micay 6d36e758f5 update copyright notice 2023-02-17 13:07:26 -05:00
Daniel Micay cd9b875297 reorganize compiler switches 2023-02-17 13:07:24 -05:00
Daniel Micay 2250130c53 remove unnecessary UNUSED marker 2022-09-16 01:03:47 -04:00
Daniel Micay 72dba6765f disable tidy identifier length lint 2022-09-16 00:57:08 -04:00
Daniel Micay 8f38bbdee6 add configuration for self-init
This needs to be disabled for compatibility with the exploit protection
compatibility mode on GrapheneOS. hardened_malloc shouldn't be trying to
initialize itself when exploit protection compatibility mode is enabled.
This has to be handled in our Bionic integration instead.
2022-09-14 03:41:31 -04:00
Daniel Micay dd427cb3b8 arm64 page table / page size docs 2022-09-08 23:17:25 -04:00
8 changed files with 41 additions and 17 deletions

View File

@ -1,2 +1,2 @@
Checks: 'bugprone-*,-bugprone-easily-swappable-parameters,-bugprone-macro-parentheses,-bugprone-too-small-loop-variable,cert-*,clang-analyzer-*,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,-clang-diagnostic-constant-logical-operand,readability-*,-readability-function-cognitive-complexity,-readability-inconsistent-declaration-parameter-name,-readability-magic-numbers,-readability-named-parameter,llvm-include-order,misc-*'
Checks: 'bugprone-*,-bugprone-easily-swappable-parameters,-bugprone-macro-parentheses,-bugprone-too-small-loop-variable,cert-*,clang-analyzer-*,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,-clang-diagnostic-constant-logical-operand,readability-*,-readability-function-cognitive-complexity,-readability-identifier-length,-readability-inconsistent-declaration-parameter-name,-readability-magic-numbers,-readability-named-parameter,llvm-include-order,misc-*'
WarningsAsErrors: '*'

View File

@ -1,10 +1,10 @@
common_cflags = [
"-pipe",
"-O3",
//"-flto",
"-fPIC",
"-fvisibility=hidden",
//"-fno-plt",
"-pipe",
"-Wall",
"-Wextra",
"-Wcast-align",
@ -29,6 +29,7 @@ common_cflags = [
"-DCONFIG_CLASS_REGION_SIZE=34359738368", // 32GiB
"-DN_ARENA=1",
"-DCONFIG_STATS=true",
"-DCONFIG_SELF_INIT=false",
]
cc_defaults {

View File

@ -1,4 +1,4 @@
Copyright © 2018-2022 GrapheneOS
Copyright © 2018-2023 GrapheneOS
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -18,9 +18,9 @@ $(shell $(CC) $(if $(filter clang,$(CC)),-Werror=unknown-warning-option) -E $1 -
endef
CPPFLAGS := $(CPPFLAGS) -D_GNU_SOURCE -I include
SHARED_FLAGS := -O3 -flto -fPIC -fvisibility=hidden -fno-plt \
$(call safe_flag,-fstack-clash-protection) -fstack-protector-strong -pipe -Wall -Wextra \
$(call safe_flag,-Wcast-align=strict,-Wcast-align) -Wcast-qual -Wwrite-strings
SHARED_FLAGS := -pipe -O3 -flto -fPIC -fvisibility=hidden -fno-plt \
-fstack-clash-protection $(call safe_flag,-fcf-protection) -fstack-protector-strong \
-Wall -Wextra $(call safe_flag,-Wcast-align=strict,-Wcast-align) -Wcast-qual -Wwrite-strings
ifeq ($(CONFIG_WERROR),true)
SHARED_FLAGS += -Werror
@ -84,6 +84,10 @@ ifeq (,$(filter $(CONFIG_STATS),true false))
$(error CONFIG_STATS must be true or false)
endif
ifeq (,$(filter $(CONFIG_SELF_INIT),true false))
$(error CONFIG_SELF_INIT must be true or false)
endif
CPPFLAGS += \
-DCONFIG_SEAL_METADATA=$(CONFIG_SEAL_METADATA) \
-DZERO_ON_FREE=$(CONFIG_ZERO_ON_FREE) \
@ -102,7 +106,8 @@ CPPFLAGS += \
-DFREE_SLABS_QUARANTINE_RANDOM_LENGTH=$(CONFIG_FREE_SLABS_QUARANTINE_RANDOM_LENGTH) \
-DCONFIG_CLASS_REGION_SIZE=$(CONFIG_CLASS_REGION_SIZE) \
-DN_ARENA=$(CONFIG_N_ARENA) \
-DCONFIG_STATS=$(CONFIG_STATS)
-DCONFIG_STATS=$(CONFIG_STATS) \
-DCONFIG_SELF_INIT=$(CONFIG_SELF_INIT)
$(OUT)/libhardened_malloc$(SUFFIX).so: $(OBJECTS) | $(OUT)
$(CC) $(CFLAGS) $(LDFLAGS) -shared $^ $(LDLIBS) -o $@

View File

@ -181,6 +181,13 @@ large number of guard pages created by hardened\_malloc. As an example, in
This is unnecessary if you set `CONFIG_GUARD_SLABS_INTERVAL` to a very large
value in the build configuration.
On arm64, make sure your kernel is configured to use 4k pages since we haven't
yet added support for 16k and 64k pages. The kernel also has to be configured
to use 4 level page tables for the full 48 bit address space instead of only
having a 39 bit address space for the default hardened\_malloc configuration.
It's possible to reduce the class region size substantially to make a 39 bit
address space workable but the defaults won't work.
## Configuration
You can set some configuration options at compile-time via arguments to the

View File

@ -20,3 +20,4 @@ CONFIG_FREE_SLABS_QUARANTINE_RANDOM_LENGTH := 32
CONFIG_CLASS_REGION_SIZE := 34359738368 # 32GiB
CONFIG_N_ARENA := 4
CONFIG_STATS := false
CONFIG_SELF_INIT := true

View File

@ -20,3 +20,4 @@ CONFIG_FREE_SLABS_QUARANTINE_RANDOM_LENGTH := 32
CONFIG_CLASS_REGION_SIZE := 34359738368 # 32GiB
CONFIG_N_ARENA := 4
CONFIG_STATS := false
CONFIG_SELF_INIT := true

View File

@ -658,6 +658,7 @@ static void enqueue_free_slab(struct size_class *c, struct slab_metadata *metada
c->free_slabs_tail = substitute;
}
// preserves errno
static inline void deallocate_small(void *p, const size_t *expected_size) {
struct slab_size_class_info size_class_info = slab_size_class(p);
size_t class = size_class_info.class;
@ -770,6 +771,7 @@ static inline void deallocate_small(void *p, const size_t *expected_size) {
metadata->prev = NULL;
if (c->empty_slabs_total + slab_size > max_empty_slabs_total) {
int saved_errno = errno;
if (!memory_map_fixed(slab, slab_size)) {
label_slab(slab, slab_size, class);
stats_slab_deallocate(c, slab_size);
@ -778,6 +780,7 @@ static inline void deallocate_small(void *p, const size_t *expected_size) {
return;
}
memory_purge(slab, slab_size);
errno = saved_errno;
// handle out-of-memory by putting it into the empty slabs list
}
@ -1183,11 +1186,13 @@ static inline unsigned init(void) {
return arena;
}
#if CONFIG_SELF_INIT
// trigger early initialization to set up pthread_atfork and protect state as soon as possible
COLD __attribute__((constructor(101))) static void trigger_early_init(void) {
// avoid calling init directly to skip it if this isn't the malloc implementation
h_free(h_malloc(16));
}
#endif
// Returns 0 on overflow.
static size_t get_large_size_class(size_t size) {
@ -1532,6 +1537,7 @@ EXPORT void *h_pvalloc(size_t size) {
}
#endif
// preserves errno
EXPORT void h_free(void *p) {
if (p == NULL) {
return;
@ -1544,7 +1550,9 @@ EXPORT void h_free(void *p) {
return;
}
int saved_errno = errno;
deallocate_large(p, NULL);
errno = saved_errno;
thread_seal_metadata();
}
@ -1855,7 +1863,7 @@ EXPORT struct mallinfo2 h_mallinfo2(void) {
#endif
#ifndef __ANDROID__
EXPORT int h_malloc_info(int options, UNUSED FILE *fp) {
EXPORT int h_malloc_info(int options, FILE *fp) {
if (options) {
errno = EINVAL;
return -1;
@ -1881,12 +1889,13 @@ EXPORT int h_malloc_info(int options, UNUSED FILE *fp) {
mutex_unlock(&c->lock);
if (nmalloc || ndalloc || slab_allocated || allocated) {
fprintf(fp, "<bin nr=\"%u\" size=\"%" PRIu32 "\">", class, size_classes[class]);
fprintf(fp, "<nmalloc>%" PRIu64 "</nmalloc>", nmalloc);
fprintf(fp, "<ndalloc>%" PRIu64 "</ndalloc>", ndalloc);
fprintf(fp, "<slab_allocated>%zu</slab_allocated>", slab_allocated);
fprintf(fp, "<allocated>%zu</allocated>", allocated);
fputs("</bin>", fp);
fprintf(fp, "<bin nr=\"%u\" size=\"%" PRIu32 "\">"
"<nmalloc>%" PRIu64 "</nmalloc>"
"<ndalloc>%" PRIu64 "</ndalloc>"
"<slab_allocated>%zu</slab_allocated>"
"<allocated>%zu</allocated>"
"</bin>", class, size_classes[class], nmalloc, ndalloc, slab_allocated,
allocated);
}
}
@ -1898,9 +1907,9 @@ EXPORT int h_malloc_info(int options, UNUSED FILE *fp) {
size_t region_allocated = ra->allocated;
mutex_unlock(&ra->lock);
fprintf(fp, "<heap nr=\"%u\">", N_ARENA);
fprintf(fp, "<allocated_large>%zu</allocated_large>", region_allocated);
fputs("</heap>", fp);
fprintf(fp, "<heap nr=\"%u\">"
"<allocated_large>%zu</allocated_large>"
"</heap>", N_ARENA, region_allocated);
thread_seal_metadata();
}