Most likely the security controls weren't correct in the first place, which is pretty bad for a security control.
Most likely the security controls weren't correct in the first place, which is pretty bad for a security control.
For example, trying to zero a page before freeing it (because is contains sensitive information) is surprisingly hard. Optimizing compilers will consider that since the memory is not going to be accessed it doesn't need to write the zeroes to it. Look at all the contortions libsodium goes to do coerce all the compilers to do the right thing :) https://github.com/jedisct1/libsodium/blob/a26467874a512de30...
Also they know, because it's what those functions they call are for. man explicit_bzero for example. It says:
"The explicit_bzero() function performs the same task as bzero(). It differs from bzero() in that it guarantees that compiler optimizations will not remove the erase operation if the compiler deduces that the operation is "unnecessary"."
What is the purpose of this line?
Why do you think it's there if the C code using volatile is enough on its own?
https://github.com/jedisct1/libsodium/blob/a26467874a512de30...
It's a workaround to prevent optimisations because that happens to be how some compilers are implemented today. Will it be implemented like that tomorrow or in a different compiler? Who knows.
https://github.com/jedisct1/libsodium/commit/27872ca13c713c9...
https://boringssl.googlesource.com/boringssl/+/refs/heads/ma...
https://boringssl.googlesource.com/boringssl/+/ad1907fe73334...
However because inline assembly is non-standard even that is not truly guaranteed. Your relying on the good graces of the optimizers that have broken all the other code paths with their legalistic approach.
I must concede this notion troubles me now that you mentioned it, it is indeed possible that GCC or Clang could decide that there is some other way explicit memset-like stuff should be done; and boringssl could deal with it, they are not a stable API for one thing, and Google employs GCC, LLVM and Clang developers anyway so it would be easier for BoringSSL than the rest of the world to fix the compilers changing stuff...
Edit: Actually looking at your link closer (too many #defines makes my eyes glaze over), it looks like the final else branch appears to use volatile like I mentioned.
I assume all the branches above it are optimizations for different systems?
Imo if you don't want the compiler to optimize something, tell it not to. For example in GCC:
__attribute__((optimize("-O0"), noinline))
void zero_memory(void* memory, size_t sz) {
memset(memory, 0, sz);
}
If you wanted to make that portable, there are equivalents in clang and msvc so you'd want to use some #defines here and there. Of course disabling optimizations/inlining in functions has a performance hit, but I think if you're so concerned with code being ignored the tradeoff is appropriate.https://docs.microsoft.com/en-us/previous-versions/windows/d...
The reality is that the source code is just an input, and even if it's correct or sensible, the control flow in the produced binary is the only truth on a system.
An example is when e.g. zeroing out a buffer containing secrets after usage, this overwrite is stripped by the compiler.
For example, to prevent timing attacks positive and negative code paths should take the same amount of time. An optimising compiler could decide that the operations in the negative code path are irrevelant, which in terms of the actual work its doing is true, and remove them. Except now it has reintroduced the timing attack.