-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
sodium_malloc() does not check return value from sodium_mlock() #1237
Comments
These system calls are intentionally not checked here. We can't guarantee that On other systems, the system call may or may not work according to the system configuration and the amount of already locked memory, which is very non-deterministic. For many application developers, The reason is was introduced is to mitigate heartbleed-like attacks. It can also be used as a general bound checking mechanism, and it's widely used that way in the test suite. Locking memory is just a bonus step, but without any guarantees. If the documentation states it otherwise or is confusing, that should be clarified. For cases where memory locking is absolutely required, there is the |
The relevant documentation is this:
(found here) I think clarification would be appropriate here, e.g.:
I would also suggest documenting this design decision in the source code, to avoid future misunderstandings of this kind. |
See jedisct1/libsodium#1237: sodium_malloc() calls sodium_mlock() for us, but it ignores any failures reported from there, so if we run out of our mlock quota, instead of failing loudly and clearly, it will just give us non-mlocked memory instead, and when we use it under the assumption that it will be mlocked, all sorts of spurious / nondeterministic failures will result.
See jedisct1/libsodium#1237: sodium_malloc() calls sodium_mlock() for us, but it ignores any failures reported from there, so if we run out of our mlock quota, instead of failing loudly and clearly, it will just give us non-mlocked memory instead, and when we use it under the assumption that it will be mlocked, all sorts of spurious / nondeterministic failures will result.
See jedisct1/libsodium#1237: sodium_malloc() calls sodium_mlock() for us, but it ignores any failures reported from there, so if we run out of our mlock quota, instead of failing loudly and clearly, it will just give us non-mlocked memory instead, and when we use it under the assumption that it will be mlocked, all sorts of spurious / nondeterministic failures will result.
See jedisct1/libsodium#1237: sodium_malloc() calls sodium_mlock() for us, but it ignores any failures reported from there, so if we run out of our mlock quota, instead of failing loudly and clearly, it will just give us non-mlocked memory instead, and when we use it under the assumption that it will be mlocked, all sorts of spurious / nondeterministic failures will result.
Specific source code location:
libsodium/src/libsodium/sodium/utils.c
Line 622 in 3eb9e5a
When
sodium_mlock()
runs into an OS-imposed mlock limit, it will set errno and return -1, and the memory will remain unlocked. Butsodium_malloc()
does not check the return value, so we still get the allocated memory back, and, in line to the documentation, we expect it to be mlocked, but it actually isn't.And because there is no "loud error", the consequences of this may go entirely undetected (after all, the memory itself is still valid, it's just not mlocked), or they may cause spurious errors in code that depends on it being mlocked, like segfaults, assertion failures on line 627, or just silently leaking secrets to swap.
IMO, a fix would amount to this:
sodium_mlock()
.base_ptr
, and returnNULL
.errno
should hold the correct error at this point.The text was updated successfully, but these errors were encountered: