
For the love of POSIX: A more useful way to not segfault from null pointers - wheels
http://blog.directededge.com/2010/03/31/for-the-love-of-posix-a-more-useful-way-to-not-segfault-from-null-pointers/
======
jluxenberg
I think the author is missing the point of the ksplice article (
<http://news.ycombinator.com/item?id=1231961> ), which is that you can exploit
NULL pointer de-references in the kernel to gain privilege escalation.

~~~
wheels
That's not actually the point of that article; it's the point of their next
one. The linked article basically said nothing about security exploits other
than "they happen and we'll talk about them next time". It's a pretty general
introduction to virtual memory and a way in user space to avoid crashing
dereferencing a null pointer. That said, the post is as much a response to the
title on HN as anything:

 _Dereferencing a NULL pointer always segfaults, right? Not if you're
clever..._

Now, I don't actually know enough about the exploits they're talking about to
know if handling the signal would avoid them or if the null pointer
dereference has to actually be in kernel space and they were just starting
with examples from user space, which was my assumption on the first pass of
reading the article.

~~~
scott_s
Sorry, but the point of the article is clearly not "Here's a useful way to
avoid having null pointer dereferences crash your program." They start out
talking about kernel vulnerabilities in general and the null pointer
dereferences specifically.

~~~
wheels
Can you paste some part where they actually talk about the vulnerability? I
assume that the title quoted above was the original title of the post since
that's what's used on HN and Reddit.

~~~
scott_s
The first two paragraphs clearly talk about it in the context of a security
vulnerability. They don't explain how to exploit the vulnerability, but one
versed in systems programming should either realize what it is, or be able to
easily find it through Google or the pages they referenced in those
paragraphs.

If you Google "linux kernel null pointer exploit" you will find many examples.

~~~
wheels
So you think most people found the post interesting because of the thing that
they're actually going to talk about next time rather than the actual content?

I believe that it's been widely read because of the novelty of avoiding
crashes when dereferencing null pointers; in fact, for anyone who could have
jumped to the conclusions about how the exploit would work, they could have
reduced it to one line: "You can map address 0x0 with mmap and then segfaults
on deferencing null don't happen." All of the rest of the article is only
useful to people _who don't_ know systems programming.

At any rate, I'm not sure that our fundamental disagreement is that wide;
clearly the article is laying down a building block for a later piece on the
security exploit and it was written to serve that purpose. This seems to be
your point. My point is the actual content can stand alone and, in fact does,
and is not about security.

~~~
Locke1689
_So you think most people found the post interesting because of the thing that
they're actually going to talk about next time rather than the actual
content?_

Actually, yes. I posted a comment on the previous article saying so. The
information in the current article is rather trite. The intricacies of kernel
privilege escalation is a different story.

------
tptacek
The problem here is that you've caught all SEGV's, not just the ones from NULL
pointers. That's much more dangerous than trying to be clever about NULL.

You can play games with sigaction and siginfo_t to get around this, but that's
hairier than just mmap'ing.

~~~
timtadh
Why is catching all the SEGV's more dangerous? What specifically can happen?

~~~
tptacek
Some SEGVs will be from dereferencing NULL, which is a fairly innocuous error
(you asked for something from an API and the API said "no"), but many others
will be from derefencing wild pointers.

------
strlen
This is an interesting post, but I have a few points. First, there are certain
kinds of error conditions where it's better to crash (producing a core dump)
and restart rather than "swallow" the condition (even if it's logged). Java
attempted to differentiate in this realm by introducing checked exceptions
(where you could explicitly say this is an error condition where you can and
should recover from, this is an error condition that you might not be able to
recover from), but it hasn't had the intended effect (exceptions are simply
seen as boiler plate and are wrapped in a try { } catch (Exception e) {
logger.error(e); } block; checked exceptions are seen as a mistake).

Null pointers are typically be exactly _such_ errors: e.g., you failed to
allocate memory and malloc returned NULL, you didn't do proper validation on
input or you assumed a key exists in a hash table when it doesn't. Either
assumption that pointer is not NULL is an invariant (in which case it's better
_to crash_ and leave a core dump), or it's not (in which case the application
should do a check for a null pointer).

It's also _not_ advised to do complex processing inside signal handlers: the
idea is to perform a single atomic operation in a signal handler (e.g., change
an integer from 0 to 1), and let the application examine that operation's side
effects. For example, there could be a "should_quit" integer which when 1
would mean the event loop should terminate and the signal handler would just
set that integer to 1.

------
yan
From the article being ranted about: " _Next time, we’ll look at how a process
can not only map NULL in its own address space, but can also create mappings
in the kernel’s address space. And, I’ll show you how this lets an attacker
use a NULL dereference in the kernel to take over the entire machine. Stay
tuned!_ "

So it's not really about handling NULL ptr derefs, but exploiting them.

------
sophacles
So, catching SIGSEGV is still a segfault! It is not fatal, so in that sense
sure you aren't segfaulting, but the error still occurs, the signal is still
generated, and you still don't actually dereference NULL. In the other article
there is no error, SIGSEGV is not generated, and therefore there is no
segfault at all. They are fundamentally different.

~~~
jetsnoc
Hiding the error does not mean that the error did not occur or that it is not
a problem.. It was about to occur and there is still a fundamental problem in
your logic leading up to the would-have-been segfault that was swept under the
rug.

I would much rather know where my code tried to access a null memory space and
what/why/how a null pointer was passed than to have it "fake" that it didn't
ever happen! A signal handler for a SIGSEGV/SIGBUS is a great place to add a
syslog() so you can find the error in your logic and correct it.

~~~
senko
> Hiding the error does not mean that the error did not occur or that it is
> not a problem.. It was about to occur and there is still a fundamental
> problem in your logic leading up to the would-have-been segfault that was
> swept under the rug.

It's an error only if you didn't want to dereference address 0. If you know
it's safe and useful to do so on the system for which you're developing, why
shouldn't you be able to do it?

As the KSplice article shows, on Linux (under specific setup which is not the
default), you can actually have something mapped there. I'd be hard pressed to
invent a convincable scenario in which you would _want_ to do it, but that
doesn't mean there is none.

------
xpaulbettsx
As I mention on his blog post, both of these tactics are inherently evil and
can result in security vulnerabilities, since the attacker now can keep trying
memory addresses until he succeeds, which defeats ASLR for one.

It will also turn an easy-to-debug SIGSEGV into a horrible-to-debug memory
corruption; check out <http://support.microsoft.com/kb/976038> for an example.
This bug made debugging large applications on x64 a _real_ pain.

------
meastham
I don't think the ksplice article was really about a way to "not segfault"
from dereferencing a null pointer, but this ended up being a nice, short
exposition on handling signals anyway.

~~~
waratuman
Agreed, the code was a clear example of how to handle signals. I could
understand it even though I haven't even dealt with signals before.

------
alayne
Where's the POSIX? This is bad example code.

------
joe_the_user
WTF,

You _should_ get an error condition from dereferencing a null. When you're
debugging your code, that error condition should be nice and verbose. Once
you're shipping, that error condition should be very short and simple and
should almost never occur. Trust me, your customers will not help you debug
your code.

Test Driven Development and Design By Contract AND traditional software
engineering all agree - FAIL EARLY AND OFTEN in your test suite to avoid later
bugs. It is WRONG to let errors float around in your program logic, WRONG.

I went from C++ to Rails and back to C++. Is Rails reasoning trying to seep
into C++? HELL NO!, The C-parts of C++ are serious and won't stand for this
shit.

