glibc segfault on "special" long double values is _ok_!?

classic Classic list List threaded Threaded
49 messages Options
123
Reply | Threaded
Open this post in threaded view
|

glibc segfault on "special" long double values is _ok_!?

Jim Meyering
Hi Andreas,

Did you mean to close this bug as "resolved/invalid"?

    printf crashes on some 'long double' values
    http://sourceware.org/bugzilla/show_bug.cgi?id=4586
    [BTW, it segfaults on i686 rawhide, even with no compiler options]

I'm interested, because I don't want my applications to segfault on such
inputs.  Sure it may look a little far-fetched, but I think it's not.
Imagine such a bit pattern being injected into a network data stream
that is then printed as a long double.  Just printing an arbitrary
"long double" should not make a server vulnerable to a DoS attack.

If glibc were to stay this way, I would feel obliged to make applications
I care about pull in the gnulib replacement printf infrastructure even
when my system provides the latest glibc.  That would be a shame.

It may well be that the current glibc behavior is not prohibited by
any standard, but I think that "quality of implementation" concerns
(not to mention a desire for robustness and security) would dictate a
more manageable result.

Jim
Reply | Threaded
Open this post in threaded view
|

Re: glibc segfault on "special" long double values is _ok_!?

Andreas Schwab
Jim Meyering <[hidden email]> writes:

> I'm interested, because I don't want my applications to segfault on such
> inputs.  Sure it may look a little far-fetched, but I think it's not.
> Imagine such a bit pattern being injected into a network data stream
> that is then printed as a long double.  Just printing an arbitrary
> "long double" should not make a server vulnerable to a DoS attack.

In which way is this different from passing NULL to strlen?

Andreas.

--
Andreas Schwab, SuSE Labs, [hidden email]
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."
Reply | Threaded
Open this post in threaded view
|

Re: glibc segfault on "special" long double values is _ok_!?

Jim Meyering
Andreas Schwab <[hidden email]> wrote:
> Jim Meyering <[hidden email]> writes:
>
>> I'm interested, because I don't want my applications to segfault on such
>> inputs.  Sure it may look a little far-fetched, but I think it's not.
>> Imagine such a bit pattern being injected into a network data stream
>> that is then printed as a long double.  Just printing an arbitrary
>> "long double" should not make a server vulnerable to a DoS attack.
>
> In which way is this different from passing NULL to strlen?

I'm surprised to hear you arguing that it is desirable for glibc's printf
implementation to segfault for a long-double with an unusual bit pattern.
Reply | Threaded
Open this post in threaded view
|

Re: glibc segfault on "special" long double values is _ok_!?

Andreas Schwab
Jim Meyering <[hidden email]> writes:

> Andreas Schwab <[hidden email]> wrote:
>> Jim Meyering <[hidden email]> writes:
>>
>>> I'm interested, because I don't want my applications to segfault on such
>>> inputs.  Sure it may look a little far-fetched, but I think it's not.
>>> Imagine such a bit pattern being injected into a network data stream
>>> that is then printed as a long double.  Just printing an arbitrary
>>> "long double" should not make a server vulnerable to a DoS attack.
>>
>> In which way is this different from passing NULL to strlen?
>
> I'm surprised to hear you arguing that it is desirable for glibc's printf
> implementation to segfault for a long-double with an unusual bit pattern.

In which way is this different from printf("%s", (char*)1)?

Andreas.

--
Andreas Schwab, SuSE Labs, [hidden email]
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."
Reply | Threaded
Open this post in threaded view
|

Re: glibc segfault on "special" long double values is _ok_!?

John Haxby-2
Andreas Schwab wrote:
>> I'm surprised to hear you arguing that it is desirable for glibc's printf
>> implementation to segfault for a long-double with an unusual bit pattern.
>>    
>
> In which way is this different from printf("%s", (char*)1)?
>  
In that it doesn't dereference a pointer?  You can say that, yes, it's a
valid pointer and you can do things like pointer arithmetic with it in
the same way that the odd long-double values are valid in that you can
do long-double operations with them and by that token there's no need
for printf() to behave itself.  On the other hand, you can pass those
odd long-double values to, say, sqrt() and they'll not crash either (I'm
guessing) whereas something that doesn't point to a null-terminated
sequence of bytes will likely make strlen() crash.

