Deutsch   English   Français   Italiano  
<87il1f1ie2.fsf@nosuchdomain.example.com>

View for Bookmarking (what is this?)
Look up another Usenet article

Path: eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Keith Thompson <Keith.S.Thompson+u@gmail.com>
Newsgroups: comp.lang.c
Subject: Re: A Famous Security Bug
Date: Thu, 21 Mar 2024 12:42:29 -0700
Organization: None to speak of
Lines: 85
Message-ID: <87il1f1ie2.fsf@nosuchdomain.example.com>
References: <bug-20240320191736@ram.dialup.fu-berlin.de>
	<20240320114218.151@kylheku.com>
	<20240321211306.779b21d126e122556c34a346@gmail.moc>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Info: dont-email.me; posting-host="0bf58c5e3e50115de10475b5e7b86fc1";
	logging-data="2532317"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX19guZPEpbD+tNfuRHCiNdwi"
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux)
Cancel-Lock: sha1:UVJTjP+V4zbs4q2eDVKwKfytHBk=
	sha1:Qm2e65Z+EfLOLBhy5N59JMALyro=

Anton Shepelev <anton.txt@gmail.moc> writes:
> Kaz Kylheku to Stefan Ram:
>
>> > >   A "famous security bug":
>> > >
>> > > void f( void )
>> > > { char buffer[ MAX ];
>> > >   /* . . . */
>> > >   memset( buffer, 0, sizeof( buffer )); }
>> > >
>> > >   . Can you see what the bug is?
>>
>> I don't know about "the bug", but conditions can be
>> identified under which that would have a problem
>> executing, like MAX being in excess of available automatic
>> storage.
>>
>> If the /*...*/ comment represents the elision of some
>> security sensitive code, where the memset is intended to
>> obliterate secret information, of course, that
>> obliteration is not required to work.
>>
>> After the memset, the buffer has no next use, so the all
>> the assignments performed by memset to the bytes of buffer
>> are dead assignments that can be elided.
>>
>> To securely clear memory, you have to use a function for
>> that purpose that is not susceptible to optimization.
>
> I think this behavior (of a C compiler) rather stupid.  In a
> low-level imperative language, the compiled program shall
> do whatever the programmer commands it to do.  If he
> commands it to clear the buffer, it shall clear the buffer.
> This optimisation is too high-level, too counter-inituitive,
> even deceitful.  The optimiser is free to perform the task
> in the fastest manner possible, but it shall not ignore the
> programmer's order to zero-fill the buffer, especially
> without emitting a warning about (potentially!) redundant
> code, which it is the programmer's reponsibility to confirm
> and remove.
>
> Redundant code shall be dealt with in the source, rather than
> in the executable.

Then C is not what you call a "low-level imperative language", and none
of your "shall"s apply to the language defined by the ISO C standard.

C programs define behavior, not generated machine code.  If an
implementation can implement the behavior of a C program with a memset()
call without invoking memset(), it's free to do so.

The programmer's intent in the code snippet that started this thread was
for the memset call to erase sensitive data in memory that, after the
function returns, is not part of any object.  C (prior to C23) doesn't
provide a way to do that.  Any program whose observable behavior differs
depending on whether that memory was cleared has undefined behavior.

Judicious use of "volatile" should avoid the problem.

5.1.2.3p6:

    The least requirements on a conforming implementation are:

    - Volatile accesses to objects are evaluated strictly according 
      to the rules of the abstract machine.

    - At program termination, all data written into files shall be
      identical to the result that execution of the program according 
      to the abstract semantics would have produced.

    - The input and output dynamics of interactive devices shall take
      place as specified in 7.23.3.  The intent of these requirements 
      is that unbuffered or line-buffered output appear as soon as
      possible, to ensure that prompting messages appear prior to a
      program waiting for input.

    This is the *observable behavior* of the program.

If you think that's stupid, I won't try to change your mind, but the
meaning is clear.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Medtronic
void Void(void) { Void(); } /* The recursive call of the void */