Skip to content

Commit

Permalink
Prevent optimization of buffer clearing.
Browse files Browse the repository at this point in the history
Some buffers that contain sensitive information are cleared after use. If
the compiler sees that memset is a "pure" function, and that the buffer is
not used after the memset, it may optimize away the memset. To prevent
this from happening, read from the buffer after the memset.
  • Loading branch information
evangreen committed Oct 18, 2016
1 parent dc47f14 commit 0a26e03
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 27 deletions.
1 change: 0 additions & 1 deletion apps/debug/client/profthrd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1519,7 +1519,6 @@ Return Value:
return NULL;
}

memset(IntegerArray, 0, ArgumentCount * sizeof(ULONG));
for (Index = 0; Index < ArgumentCount; Index += 1) {
Integer = strtoul(Arguments[Index], &AfterScan, 0);
if (AfterScan == Arguments[Index]) {
Expand Down
26 changes: 13 additions & 13 deletions apps/libc/crypt/crypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ Return Value:
// No security droppings.
//

memset(Hash, 0, MD5_HASH_SIZE);
SECURITY_ZERO(Hash, MD5_HASH_SIZE);
return ClCryptBuffer;
}

Expand Down Expand Up @@ -830,12 +830,12 @@ Return Value:
// Clear things out to avoid leaving security context around.
//

memset(Hash, 0, SHA256_HASH_SIZE);
memset(Hash2, 0, SHA256_HASH_SIZE);
memset(PBytes, 0, KeyLength);
memset(SBytes, 0, SaltLength);
memset(&Context, 0, sizeof(Context));
memset(&Context2, 0, sizeof(Context2));
SECURITY_ZERO(Hash, SHA256_HASH_SIZE);
SECURITY_ZERO(Hash2, SHA256_HASH_SIZE);
SECURITY_ZERO(PBytes, KeyLength);
SECURITY_ZERO(SBytes, SaltLength);
SECURITY_ZERO(&Context, sizeof(Context));
SECURITY_ZERO(&Context2, sizeof(Context2));
return Buffer;
}

Expand Down Expand Up @@ -1307,12 +1307,12 @@ Return Value:
// Clear things out to avoid leaving security context around.
//

memset(Hash, 0, SHA512_HASH_SIZE);
memset(Hash2, 0, SHA512_HASH_SIZE);
memset(PBytes, 0, KeyLength);
memset(SBytes, 0, SaltLength);
memset(&Context, 0, sizeof(Context));
memset(&Context2, 0, sizeof(Context2));
SECURITY_ZERO(Hash, SHA512_HASH_SIZE);
SECURITY_ZERO(Hash2, SHA512_HASH_SIZE);
SECURITY_ZERO(PBytes, KeyLength);
SECURITY_ZERO(SBytes, SaltLength);
SECURITY_ZERO(&Context, sizeof(Context));
SECURITY_ZERO(&Context2, sizeof(Context2));
return Buffer;
}

Expand Down
15 changes: 15 additions & 0 deletions apps/libc/crypt/cryptp.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,21 @@ Module Name:

#define LIBCRYPT_API __DLLEXPORT

//
// --------------------------------------------------------------------- Macros
//

//
// This macro zeros memory and ensures that the compiler doesn't optimize away
// the memset.
//

#define SECURITY_ZERO(_Buffer, _Size) \
{ \
memset((_Buffer), 0, (_Size)); \
*(volatile char *)(_Buffer) = *((volatile char *)(_Buffer) + 1); \
}

//
// ---------------------------------------------------------------- Definitions
//
Expand Down
11 changes: 11 additions & 0 deletions apps/libc/dynamic/libcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@ Module Name:
(_Stream)->Flags |= (_Orientation); \
}

//
// This macro zeros memory and ensures that the compiler doesn't optimize away
// the memset.
//

#define SECURITY_ZERO(_Buffer, _Size) \
{ \
memset((_Buffer), 0, (_Size)); \
*(volatile char *)(_Buffer) = *((volatile char *)(_Buffer) + 1); \
}

//
// This macro asserts that the file permission bits are equivalent.
//
Expand Down
2 changes: 1 addition & 1 deletion apps/libc/dynamic/line.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ Return Value:
memcpy(NewBuffer, ClGetpassBuffer, ClGetpassBufferSize);
}

