Compare commits
10 Commits
b5dd9d11d9
...
d3152b8e8f
Author | SHA1 | Date | |
---|---|---|---|
|
d3152b8e8f | ||
|
2e9daf3122 | ||
|
6038030d0b | ||
|
4d23fa37ad | ||
|
6d36e758f5 | ||
|
cd9b875297 | ||
|
2250130c53 | ||
|
72dba6765f | ||
|
8f38bbdee6 | ||
|
dd427cb3b8 |
@ -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: '*'
|
||||
|
@ -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 {
|
||||
|
2
LICENSE
2
LICENSE
@ -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
|
||||
|
13
Makefile
13
Makefile
@ -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 $@
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
29
h_malloc.c
29
h_malloc.c
@ -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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user