I may be naïve here, but I don't think it's meaningful to compare the
behaviour of bad pointers to the behaviour of strangelong-double
numbers.  I'm saying you're wrong, but I don't think that there's a
strong case for drawing that parallel -- in particular it seems rather
odd to me that one would have to test any sort of number to make sure
that it's printable.

jch
Reply | Threaded
Open this post in threaded view
|

Re: glibc segfault on "special" long double values is _ok_!?

Jim Meyering
In reply to this post by Andreas Schwab
Andreas Schwab <[hidden email]> wrote:

> Jim Meyering <[hidden email]> writes:
>
>> Andreas Schwab <[hidden email]> wrote:
>>> Jim Meyering <[hidden email]> writes:
>>>
>>>> I'm interested, because I don't want my applications to segfault on such
>>>> inputs.  Sure it may look a little far-fetched, but I think it's not.
>>>> Imagine such a bit pattern being injected into a network data stream
>>>> that is then printed as a long double.  Just printing an arbitrary
>>>> "long double" should not make a server vulnerable to a DoS attack.
>>>
>>> In which way is this different from passing NULL to strlen?
>>
>> I'm surprised to hear you arguing that it is desirable for glibc's printf
>> implementation to segfault for a long-double with an unusual bit pattern.
>
> In which way is this different from printf("%s", (char*)1)?

Posing the question for printf("%s", NULL) wouldn't have made
the same point, Eh?

Just because standards leave it undefined doesn't mean
that "segfault" is the best response -- or even a "good" one.
Standards conformance is obviously not the issue here.
Reply | Threaded
Open this post in threaded view
|

Re: glibc segfault on "special" long double values is _ok_!?

Andreas Schwab
Jim Meyering <[hidden email]> writes:

> Andreas Schwab <[hidden email]> wrote:
>> Jim Meyering <[hidden email]> writes:
>>
>>> Andreas Schwab <[hidden email]> wrote:
>>>> Jim Meyering <[hidden email]> writes:
>>>>
>>>>> I'm interested, because I don't want my applications to segfault on such
>>>>> inputs.  Sure it may look a little far-fetched, but I think it's not.
>>>>> Imagine such a bit pattern being injected into a network data stream
>>>>> that is then printed as a long double.  Just printing an arbitrary
>>>>> "long double" should not make a server vulnerable to a DoS attack.
>>>>
>>>> In which way is this different from passing NULL to strlen?
>>>
>>> I'm surprised to hear you arguing that it is desirable for glibc's printf
>>> implementation to segfault for a long-double with an unusual bit pattern.
>>
>> In which way is this different from printf("%s", (char*)1)?
>
> Posing the question for printf("%s", NULL) wouldn't have made
> the same point, Eh?

You still did not answer my questions.

Andreas.

--
Andreas Schwab, SuSE Labs, [hidden email]
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."
Reply | Threaded
Open this post in threaded view
|

Re: glibc segfault on "special" long double values is _ok_!?

Jim Meyering
Andreas Schwab <[hidden email]> wrote:

> Jim Meyering <[hidden email]> writes:
>
>> Andreas Schwab <[hidden email]> wrote:
>>> Jim Meyering <[hidden email]> writes:
>>>
>>>> Andreas Schwab <[hidden email]> wrote:
>>>>> Jim Meyering <[hidden email]> writes:
>>>>>
>>>>>> I'm interested, because I don't want my applications to segfault on such
>>>>>> inputs.  Sure it may look a little far-fetched, but I think it's not.
>>>>>> Imagine such a bit pattern being injected into a network data stream
>>>>>> that is then printed as a long double.  Just printing an arbitrary
>>>>>> "long double" should not make a server vulnerable to a DoS attack.
>>>>>
>>>>> In which way is this different from passing NULL to strlen?
>>>>
>>>> I'm surprised to hear you arguing that it is desirable for glibc's printf
>>>> implementation to segfault for a long-double with an unusual bit pattern.
>>>
>>> In which way is this different from printf("%s", (char*)1)?
>>
>> Posing the question for printf("%s", NULL) wouldn't have made
>> the same point, Eh?
>
> You still did not answer my questions.

