Zapping memory and C++ compatibility

ghudson@MIT.EDU ghudson at MIT.EDU
Fri Nov 20 23:45:40 EST 2009

Back in 2002 or so, people noticed that certain compilers (I think gcc
3.x and Visual C++) would sometimes optimize out a memset() which they
could prove doesn't affect the execution of the program according to
standardized behaviors (which doesn't include accessing stack garbage
or the contents of core dumps or anything of that sort).  So, there
was a lot of discussion about how to securely zero passwords or
cryptographic keys.

We had out own discussion, which you can review at
The eventual upshot was this collection of macros or inlines:

Win32: #define krb5int_zap_data(ptr, len) SecureZeroMemory(ptr, len)
gcc:   static inline void krb5int_zap_data(void *ptr, size_t len) {
       memset(ptr, 0, len); asm volatile ("" : : "g" (ptr), "g" (len)); }
else:  #define krb5int_zap_data(ptr, len) memset((volatile void *)ptr, 0, len)

The last construction was based on the idea that a hypothetical
compiler might see the cast through volatile void * and decide not to
perform an optimization.  It's not clear to me how valid this
reasoning is, since neither the proximal type (after the implicit cast
to void * by the call to memset) nor the original type is volatile.

Today's problem is that the last construction isn't valid C++.  We
have a test case which tries passing k5-int.h through C++ compiler,
and it now fails on Solaris with the native compiler.  It didn't fail
before because the macro was never expanded within k5-int.h, but now
it gets expanded by the new zapfree() inline function.

So, I'm trying to figure out how to resolve this C++ compatibility
issue without raising the likelihood of an information leakage
vulnerability.  A possible choice is to make the macro more obviously
wishy-washy by explicitly casting ptr back to void *:

  memset((void *)(volatile void *)ptr, 0, len)

Anyway, advice appreciated if anyone on the list has expertise in this

More information about the krbdev mailing list