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

Jonny Grant via cfe-dev cfe-dev at lists.llvm.org
Fri Jan 4 04:47:00 PST 2019


AM,

Why not just write an inline function which does after memset :-

if(*buf!=0) *buf=0;

For security, it's better to actually verify every byte, sanity check. You
never know, maybe programmer cleared wrong size.

Jonny.





On Fri, 4 Jan 2019, 12:13 Mehdi AMINI via cfe-dev <cfe-dev at lists.llvm.org
wrote:

>
>
> On Thu, Jan 3, 2019 at 7:47 AM myLC at gmx.de via cfe-dev <
> cfe-dev at lists.llvm.org> 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?
>>
>>
> If I understand correctly what you're looking for, this should be
> relevant:
> https://github.com/google/benchmark/blob/master/include/benchmark/benchmark.h#L309-L312
>
> Best,
>
> --
> Mehdi
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20190104/59954e59/attachment.html>


More information about the cfe-dev mailing list