[ off-topic debate games...

    In a way, I did answer them by talking about undefined behavior,
    which is what they all evoke.  However, I avoided answering
    directly because the actual answers are not relevant, since as I
    said from the start, this is a quality of implementation issue,
    and has no bearing on conformance.

    If I had said this was a bug, or that this behavior made glibc
    non-conforming (to some standard), then your questions would have
    been perfectly relevant, and would have put me firmly in my place
    for making what would have amounted to a false accusation.
    However, I did neither of those things.
]

I just want to be able to write robust code, and if glibc doesn't
provide the tools to do that, then I think it's fair to expect a
change, or at least an explanation for why change is not possible.

So, would you argue that robust code must first ensure each
arbitrary-bit-pattern long double is valid before printing it?
Obviously, that is required now, given glibc's current behavior, but
should it be required forever?  If so, this should be documented,
along with a description of how to detect the offending values.
The fpclassify macro cannot be used, because it declares the
offending value to be FP_NORMAL.  Application code should not have
to limit itself to printing only values for which isnanl returns 0.

My original point is that this bug report deserves more than
a summary dismissal:

    http://sourceware.org/bugzilla/show_bug.cgi?id=4586

At the very least, it deserves an explanation of why a segfault should
remain glibc/printf's response to an invalid long double bit pattern.

But glibc deserves better than that.
Reply | Threaded
Open this post in threaded view
|

Re: glibc segfault on "special" long double values is _ok_!?

James Youngman-5
In reply to this post by Andreas Schwab
On 6/6/07, Andreas Schwab <[hidden email]> wrote:
> Jim Meyering <[hidden email]> writes:
>
> > I'm interested, because I don't want my applications to segfault on such
> > inputs.  Sure it may look a little far-fetched, but I think it's not.
> > Imagine such a bit pattern being injected into a network data stream
> > that is then printed as a long double.  Just printing an arbitrary
> > "long double" should not make a server vulnerable to a DoS attack.
>
> In which way is this different from passing NULL to strlen?

If I read a stream of data (from a file, a network socket, etc.) which
is supposed to contain valid floating-point data, it is reasonable for
a program to print it.  Especially so if the printing I am doing is a
for diagnostic logging.  For example, in the case where a program
seems to behave oddly with a certain input, it is reasonable for the
invoking user to turn up the verbosity of diagnostic messages.   So
there will be some statements in applications which preferentially
invoke printf-family functions on dubious data.

What the program is doing here is under the control of the program
author.  What the data stream contains is under the control of the
user, modulo lossage caused by user error and faulty hardware.  Faulty
hardware is perfectly capable of injecting random bit corruption into
(for example) a TCP data stream, undetected.  (That is, undetected by
both the TCP checksum and the CRCs on the Ethernet frames).

Summary - the application author can reasonably write their program
under the assumption that a data set is of a certain type, but the
world is a sufficiently complex place that sometimes the data can be
corrupted or of an unexpected nature.

Contrariwise, the same consideration doesn't really apply to passing
NULL to strlen.  For that to happen, the application essentially needs
to contain a logic error (for example a code path in which a pointer
is used before being assigned to the address of an allocated buffer).
 That's a different type of failure; it's a problem within the program
itself, not with the environment in which the program is operating.

Robust programs need to be able to detect and report problems with
their environment and their input.

James.
Reply | Threaded
Open this post in threaded view
|

Re: glibc segfault on "special" long double values is _ok_!?

Paul Mackerras
In reply to this post by Andreas Schwab
Andreas Schwab writes:

> Jim Meyering <[hidden email]> writes:
>
> > I'm interested, because I don't want my applications to segfault on such
> > inputs.  Sure it may look a little far-fetched, but I think it's not.
> > Imagine such a bit pattern being injected into a network data stream
> > that is then printed as a long double.  Just printing an arbitrary
> > "long double" should not make a server vulnerable to a DoS attack.
>
> In which way is this different from passing NULL to strlen?

In that long doubles are scalar values while strlen's argument is a
pointer value.  In general with scalars there is no value whose
meaning or effect is undefined, unlike pointers.

