public inbox for gcc-prs@sourceware.org
help / color / mirror / Atom feed
From: wagnerjd@prodigy.net
To: gcc-gnats@gcc.gnu.org
Subject: optimization/8537: Optimizer Removes Code Necessary for Security
Date: Tue, 19 Nov 2002 12:46:00 -0000	[thread overview]
Message-ID: <20021112032056.17836.qmail@sources.redhat.com> (raw)


>Number:         8537
>Category:       optimization
>Synopsis:       Optimizer Removes Code Necessary for Security
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    unassigned
>State:          open
>Class:          wrong-code
>Submitter-Id:   net
>Arrival-Date:   Mon Nov 11 19:26:01 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     Joseph D. Wagner
>Release:        GCC-3.2
>Organization:
>Environment:
i386
but most likely applicable to all environments
>Description:
When optimizing code for "dead store removal" the optimizing compiler may remove code necessary for security.

For example:

// Beginning of Example Code

#include <string>
using std::string;

#include <memory>

// The specifics of this function are
// not important for demonstrating this bug.
const string getPasswordFromUser() const;

bool isPasswordCorrect() {
	bool isPasswordCorrect = false;
	string Password("password");

	if(Password == getPasswordFromUser()) {
		isPasswordCorrect = true;
	}

	// This line is removed from the optimized code
	// even though it secures the code by wiping
	// the password from memory.
	memset(Password, 0, sizeof(Password));

	return isPasswordCorrect;
}

// End of Example Code

It's considered good practice to remove sensitive data from memory when it's no long needed so that the sensitive data doesn't accidentally end up in the swap file, temp file, memory dump file, etc.

However, in the above example, the optimizing compiler removes the "memset" function as part of "dead store removal" optimization.  The optimizing compiler realizes that "memset" writes to "Password" but "Password" is never again read; hence, it is removed as part of the "dead store removal" optimization.

A programmer could erroneously think that his code is secure, even though the securing code -- "memset" -- is removed from the compiled code.
>How-To-Repeat:
Any code where "memset" is the last function to affect a sensitive variable/data would be affected by this problem.
>Fix:
Two fixes exist from this problem: a workaround and a permanent solution.

WORKAROUND: Read "Password" after it has been wiped from memory.

For example, insert this line after "memset":

// Beginning of Example Code

*(volatile char *)Password = *(volatile char *)Password;

// End of Example Code

This will do nothing, but it will result in reading the "Password" variable, signaling to the optimizing compiler that "memset" should not be "dead store removal" optimized out.

PERMANENT SOLUTION: The WORKAROUND uses both memory and execution time.  A better solution would be to turn off optimization for that part of the code.

However, to the best of my knowledge, GCC does not support altering optimization options on-the-fly though preprocessor statements.  (If it does, will someone please provide me with a link to the appropriate documentation?  I was unable to find any documentation showing that GCC supports this feature.)

For example, altering optimization options on-the-fly through preprocessor statements could be implemented this way:

// Beginning of Example Code

#pragma optimize("-no-dead-code-removal")
memset(Password, 0, sizeof(Password));
#pragma optimize("-dead-code-removal")

// End of Example Code

There's a dozen different ways to accomplish this, but to the best of my understanding and knowledge, the PERMANENT SOLUTION has to be implemented as a new feature (if such a feature doesn't already exist).

>Release-Note:
>Audit-Trail:
>Unformatted:


             reply	other threads:[~2002-11-12  3:26 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-11-19 12:46 wagnerjd [this message]
2002-11-22 11:26 fw
2002-11-22 11:26 Joseph D. Wagner
2002-11-22 11:36 Florian Weimer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20021112032056.17836.qmail@sources.redhat.com \
    --to=wagnerjd@prodigy.net \
    --cc=gcc-gnats@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).