On Mon, Mar 4, 2019 at 9:46 PM David Brown <david.br...@hesbynett.no> wrote:
>
> On 19/02/2019 11:23, P J P wrote:
> > Hello,
> >    -> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87210
> >
> > This RFE is about providing gcc option(s) to eliminate information leakage
> > issues from programs. Information leakage via uninitialised memory has 
> > beena chronic/recurring issue across all software. They are found quite 
> > often andmay lead to severe effects if found in system software/kernel, OR 
> > an applicationwhich handles sensitive information.
> > Various projects/efforts are underway to keep such information exposurefrom 
> > happening
> > * STACKLEAK - http://lkml.iu.edu/hypermail/linux/kernel/1810.3/00522.html
> > * KLEAK - https://netbsd.org/gallery/presentations/maxv/kleak.pdf* 
> > https://j00ru.vexillium.org/papers/2018/bochspwn_reloaded.pdf
> > But these are still external corrections to improve specific project 
> > and/orsoftware. It does not help to fix/eliminate all information leakage 
> > issues.
> > Automatic memory initialisation:
> >
> > * https://lists.llvm.org/pipermail/cfe-dev/2018-November/060172.html
> > * https://reviews.llvm.org/D54604
> > It'd be immensely helpful and welcome if gcc(1) could provide 
> > compile/buildtime options to enable/disable - automatic memory 
> > initialisation.
> > Could we please consider it as more viable/useful option?
> > Thank you.---
> >    -P J P
> > http://feedmug.com
> >
>
> This strikes me as getting the issue completely backwards.
>
> It is not lack of initialisation of stack variables that leads to
> information leakage - it is a failure to clear the important data left
> behind on the stack.
Well, yes and no.
If we consider only a handful of variables containing important data,
we can probably afford to annotate them to be cleared upon leaving the
function using an attribute you're suggesting below.
(Although humans are really bad at annotating code - such attributes
go out of sync in no time).
But e.g. in the Linux kernel even a leak of a single word or a pointer
can help malicious users to defeat ASLR, stack canaries etc.
Now, if we choose to clear _every_ local variable when we leave the
function, we'll have to memset the whole stack frame, which is costly
(as you mention, we don't want the memset to be optimized away).
At the same time, memsetting locals upon function entry gives us the
same result, but has a bigger optimization potential (most of the time
one won't have to pre-initialize anything, thanks to DSE).

> The problem with information leakage is when you have something like:
>
> void foo(void) {
>         char key[20];
>         strcpy(key, "Top secret!");
>         usekey(&key);
>         memset(key, 0, sizeof(key));    // optimised away by DSE
> }
>
> void bar(void) {
>         foo();
>         char stolen_key[40];    // Covering "key" and other stack
>         steal_key(&stolen_key);
> }
>
>
> Forcing "stolen_key" to be zero initialised does not help anyone -
> options for that just make code slower and hide errors that would occur
> with other compiler options.  The challenge is to make sure /key/ is
> zeroed out after use - no matter what optimisations, and whether or not
> the "memset" is called.
>
> gcc already has mechanisms for handling this.
>
> First, there is a way to tell gcc that something in memory will be read,
> even though it doesn't look like it:
>
> void foo(void) {
>      char key[20];
>      strcpy(key, "Top secret");
>      usekey(key);
>      memset(key, 0, sizeof(key));
>      {
>          typedef struct { char x[20]; } XS;
>          XS *p = (XS *) key;
>          asm("" : "+m" (*p));
>      }
> }
>
> Next, to automate the clearing of the key regardless of how and when the
> function "foo" is exited and whether or not "memset" is called, we can
> use the "cleanup" attribute:
>
> static void clearKey(char (*key)[20]) {
>      memset(key, 0, 20);
>      {
>          typedef struct { char x[20]; } XS;
>          XS *p = (XS *) key;
>          asm("" : "+m" (*p));
>      }
> }
>
> void foo2(void) {
>      char key[20] __attribute__((cleanup(clearKey)));
>      strcpy(key, "Top secret");
>      usekey(key);
> }
>
> This stops information leakage where it should be stopped - once the
> information is no longer used.  Forcing initialisation of stack
> variables would put it in the wrong place, when the stack space is reused.
>
> And the code generated here is as good as it gets - no efficiency is lost.
>
>
> So as far as I can see, gcc has all the bits it needs - it just needs a
> nicer and simpler syntax.  Something like an attribute "secure" which
> will generate and use an appropriately sized zeroing function on scope
> exit.  Ideally, this could be attached to a type as well as a variable.
>
> (I have no idea how simple or difficult this task might be.)
>
>


-- 
Alexander Potapenko
Software Engineer

Google Germany GmbH
Erika-Mann-Straße, 33
80636 München

Geschäftsführer: Paul Manicle, Halimah DeLaine Prado
Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg

Reply via email to