-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
I presume MaxSize is appropriate, but the libsodium code is a little confusing as the pointers make it look like the data and canary don't necessarily go in the same page. It's not great this is potentially variable as well. AsSpan() is a bit dangerous because it can cause an access violation after Dispose() if you're not careful. It's best to call it each time rather than creating a span variable. NoAccess(), ReadOnly(), and ReadWrite() might want to be renamed. For example, adding 'Access' to the end of each or adding 'Set' to the beginning of each. sodium_allocarray() isn't supported because you can just slice the returned span. It just calls sodium_malloc() anyway.
- Loading branch information
1 parent
d95c5bd
commit b684510
Showing
3 changed files
with
147 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
using static Interop.Libsodium; | ||
|
||
namespace Geralt; | ||
|
||
public sealed class GuardedHeapAllocation : IDisposable | ||
{ | ||
// A canary is placed before the data. However, this max size is artificial to limit memory usage | ||
public static readonly int MaxSize = SecureMemory.PageSize - CANARY_SIZE; | ||
private readonly IntPtr _pointer; | ||
private readonly int _size; | ||
private bool _disposed; | ||
|
||
public GuardedHeapAllocation(int size) | ||
{ | ||
Validation.SizeBetween(nameof(size), size, 1, MaxSize); | ||
Sodium.Initialize(); | ||
_pointer = sodium_malloc((nuint)size); | ||
if (_pointer == IntPtr.Zero) { throw new OutOfMemoryException("Unable to allocate memory."); } | ||
_size = size; | ||
_disposed = false; | ||
} | ||
|
||
public unsafe Span<byte> AsSpan() | ||
{ | ||
if (_disposed) { throw new ObjectDisposedException(nameof(GuardedHeapAllocation)); } | ||
return new Span<byte>((void*)_pointer, _size); | ||
} | ||
|
||
public void NoAccess() | ||
{ | ||
if (_disposed) { throw new ObjectDisposedException(nameof(GuardedHeapAllocation)); } | ||
int ret = sodium_mprotect_noaccess(_pointer); | ||
if (ret != 0) { throw new InvalidOperationException("Unable to make memory inaccessible."); } | ||
} | ||
|
||
public void ReadOnly() | ||
{ | ||
if (_disposed) { throw new ObjectDisposedException(nameof(GuardedHeapAllocation)); } | ||
int ret = sodium_mprotect_readonly(_pointer); | ||
if (ret != 0) { throw new InvalidOperationException("Unable to make memory read-only."); } | ||
} | ||
|
||
public void ReadWrite() | ||
{ | ||
if (_disposed) { throw new ObjectDisposedException(nameof(GuardedHeapAllocation)); } | ||
int ret = sodium_mprotect_readwrite(_pointer); | ||
if (ret != 0) { throw new InvalidOperationException("Unable to make memory readable and writable."); } | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
if (_disposed) { throw new ObjectDisposedException(nameof(GuardedHeapAllocation)); } | ||
// This calls sodium_mprotect_readwrite internally | ||
sodium_free(_pointer); | ||
_disposed = true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters