Why would you want to zero a buffer ? Because it may contain sensitive information, I presume. If you don't have additional properties w.r.t allocated memory, what prevent a system with high load to temporarily put the given memory block on swap, leaking the information on disk ? Security is hard...
How to zero a buffer
141–150 of 216 posts
Re: How to zero a buffer
#142Why would you want to zero a buffer ? Because it may contain sensitive information, I presume. If you don't have additional properties w.r.t allocated memory, what prevent a system with high load to temporarily put the given memory block on swap, leaking the information on disk ? Security is hard...
>Why would you want to zero a buffer ? Because it may contain sensitive information, I presume. You don't zero sensitive buffers. You randomize them, then free() them.
Re: How to zero a buffer
#143In GNU C one can add the statement asm ("" : : "m" (&key)); just before or after the memset, effectively telling the compiler that the address of "key" escapes the scope of the function.
GCC also has an `optimize' function attribute which might make sense to use here. This can set optimizations for the function to -O0. But I haven't tried it.
The best answer is really GCC's __asm__("" : : "m" (&key)), or perhaps something like __asm__("" : : "r" (key) : "memory"), after the memset. It generates no extra code, just ensures that the memset won't be removed.
For other compilers (in practice only MSVC, since clang is gcc-compatible), you could pass the pointer to a dummy assembly function instead of using inline assembly; even link-time optimization can't know what happens within a function written in assembly. Or, for better performance, create in assembly a "safer_memset" which is a single instruction: a jump to the real memset function.
Re: How to zero a buffer
#144Is the proposed solution really the best approach? It seems complicated to me and relies on obscure parts of the language. Maybe the problem (compiler optimizes away function call because the result is no longer needed) could be solved like this: memset(key, 0, sizeof(key)); if (key[0]) // we are using key, so you can't skip memset() dropDead(); Unless the compilers "understand" memset and still optimize away the las…
They do. That's the whole "problem" - the compiler knows what memset is and what it does, since it's specified in the standard.
Re: How to zero a buffer
#145Why wouldn't you make key volatile? Shouldn't that solve all the problems? Or is it because it would be to slow because the compiler can't do that many optimizations in the rest of the function any more?
Yes, making key volatile would force the zeroing to happen; and yes, you don't want to do that because it would absolutely kill your code performance.
i.e. declare the storage volatile but running your crypto code on a non-volatile ptr to it (obtained via cast) to get your performance back?
If the compiler then generates enough smarts to work out that the non-volatile ptr you've passed into your crypto code is referring to volatile storage, then you keep security but get a (noticeable in testing?) performance hit.
I guess that's not as good as your solution though.
Re: How to zero a buffer
#146You should have test cases to verify the zeroing behavior in the object code. Even if the standard says a compiler must do something does not mean that it does.
The difficult thing is that any way to verify the zeroing behavior would change the compiler's decision about whether it could elide the call to memset. So it's possible (well, almost guaranteed) that the test would succeed even though the memory wouldn't actually be zeroed in production.
Re: How to zero a buffer
#147Does GCC include any flags to prevent this sort of detrimental optimization?
-O0 // Do Not Optimise
This sounds like it should do the trick (but I've not done C coding for quite some time, so I don't know if there's a nuance as to why it wouldn't), but would also presumably kill any other optimisation.
A better option may be to combine that with pragmas (https://gcc.gnu.org/onlinedocs/gcc/Function-Specific-Option-...) to switch optimisation levels within the code.
Anyone who's played with GCC recently know whether this would work or not?
Re: How to zero a buffer
#148I had no idea that such things are possible in C. The things about I've read recently (the "friendly" C suggestion) and this seem like violations of the spirit of the language. And for what, really? The language looses its signature predictability, which to me seemed like a great feature of C. If you write crappy code and expect the compiler to fix it for you, you should maybe consider another language. I can only im…
> If you write crappy code and expect the compiler to fix it for you, you should maybe consider another language. This seems rather to be a case of writing good code and having the compiler break it for you.
BTW, I gave you an upvote by accident :D
Re: How to zero a buffer
#149When I allocate the key on the heap, the memset is carried (heavily optimized and inlined). When I allocate key on the stack, it disappears. Using gcc -03: #include void doSecure(void) { /*char key[32];*/ char *key = (char*) malloc(sizeof(char)*32); memset(key,sizeof(char),32); } int main(void) { doSecure(); return 0; } -- key on stack main: .LFB13: .cfi_startproc xorl %eax, %eax ret .cfi_endproc -- key on heap main:…
memset(key,sizeof(char),32);
Note that you are not clearing 32 bytes with NUL (byte value 0). You are clearing 32 bytes with byte value 1 == (int)(sizeof(char).That's why memset that works 8 bytes at a time fills memory with 72340172838076673 == 0x0101010101010101
Re: How to zero a buffer
#150Earlier quoted context omitted.
> If you write crappy code and expect the compiler to fix it for you, you should maybe consider another language. This seems rather to be a case of writing good code and having the compiler break it for you.
Yes it is. You misunderstood my point, which was about the purpose of existence for such optimizations - they are meant to improve code, which presumably needs improvement. But if your code needs improvement, then why not go for a higher level language? BTW, I gave you an upvote by accident :D
You could try do low level optimizations in your C or assembly, but for most programs this will eventually backfire. So letting the compiler do its job is actually a good thing.