[cfe-dev] Security fail (memset being optimized away)

Paul Anderson via cfe-dev cfe-dev at lists.llvm.org
Thu Jan 3 07:53:17 PST 2019


Hi:

There's a discussion of this very issue here:

https://wiki.sei.cmu.edu/confluence/display/c/MSC06-C.+Beware+of+compiler+optimizations

-Paul

On 1/3/2019 10:47 AM, myLC at gmx.de via cfe-dev wrote:
> A few days ago Ilja van Sprundel held a talk at the 35C3 (Chaos 
> Computer Club
> annual convention) calling it "Memsad - why clearing memory is hard".
> It can be found here:
>
> https://media.ccc.de/v/35c3-9788-memsad
> or here:
> https://www.youtube.com/watch?v=0WzjAKABSDk
>
> The problem he described arises, when you have a buffer with sensitive 
> content
> (crypto key) and try to clear this from memory, before the buffer goes 
> out of
> scope:
>
>
> #include <string.h>
>
> void foo( int x ) {
>     char buf[ 10 ];
>     size_t i;
>     for( i = 0; i < sizeof( buf ); ++i )
>         buf[ i ] = x++;
> // ...
>     memset( buf, 0, sizeof( buf ) );    // rightfully removed by 
> optimizer
> }
>
>
> He showed how this sort of code could be found in many 
> implementations, thus
> "leaking" sensitive information into memory (core dumps), which was 
> intended
> to be overwritten. He described the problematic of finding a portable 
> solution
> for a "forced memset".
>
>
> Purely out of curiosity, this made me wonder about how to force the 
> execution
> of a function that would otherwise be optimized away - in a portable 
> manner.
> I came up with these unsophisticated lines:
>
>
> #include <string.h>
>
> void foo( int x ) {
>     char buf[ 10 ];
>     size_t i;
>     for( i = 0; i < sizeof( buf ); ++i )
>         buf[ i ] = x++;
> // ...
>     // Declare volvar as volatile pointer to function (void*, int, 
> size_t ) returning void*:
>     void* ( *volatile volvar )( void*, int, size_t ) = &memset;
>     // Call memset from within this "black box":
>     ( *volvar )( buf, 0, sizeof( buf ) );
> }
>
>
> The idea behind this is simple. "volvar" is a volatile variable. 
> Therefore,
> the compiler can make no assumptions on its contents at compile time. It
> cannot remove the function call, which is based on that variable's 
> content
> (at that given time).
>
> This code looks portable to me. I tested it on "Compiler Explorer"
> ( https://godbolt.org/ ). It compiles without warnings on all targets I
> tested. Except for one, all contain the reference to memset and 
> display the
> call. The exception is the PowerPC platform in conjunction with CLANG
> ("power64le clang - trunk" and "powerpc64 clang - trunk". I'm 
> guessing, that
> this is running "some version" of memset (inlined?) as well, but 
> references
> to ".LC0 at toc@ha" and such leave me puzzled.
>
>
> Without wanting to disturb too much, I'm asking about your opinion.
> Is this solution portable?
> Does it assure that the function call will not be optimized away?
> And - does the CLANG PowerPC version work as well?
>
>
> Thank you very much and a happy new year!
>     LC
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

-- 
Paul Anderson, VP of Engineering, GrammaTech, Inc.
531 Esty St., Ithaca, NY 14850
Tel: +1 607 273-7340 x118; http://www.grammatech.com



More information about the cfe-dev mailing list