diff --git a/Makefile b/Makefile index 7f05f11..fcc0435 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,23 @@ +CONFIG_CXX_ALLOCATOR := true + CPPFLAGS := -D_GNU_SOURCE CFLAGS := -std=c11 -Wall -Wextra -Wmissing-prototypes -O2 -flto -fPIC -fvisibility=hidden -fno-plt -pipe +CXXFLAGS := -std=c++14 -Wall -Wextra -O2 -flto -fPIC -fvisibility=hidden -fno-plt -pipe LDFLAGS := -Wl,-z,defs,-z,relro,-z,now,-z,nodlopen,-z,text OBJECTS := chacha.o malloc.o memory.o pages.o random.o util.o +ifeq ($(CONFIG_CXX_ALLOCATOR),true) + LDLIBS += -lstdc++ + OBJECTS += new.o +endif + hardened_malloc.so: $(OBJECTS) $(CC) $(CFLAGS) $(LDFLAGS) -shared $^ $(LDLIBS) -o $@ chacha.o: chacha.c chacha.h malloc.o: malloc.c malloc.h mutex.h config.h memory.h pages.h random.h util.h memory.o: memory.c memory.h util.h +new.o: new.cc pages.o: pages.c pages.h memory.h util.h random.o: random.c random.h chacha.h util.h util.o: util.c util.h diff --git a/README.md b/README.md index 2a0e42c..61e76c5 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,16 @@ libraries. # Configuration +You can set some configuration options at compile-time via arguments to the +make command as follows: + + make CONFIG_EXAMPLE=false + +The available configuration options are the following: + +* `CONFIG_CXX_ALLOCATOR`: `true` (default) or `false` to control whether the + C++ allocator is replaced + Compile-time configuration is available in the `config.h` file for controlling the balance between security and performance / memory usage. By default, all the optional security features are enabled. Options are only provided for the diff --git a/new.cc b/new.cc new file mode 100644 index 0000000..2dff7da --- /dev/null +++ b/new.cc @@ -0,0 +1,82 @@ +#include +#include +#include + +#define noreturn + +extern "C" { +#include "malloc.h" +#include "util.h" +} + +COLD static void *handle_out_of_memory(size_t size, bool nothrow) { + void *ptr; + + do { + std::new_handler handler = std::get_new_handler(); + if (handler == nullptr) { + break; + } + + try { + handler(); + } catch (const std::bad_alloc &) { + break; + } + + ptr = h_malloc(size); + } while (ptr == nullptr); + + if (ptr == nullptr && !nothrow) { + std::__throw_bad_alloc(); + } + return ptr; +} + +static inline void *new_impl(size_t size, bool nothrow) { + void *ptr = h_malloc(size); + if (likely(ptr != nullptr)) { + return ptr; + } + return handle_out_of_memory(size, nothrow); +} + +void *operator new(size_t size) { + return new_impl(size, false); +} + +void *operator new[](size_t size) { + return new_impl(size, false); +} + +void *operator new(size_t size, const std::nothrow_t &) noexcept { + return new_impl(size, true); +} + +void *operator new[](size_t size, const std::nothrow_t &) noexcept { + return new_impl(size, true); +} + +void operator delete(void *ptr) noexcept { + h_free(ptr); +} + +void operator delete[](void *ptr) noexcept { + h_free(ptr); +} + +void operator delete(void *ptr, const std::nothrow_t &) noexcept { + h_free(ptr); +} + +void operator delete[](void *ptr, const std::nothrow_t &) noexcept { + h_free(ptr); +} + +void operator delete(void *ptr, size_t size) noexcept { + h_free_sized(ptr, size); +} + +void operator delete[](void *ptr, size_t size) noexcept { + h_free_sized(ptr, size); +}