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.htmlhttps://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.

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.)


Reply via email to