Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

override add malloc_conceal api proposal #434

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions src/mem/localalloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -418,15 +418,18 @@ namespace snmalloc
/**
* Allocate memory of a dynamically known size.
*/
template<ZeroMem zero_mem = NoZero>
template<ZeroMem zero_mem = NoZero, CoreDumpMem core_dump = YesDump>
SNMALLOC_FAST_PATH ALLOCATOR void* alloc(size_t size)
{
void* result = nullptr;
#ifdef SNMALLOC_PASS_THROUGH
// snmalloc guarantees a lot of alignment, so we can depend on this
// make pass through call aligned_alloc with the alignment snmalloc
// would guarantee.
void* result = external_alloc::aligned_alloc(
result = external_alloc::aligned_alloc(
natural_alignment(size), round_size(size));
if constexpr (core_dump == NoDump)
SharedStateHandle::Pal::nodump(result, size);
if constexpr (zero_mem == YesZero)
memset(result, 0, size);
return result;
Expand All @@ -438,11 +441,17 @@ namespace snmalloc
{
// Small allocations are more likely. Improve
// branch prediction by placing this case first.
return capptr_reveal(small_alloc<zero_mem>(size));
result = capptr_reveal(small_alloc<zero_mem>(size));
if constexpr (core_dump == NoDump)
SharedStateHandle::Pal::nodump(result, size);
return result;
}

return capptr_reveal(alloc_not_small<zero_mem>(size));
result = capptr_reveal(alloc_not_small<zero_mem>(size));
if constexpr (core_dump == NoDump)
SharedStateHandle::Pal::nodump(result, size);
#endif
return result;
}

/**
Expand Down
35 changes: 35 additions & 0 deletions src/override/malloc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,41 @@ extern "C"
return ThreadAlloc::get().alloc<ZeroMem::YesZero>(sz);
}

#if !defined(__OpenBSD__)
SNMALLOC_EXPORT void* SNMALLOC_NAME_MANGLE(malloc_conceal)(size_t size)
{
return ThreadAlloc::get().alloc<NoZero, CoreDumpMem::NoDump>(size);
}

SNMALLOC_EXPORT void*
SNMALLOC_NAME_MANGLE(calloc_conceal)(size_t nmemb, size_t size)
{
bool overflow = false;
size_t sz = bits::umul(size, nmemb, overflow);
if (SNMALLOC_UNLIKELY(overflow))
{
return SNMALLOC_NAME_MANGLE(snmalloc_set_error)();
}
return ThreadAlloc::get().alloc<ZeroMem::YesZero, CoreDumpMem::NoDump>(sz);
}

SNMALLOC_EXPORT void SNMALLOC_NAME_MANGLE(freezero)(void* p, size_t size)
{
if (SNMALLOC_UNLIKELY(p == nullptr))
{
return;
}

size_t sz = bits::min(size, ThreadAlloc::get().alloc_size(p));
/* we are not trying to be fast, here but disallowing to potentially
* optimize away the memset call */
void* (*volatile memset_fn)(void*, int, size_t) = memset;
memset_fn(p, 0, sz);

ThreadAlloc::get().dealloc(p);
}
#endif

SNMALLOC_EXPORT
size_t SNMALLOC_NAME_MANGLE(malloc_usable_size)(
MALLOC_USABLE_SIZE_QUALIFIER void* ptr)
Expand Down
6 changes: 6 additions & 0 deletions src/pal/pal_consts.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ namespace snmalloc
YesZero
};

enum CoreDumpMem
{
NoDump,
YesDump
};

/**
* Default Tag ID for the Apple class
*/
Expand Down
5 changes: 5 additions & 0 deletions src/pal/pal_freebsd.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ namespace snmalloc
~static_cast<unsigned int>(CHERI_PERM_CHERIABI_VMMAP)));
}
# endif

static void nodump(void* p, size_t size) noexcept
{
madvise(p, size, MADV_NOCORE);
}
};
} // namespace snmalloc
#endif
6 changes: 6 additions & 0 deletions src/pal/pal_freebsd_kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ namespace snmalloc
}
return get_vm_offset(addr);
}

static void nodump(void* p, size_t size) noexcept
{
UNUSED(p);
UNUSED(size);
}
};
}
#endif
5 changes: 5 additions & 0 deletions src/pal/pal_linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ namespace snmalloc
madvise(p, size, MADV_FREE);
}
}