If glibc can indeed be made to segfault just by doing printf on some
particular long double value then I think that is worth reporting as a
security vulnerability.

Paul.
Reply | Threaded
Open this post in threaded view
|

Re: glibc segfault on "special" long double values is _ok_!?

Andreas Schwab
Paul Mackerras <[hidden email]> writes:

> In general with scalars there is no value whose meaning or effect is
> undefined, unlike pointers.

This is not true.

Andreas.

--
Andreas Schwab, SuSE Labs, [hidden email]
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."
Reply | Threaded
Open this post in threaded view
|

Re: glibc segfault on "special" long double values is _ok_!?

Ulrich Drepper
In reply to this post by Paul Mackerras
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Stop this nonsense discussion.  Intel's IA-64 people (and I smell HP in
there) are the idiots who caused this.  Talk to them.  If the work
around wouldn't be as simple as Jakub suggested I'd leave it as is.
Garbage in, whatever out, including crashes.  The numbers are completely
invalid and cannot happen in a regular program with a correct
implementation.  Here it's the implementation of the processor which is
at fault.  Neither CPU nor kernel bugs will be worked around if it's
expensive.  Just don't use those OS and processor versions if it bothers
you.

- --
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)

iD8DBQFGZ0LC2ijCOnn/RHQRAgb1AJ4lsvX5Y0+SMI+n6aWjNOlYhPxUegCdFqFw
U/edo9EcRfHH62XpKundF+4=
=OG+c
-----END PGP SIGNATURE-----
Reply | Threaded
Open this post in threaded view
|

Re: glibc segfault on "special" long double values is _ok_!?

Bruno Haible
In reply to this post by Andreas Schwab
Andreas Schwab asked:
> In which way is this different from printf("%s", (char*)1)?

The elementary operations on strings (strlen etc.) crash on (char*)1 too,
therefore one cannot blame 'printf' in particular in the string case.

The elementary operations on long doubles (==, +, isnanl, etc.) produce
no SIGSEGV; in the default settings they do not even produce a SIGFPE.
But 'printf' gives a SIGSEGV.

Bruno

Reply | Threaded
Open this post in threaded view
|

Re: glibc segfault on "special" long double values is _ok_!?

Bruno Haible
In reply to this post by Andreas Schwab
Andreas Schwab wrote:
> > Just printing an arbitrary
> > "long double" should not make a server vulnerable to a DoS attack.
>
> In which way is this different from passing NULL to strlen?

Common knowledge: Programmers know that NULL is an invalid value for
many operations. They usually don't know that there are invalid values
in the 'long double' data type (unlike the 'float' and 'double' data
types).

Bruno

Reply | Threaded
Open this post in threaded view
|

Re: glibc segfault on "special" long double values is _ok_!?

Bruno Haible
In reply to this post by Ulrich Drepper
Ulrich Drepper wrote:
> Intel's IA-64 people (and I smell HP in there) are the idiots who caused this.

The crash also occurs on i386 platforms, e.g. CPUs built by AMD.

> Here it's the implementation of the processor which is at fault.

But printf %Le does not do any hardware floating-point instruction except
those in glibc's __isnanl and __isinfl functions: __mpn_extract_long_double
extracts the bits using integer arithmetic.

> Neither CPU nor kernel bugs will be worked around if it's expensive.

Do you find that Jakub's added 4 lines of code are "expensive"?

> Just don't use those OS and processor versions if it bothers you.

Right. Don't use i386, x86_64, and ia64. What machine are you using?

Bruno

Reply | Threaded
Open this post in threaded view
|

Re: glibc segfault on "special" long double values is _ok_!?

Ulrich Drepper
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Bruno Haible wrote:
> The crash also occurs on i386 platforms, e.g. CPUs built by AMD.

Bullshit.  Those CPU never produce such numbers.

- --
➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)

iD8DBQFGZ2yy2ijCOnn/RHQRAoL1AJ9nSmjSXGC7JoOBVIl/gUxh7Aos+wCgmBvE
WWWjRjBy7IcVFGY/KE6OADc=
=NwJm
-----END PGP SIGNATURE-----
Reply | Threaded
Open this post in threaded view
|

