Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Thu, 25 Nov 2010 08:31:01 -0500
From: Nelson Elhage <nelhage@...lice.com>
To: oss-security@...ts.openwall.com
Subject: Re: Interesting behavior with struct initiailization

On Wed, Nov 24, 2010 at 09:52:47AM -0500, Dan Rosenberg wrote:
> ===============================
> 
> 3. gcc does not clear padding bytes on full C99 initialization

I don't claim to be an expect, but fwiw, my read of C99 does not
require a C99 initializer to initialize any padding bytes:

§6.7.8.8 says:
"An initializer specifies the initial value stored in an object."

Note that the initializer specifies a /value/, and §6.2.6.1.6 says

"When a value is stored in an object of structure or union type,
including in a member object, the bytes of the object representation
that correspond to any padding bytes take unspecified values."

Thus, I think there is no way, conceptually, that C99 could even talk
about an initializer specifying the value of padding fields, since an
initializer explicitly specifies a /value/ for the object, which is a
concept that exists at a different level than the /representation/,
which includes padding.

I also can't find anywhere in GCC's manual where it talks about it
making additional guarantees in this case, but I am not completely
confident I did a thorough search.

Is it possible that the zeroing out of padding bytes by GCC is an
implementation detail that we've been relying on, and never something
that was intended as part of the exposed contract? Is there anyone on
this list more qualified to comment on either the specification or
GCC's implementation?

- Nelson

> 
> I think this is unexpected behavior (at least to me), and it's the
> reason I'm writing this post.  Normally, C99 initialization
> automatically zeros out padding bytes as well.  For example:
> 
> ---
> struct test { int a; char b; int c; } arg = {};
> 
> or
> 
> struct test { int a; char b; int c; } arg = { .a = 1 };
> ---
> 
> will set the specified fields, and zero out everything else, including
> padding bytes.  However, if you explicitly initialize every member
> using C99 initialization, the padding bytes won't be zeroed out:
> 
> ---
> struct test { int a; char b; int c; } arg = { .a = 0, .b = 0, .c = 0 };
> ---
> 
> This will leave the padding bytes after "char b" uninitialized,
> surprisingly.  I imagine this is an attempted optimization on gcc, but
> now it's coming back to bite (no pun intended) everyone who relied on
> this construct to prevent leakage.
> 
> Regards,
> Dan

Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.