memset(ClGetpassBuffer, 0, ClGetpassBufferSize);
SECURITY_ZERO(ClGetpassBuffer, ClGetpassBufferSize);
free(ClGetpassBuffer);
ClGetpassBuffer = NULL;
ClGetpassBufferSize = 0;
Expand Down
8 changes: 4 additions & 4 deletions apps/swiss/login/chpasswd.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,11 +317,11 @@ Return Value:
LineNumber = 1;
while (TRUE) {
if (Line != NULL) {
memset(Line, 0, strlen(Line));
SECURITY_ZERO(Line, strlen(Line));
}

if ((NewPassword != Password) && (NewPassword != NULL)) {
memset(NewPassword, 0, strlen(NewPassword));
SECURITY_ZERO(NewPassword, strlen(NewPassword));
NewPassword = NULL;
}

Expand Down Expand Up @@ -482,12 +482,12 @@ Return Value:
}

if (Line != NULL) {
memset(Line, 0, strlen(Line));
SECURITY_ZERO(Line, strlen(Line));
free(Line);
}

if (NewPassword != NULL) {
memset(NewPassword, 0, strlen(NewPassword));
SECURITY_ZERO(NewPassword, strlen(NewPassword));
}

closelog();
Expand Down
15 changes: 15 additions & 0 deletions apps/swiss/login/lutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,21 @@ Module Name:
#include <pwd.h>
#include <shadow.h>

//
// --------------------------------------------------------------------- Macros
//

//
// This macro zeros memory and ensures that the compiler doesn't optimize away
// the memset.
//

#define SECURITY_ZERO(_Buffer, _Size) \
{ \
memset((_Buffer), 0, (_Size)); \
*(volatile char *)(_Buffer) = *((volatile char *)(_Buffer) + 1); \
}

//
// ---------------------------------------------------------------- Definitions
//
Expand Down
16 changes: 8 additions & 8 deletions apps/swiss/login/passwd.c
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ Return Value:
MainEnd:
closelog();
if (NewPassword != NULL) {
memset(NewPassword, 0, strlen(NewPassword));
SECURITY_ZERO(NewPassword, strlen(NewPassword));
free(NewPassword);
}

Expand Down Expand Up @@ -563,7 +563,7 @@ Return Value:
// Zero out the password buffer.
//

memset(CurrentPassword, 0, strlen(CurrentPassword));
SECURITY_ZERO(CurrentPassword, strlen(CurrentPassword));
if (Correct == FALSE) {
sleep(LOGIN_FAIL_DELAY);
PasswdLogMessage(LOG_WARNING,
Expand All @@ -586,7 +586,7 @@ Return Value:
}

NewPasswordCopy = strdup(NewPassword);
memset(NewPassword, 0, strlen(NewPassword));
SECURITY_ZERO(NewPassword, strlen(NewPassword));
if (NewPasswordCopy == NULL) {
return NULL;
}
Expand All @@ -597,7 +597,7 @@ Return Value:

NewPassword = getpass("Retype new password: ");
if (NewPassword == NULL) {
memset(NewPasswordCopy, 0, strlen(NewPasswordCopy));
SECURITY_ZERO(NewPasswordCopy, strlen(NewPasswordCopy));
free(NewPasswordCopy);
NewPasswordCopy = NULL;
return NULL;
Expand All @@ -609,7 +609,7 @@ Return Value:
//

Match = strcmp(NewPassword, NewPasswordCopy);
memset(NewPassword, 0, strlen(NewPassword));
SECURITY_ZERO(NewPassword, strlen(NewPassword));
Correct = SwCheckPassword(NewPasswordCopy, OldPasswordHash);
if ((Match != 0) ||
(Correct != FALSE) ||
Expand All @@ -630,7 +630,7 @@ Return Value:
"New password is the same as the old one");
}

memset(NewPasswordCopy, 0, strlen(NewPasswordCopy));
SECURITY_ZERO(NewPasswordCopy, strlen(NewPasswordCopy));
free(NewPasswordCopy);
NewPasswordCopy = NULL;
continue;
Expand All @@ -651,15 +651,15 @@ Return Value:
0,
NewPasswordCopy);

memset(NewPasswordCopy, 0, strlen(NewPasswordCopy));
SECURITY_ZERO(NewPasswordCopy, strlen(NewPasswordCopy));
free(NewPasswordCopy);

//
// Return a copy of that hash to get it out of the static buffer.
//

NewHashedPasswordCopy = strdup(NewHashedPassword);
memset(NewHashedPassword, 0, strlen(NewHashedPassword));
SECURITY_ZERO(NewHashedPassword, strlen(NewHashedPassword));
}

return NewHashedPasswordCopy;
Expand Down

0 comments on commit 0a26e03

Please sign in to comment.