6 ms·
For the love of POSIX: A more useful way to not segfault from null pointers
- jluxenberg 17y agoI think the author is missing the point of the ksplice article ( http://news.ycombinator.com/item?id=1231961 http://news.ycombinator.com/item?id=1231961 ), which is that you can exploit NULL pointer de-references in the kernel to gain privilege escalation.
- deleted 17y ago[deleted]
- wheels 17y agoThat'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 17y agoSorry, 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 17y agoCan 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 17y agoThe 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 17y agoSo 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.
- xpaulbettsx 17y agoThis was used in several Linux drivers (PPPoE if I recall..?) as an EoP exploit - mmap low addresses, then get the kernel to jump to a null pointer. This is one of the reasons that all addresses <= 0x10000 in Windows NT are invalid, regardless of user/kernel mode.
- meastham 17y agoI 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 17y agoAgreed, 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.
- yan 17y agoFrom 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.
- tptacek 17y agoThe 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 17y agoWhy is catching all the SEGV's more dangerous? What specifically can happen?
- tptacek 17y agoSome 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.
- wheels 17y agoYep, to be clear, this is meant more as an "interesting things you can play with" than a "put this in your application" post. I've never actually implemented this in an app, but had done some more vanilla signal handling and this popped into my head when reading the original article as a fun experiment to bang out.
- sophacles 17y agoSo, 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 17y agoHiding 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.
- sophacles 17y agoUnless of course you are explicitly trying to get around silly things like SIGSEGV because the 0x0 is where the OS keeps interesting things, like say interrupt jump tables...
- senko 17y ago> 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.
- strlen 17y agoThis 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.
- alayne 17y agoWhere's the POSIX? This is bad example code.
- xpaulbettsx 17y agoAs 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 http://support.microsoft.com/kb/976038 for an example. This bug made debugging large applications on x64 a real pain.
- joe_the_user 17y agoWTF, 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.