More forceful clearing of stack memory with keys

gcc 8.3.0 was apparently clever enough to optimize away the previously
used os_memset() to explicitly clear a stack buffer that contains keys
when that clearing happened just before returning from the function.
Since memset_s() is not exactly portable (or commonly available yet..),
use a less robust mechanism that is still pretty likely to prevent
current compilers from optimizing the explicit clearing of the memory
away.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2019-05-26 00:47:17 +03:00
parent e1923f5b6a
commit 31bc66e4d1
25 changed files with 98 additions and 72 deletions

View file

@ -970,7 +970,7 @@ void str_clear_free(char *str)
{
if (str) {
size_t len = os_strlen(str);
os_memset(str, 0, len);
forced_memzero(str, len);
os_free(str);
}
}
@ -979,7 +979,7 @@ void str_clear_free(char *str)
void bin_clear_free(void *bin, size_t len)
{
if (bin) {
os_memset(bin, 0, len);
forced_memzero(bin, len);
os_free(bin);
}
}
@ -1259,3 +1259,22 @@ char * get_param(const char *cmd, const char *param)
val[len] = '\0';
return val;
}
/* Try to prevent most compilers from optimizing out clearing of memory that
* becomes unaccessible after this function is called. This is mostly the case
* for clearing local stack variables at the end of a function. This is not
* exactly perfect, i.e., someone could come up with a compiler that figures out
* the pointer is pointing to memset and then end up optimizing the call out, so
* try go a bit further by storing the first octet (now zero) to make this even
* a bit more difficult to optimize out. Once memset_s() is available, that
* could be used here instead. */
static void * (* const volatile memset_func)(void *, int, size_t) = memset;
static u8 forced_memzero_val;
void forced_memzero(void *ptr, size_t len)
{
memset_func(ptr, 0, len);
if (len)
forced_memzero_val = ((u8 *) ptr)[0];
}