Re: glibc segfault on "special" long double values is _ok_!?

Jan-Benedict Glaw
In reply to this post by James Youngman-5
On Wed, 2007-06-06 22:44:17 +0100, James Youngman <[hidden email]> wrote:
> If I read a stream of data (from a file, a network socket, etc.) which
> is supposed to contain valid floating-point data, it is reasonable for
> a program to print it.  Especially so if the printing I am doing is a

Data you didn't compute yourself isn't supposed to contain anything
known. Each and every bit may contain something you didn't expect,
that's why you have to do input checking.

The most you can do with your externally fetched data is printing it
out, byte by byte, in hex. "Assuming" that this'll make up any
well-known data formats is just asking for trouble.

MfG, JBG

--
      Jan-Benedict Glaw      [hidden email]              +49-172-7608481
Signature of:               http://www.eyrie.org/~eagle/faqs/questions.html
the second  :

signature.asc (196 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: glibc segfault on "special" long double values is _ok_!?

Jakub Jelinek
On Thu, Jun 07, 2007 at 12:10:26PM +0200, Jan-Benedict Glaw wrote:

> On Wed, 2007-06-06 22:44:17 +0100, James Youngman <[hidden email]> wrote:
> > If I read a stream of data (from a file, a network socket, etc.) which
> > is supposed to contain valid floating-point data, it is reasonable for
> > a program to print it.  Especially so if the printing I am doing is a
>
> Data you didn't compute yourself isn't supposed to contain anything
> known. Each and every bit may contain something you didn't expect,
> that's why you have to do input checking.
>
> The most you can do with your externally fetched data is printing it
> out, byte by byte, in hex. "Assuming" that this'll make up any
> well-known data formats is just asking for trouble.

Passing long doubles in binary form can't be portable, there are just way
too many different formats, endianity etc. (IEEE 754 double, quad, IEEE 854
extended double, the same with Intel extensions, IBM long double format
to name just a few, in many cases with various endian encodings and
sometimes with different padding).  Using text representation (best
the ISO C99 hexadecimal float format) is much wiser.

        Jakub
Reply | Threaded
Open this post in threaded view
|

Re: glibc segfault on "special" long double values is _ok_!?

Jeremy Linton
In reply to this post by Jim Meyering


> It may well be that the current glibc behavior is not prohibited by
> any standard, but I think that "quality of implementation" concerns
> (not to mention a desire for robustness and security) would dictate a
> more manageable result.

        Your right, it would seem that if its possible to make a fix that
avoids a crash, even when that crash is caused by incorrect behavior in
the application, its the right thing to do. I do it all the time in our
application in response to user errors, hardware errors, other library
programming errors. Frankly, in our application any crash is
unacceptable.  Apparently that level of quality isn't a requirement for
glibc. I understand that its impossible to close all the holes but when
its an easy fix, I simply don't understand why the library cannot do it
instead of having every application vendor have to provide wrappers
around glibc functions to assure that error conditions that should be
caught by the library are caught and handled before calling the library.
  The current stance just makes glibc appear brittle.



        From monitoring this mailing list for a while it appears apparent that
certain people pride themselves in rejecting any patch which improves
the robustness of glibc.

Reply | Threaded
Open this post in threaded view
|

Re: glibc segfault on "special" long double values is _ok_!?

Mike Frysinger
In reply to this post by Jan-Benedict Glaw
On Thursday 07 June 2007, Jan-Benedict Glaw wrote:
> On Wed, 2007-06-06 22:44:17 +0100, James Youngman <[hidden email]> wrote:
> > If I read a stream of data (from a file, a network socket, etc.) which
> > is supposed to contain valid floating-point data, it is reasonable for
> > a program to print it.  Especially so if the printing I am doing is a
>
> Data you didn't compute yourself isn't supposed to contain anything
> known. Each and every bit may contain something you didn't expect,
> that's why you have to do input checking.

yes, but the question is where do the robustness checks live ... every single
application out there or glibc ?  consider a game transmitting/receiving
floating point data over the network and logging the results ... should the
game assume that the library isnt going to crash when feeding values into
printf() or need it check every value itself ?
-mike

signature.asc (844 bytes) Download Attachment
123