-
Notifications
You must be signed in to change notification settings - Fork 112
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
Fix the sandbox use case and add a test. #269
Conversation
Summary of changes: - Add a new PAL that doesn't allocate memory, which can be used with a memory provider that is pre-initialised with a range of memory. - Slightly refactor the memory provider class so that it has a narrower interface with LargeAlloc and is easier to proxy. - Allow the address space manager and the memory provider to be initialised with a range of memory. This may eventually also remove the need for (or, at least, simplify) the Open Enclave PAL.
This is neccessary for fixing the Verona process isolation code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not entirely familiar with snmalloc or its implementation, so my comments could be misleading. Grain of salt and all.
src/mem/largealloc.h
Outdated
const size_t rsize = bits::one_at_bit(SUPERSLAB_BITS) << large_class; | ||
available_large_chunks_in_bytes -= rsize; | ||
} | ||
return 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this return p
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I honestly have no idea how this passes any tests as written.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You probably would only detect this if you are tracking address space usage, this will not recycle any chunks (i.e. 1MiB ranges) of memory, So tests that go up and down in usage a lot will leak. Did it pass CI. I would expect a Windows test to fail with OOM with this bug. But on your own machine, probably none of the tests will come close to an issue.
src/test/func/sandbox/sandbox.cc
Outdated
{ | ||
if constexpr (pal_supports<AlignedAllocation, DefaultPal>) | ||
{ | ||
return DefaultPal::reserve_aligned<true>(sb_size); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs to test that sb_size >= DefaultPal::minimum_alloc_size
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In theory, yes, but for this test it will be - I don't think we're going to have a PAL that can't allocate 128MiB.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not all PALs provide minimum_alloc_size
. We should probably add that to the concept...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK minimum_alloc_size
is required by AlignedAllocation PALs. Sorry to have left it out of the concept; I can catch that in my next round of miscellany if you don't want to do it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, it uses it here:
snmalloc/src/mem/address_space.h
Lines 181 to 185 in 4837c82
if constexpr (pal_supports<AlignedAllocation, PAL>) | |
{ | |
if (size >= PAL::minimum_alloc_size) | |
return PAL::template reserve_aligned<committed>(size); | |
} |
src/pal/pal_noalloc.h
Outdated
*/ | ||
static constexpr uint64_t pal_features = 0; | ||
|
||
static constexpr size_t page_size = ErrorHandler::page_size; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe BasePal
since it's not just for error handling?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't want to call it a Pal because we don't forward any of the memory ops to it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've modified this to use the Aal's one, so now this just needs to implement the two error-related things.
src/pal/pal_noalloc.h
Outdated
*/ | ||
static std::pair<void*, size_t> reserve_at_least(size_t) noexcept | ||
{ | ||
error("Out of memory"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe expand the comment a bit? "This should never be called. The simplest way to achieve that is to use this PAL with a replacement AddressSpaceManager whose reserve()
method does not attempt to use its Pal to reserve memory. See test/func/sandbox/sandbox.cc for an example." ?
Is this here because PalConcept requires it to be? If that's the only reason, maybe we should add a PalFeature NoAllocation flag and relax the Concept in that case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like that idea of a feature flag for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ASM still has this code path, it just shouldn't be reached. Currently, snmalloc doesn't handle allocation failures at all, this is how the other PALs handle allocation failure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a NoAllocation
flag and guarded access to the reserve-family functions on it. This function is now gone.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ASM still has this code path, it just shouldn't be reached. Currently, snmalloc doesn't handle allocation failures at all, this is how the other PALs handle allocation failure.
Returning nullptr
should work for allocation failures. We have tests that check for OOM as that is requried behaviour on OE. If there are code paths that cannot handle a null return from the Pal, then that is a problem.
src/pal/pal_noalloc.h
Outdated
template<bool page_aligned = false> | ||
static void zero(void* p, size_t size) noexcept | ||
{ | ||
bzero(p, size); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would need to be overridable/mixinable for OE to be able to reuse this. It would be nice to not increase the code size unnecessarily.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or the OE version could just implement snmalloc::bzero
as a wrapper around oe_memset_s
.
Hopefully appease Windows CI.
Fix the consexpr if block in sandbox.cc.
In GCC 8 test:
Uninitialised? |
CI is happy! Thus ends today's game of whack-a-mole. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks for all the changes.
Summary of changes:
memory provider that is pre-initialised with a range of memory.
interface with LargeAlloc and is easier to proxy.
initialised with a range of memory.
This may eventually also remove the need for (or, at least, simplify)
the Open Enclave PAL.