static void nodump(void* p, size_t size) noexcept
{
madvise(p, size, MADV_DONTDUMP);
}
};
} // namespace snmalloc
#endif
6 changes: 6 additions & 0 deletions src/pal/pal_open_enclave.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ namespace snmalloc
oe_memset_s(p, size, 0, size);
}

static void dump(void* p, size_t size) noexcept
{
UNUSED(p);
UNUSED(size);
}

/**
* Source of Entropy
*/
Expand Down
6 changes: 6 additions & 0 deletions src/pal/pal_posix.h
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,12 @@ namespace snmalloc
return nullptr;
}

static void nodump(void* p, size_t size) noexcept
{
UNUSED(p);
UNUSED(size);
}

/**
* Source of Entropy
*
Expand Down
6 changes: 6 additions & 0 deletions src/pal/pal_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,12 @@ namespace snmalloc
return VirtualAlloc(nullptr, size, MEM_RESERVE, PAGE_READWRITE);
}

static void nodump(void* p, size_t size) noexcept
{
UNUSED(p);
UNUSED(size);
}

/**
* Source of Entropy
*/
Expand Down
62 changes: 55 additions & 7 deletions src/test/func/malloc/malloc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,20 @@ void check_result(size_t size, size_t align, void* p, int err, bool null)
our_free(p);
}

void test_calloc(size_t nmemb, size_t size, int err, bool null)
void test_calloc(
void* (*calloc_fn)(size_t, size_t),
size_t nmemb,
size_t size,
int err,
bool null)
{
printf("calloc(%zu, %zu) combined size %zu\n", nmemb, size, nmemb * size);
printf("calloc");
if (calloc_fn == our_calloc_conceal)
printf("_conceal");

printf("(%zu, %zu) combined size %zu\n", nmemb, size, nmemb * size);
errno = SUCCESS;
void* p = our_calloc(nmemb, size);
void* p = calloc_fn(nmemb, size);

if (p != nullptr)
{
Expand Down Expand Up @@ -157,7 +166,7 @@ int main(int argc, char** argv)
check_result(size + 1, 1, our_malloc(size + 1), SUCCESS, false);
}

test_calloc(0, 0, SUCCESS, false);
test_calloc(our_calloc, 0, 0, SUCCESS, false);

our_free(nullptr);

Expand All @@ -173,10 +182,10 @@ int main(int argc, char** argv)
if (overflow)
break;

test_calloc(n, size, SUCCESS, false);
test_calloc(n, 0, SUCCESS, false);
test_calloc(our_calloc, n, size, SUCCESS, false);
test_calloc(our_calloc, n, 0, SUCCESS, false);
}
test_calloc(0, size, SUCCESS, false);
test_calloc(our_calloc, 0, size, SUCCESS, false);
}

for (smallsizeclass_t sc = 0; sc < NUM_SMALL_SIZECLASSES; sc++)
Expand Down Expand Up @@ -210,6 +219,45 @@ int main(int argc, char** argv)

test_realloc(our_malloc(64), 4194304, SUCCESS, false);

for (smallsizeclass_t sc = 0; sc < (MAX_SMALL_SIZECLASS_BITS + 4); sc++)
{
const size_t size = bits::one_at_bit(sc);
printf("malloc_conceal: %zu\n", size);
errno = SUCCESS;
check_result(size, 1, our_malloc_conceal(size), SUCCESS, false);
errno = SUCCESS;
check_result(size + 1, 1, our_malloc_conceal(size + 1), SUCCESS, false);
}

our_freezero(nullptr, 1024);
void* p = our_malloc_conceal(64);
our_freezero(p, 128);
if (((uint8_t*)p)[63] != 0)
{
abort();
}

p = our_malloc_conceal(16);
our_freezero(p, 0);

for (smallsizeclass_t sc = 0; sc < NUM_SMALL_SIZECLASSES; sc++)
{
const size_t size = sizeclass_to_size(sc);

bool overflow = false;
for (size_t n = 1;
bits::umul(size, n, overflow) <= MAX_SMALL_SIZECLASS_SIZE;
n *= 5)
{
if (overflow)
break;

test_calloc(our_calloc_conceal, n, size, SUCCESS, false);
test_calloc(our_calloc_conceal, n, 0, SUCCESS, false);
}
test_calloc(our_calloc_conceal, 0, size, SUCCESS, false);
}

test_posix_memalign(0, 0, EINVAL, true);
test_posix_memalign(((size_t)-1) / 2, 0, EINVAL, true);
test_posix_memalign(OS_PAGE_SIZE, sizeof(uintptr_t) / 2, EINVAL, true);
Expand Down