×

Welcome to the Slashdot Beta site -- learn more here. Use the link in the footer or click here to return to the Classic version of Slashdot.

Thank you!

Before you choose to head back to the Classic look of the site, we'd appreciate it if you share your thoughts on the Beta; your feedback is what drives our ongoing development.

Beta is different and we value you taking the time to try it out. Please take a look at the changes we've made in Beta and  learn more about it. Thanks for reading, and for making the site better!

New Linux Kernel Flaw Allows Null Pointer Exploits

Soulskill posted more than 4 years ago | from the recipe-for-fun dept.

Security 391

Trailrunner7 writes "A new flaw in the latest release of the Linux kernel gives attackers the ability to exploit NULL pointer dereferences and bypass the protections of SELinux, AppArmor and the Linux Security Module. Brad Spengler discovered the vulnerability and found a reliable way to exploit it, giving him complete control of the remote machine. This is somewhat similar to the magic that Mark Dowd performed last year to exploit Adobe Flash. Threatpost.com reports: 'The vulnerability is in the 2.6.30 release of the Linux kernel, and in a message to the Daily Dave mailing list Spengler said that he was able to exploit the flaw, which at first glance seemed unexploitable. He said that he was able to defeat the protection against exploiting NULL pointer dereferences on systems running SELinux and those running typical Linux implementations.'"

cancel ×
This is a preview of your comment

No Comment Title Entered

Anonymous Coward 1 minute ago

No Comment Entered

391 comments

Linux More Secure than Windows? (-1, Troll)

Anonymous Coward | more than 4 years ago | (#28739911)

You betcha!

Linus, you Rookie !! (-1)

Anonymous Coward | more than 4 years ago | (#28740127)

Who but a rookie does this in a kernel? Cut and paste kernel soruces is not a good idea, Linus, you rookie !!

Re:Linus, you Rookie !! (4, Informative)

luca (6883) | more than 4 years ago | (#28740965)

Ok, I know I shouldn't be feeding the troll, but read the article: the kernel source itself is perfectly fine, is the compiler that optimizes the check away.

Fast! leave the sinking Ship! (0, Funny)

Anonymous Coward | more than 4 years ago | (#28739915)

Fast! leave the sinking Ship before its too late!

Double standards (1, Insightful)

Anonymous Coward | more than 4 years ago | (#28739929)

If this had been Windows, the article would have been tagged defectivebydesign.

Re:Double standards (-1, Flamebait)

Anonymous Coward | more than 4 years ago | (#28739955)

Wrong, this exploit isn't what you think it is. It only works when you run with setuid. Go look that up moron.

DRM is defective by design. (4, Informative)

BPPG (1181851) | more than 4 years ago | (#28739967)

I think that tag is mostly reserved for DRM related news...

And I have seen news about linux DRM modules also tagged that.

Re:DRM is defective by design. (1, Offtopic)

calmofthestorm (1344385) | more than 4 years ago | (#28740059)

...you mean the direct rendering module or proprietary modules that some evil vender installs? I don't know of any digital restrictions management kernel modules but wouldn't be that surprised if they existed.

I remember freaking out the first time I noticed the DRM module loading when I came over the Tux's loving embrace years ago.

Re:Double standards (4, Informative)

Anonymous Coward | more than 4 years ago | (#28739977)

Thats because with Windows, no one would be able to marvel at how un-obvious the flaw is. According to The Register, the kernel actually has gaurds in place against just this type of valnerability, but the complier optimized them out during compiling. IMHO this makes this flaw a very good case study, even with security in place, you cannot really trust the compiler. (actually, this flaw apparently only occurs if security is in place... or if you use PulseAudio (in which case, you deserve it!)).

Re:Double standards (3, Insightful)

Shinobi (19308) | more than 4 years ago | (#28740009)

And yet comp sci trash wonder why some of us actually learn assembler, and don't blindly trust compilers and libraries.

Re:Double standards (0, Flamebait)

Anonymous Coward | more than 4 years ago | (#28740037)

The language is called Assembly. An assembler assembles assembly code into machine code.

Re:Double standards (1)

calmofthestorm (1344385) | more than 4 years ago | (#28740085)

Blind trust is not necessary for this to be an issue. NO ONE has time to write all their code in assembly, not even for the kernel. This is arguably more of an issue in the compiler than in the kernel, and if you honestly claim you can write a C compiler without learning assembly...yeah.

Better retort: Which dialect?

Re:Double standards (5, Informative)

mortonda (5175) | more than 4 years ago | (#28740195)

This is arguably more of an issue in the compiler than in the kernel,

Not completely... from the SANS Storm Center [sans.org] , the code was as follows:


struct sock *sk = tun->sk; // initialize sk with tun->sk

if (!tun)
        return POLLERR; // if tun is NULL return error

The error was that the compiler optimized away the if statement, assuming that tun had already been initialized. The check should have been placed before the sock variable referenced it. Not entirely obvious maybe, but then again, it should have been checked before the assignment.

I really don't see how this is a compiler problem? (4, Insightful)

gbutler69 (910166) | more than 4 years ago | (#28740793)

To me, the "if (!tun)" check should/must be before the de-reference; otherwise, it is meaningless! However, the compiler should print a warning in this case, not just optimize it away.

Re:Double standards (1, Informative)

jelle (14827) | more than 4 years ago | (#28740953)

The check is not placed wrong, it should be safe as long as *sk isn't used before the check. The *sk assignment does not dereference to a memory location, it does nothing more than adding an offset to the other pointer: ((int)sk - (int)tun) is the offset of sk in 'struct sock'.

The compiler is wrong in assuming tun is always non-NULL at that point in the code.

It's certainly a compiler bug, it's the same as optimizing the 'if (!tun)' out of this code:


const int sk_off = 123;
int func(int tun)
{
    int sk = tun + sk_off;

    if (!tun) return -1;
    return sk;
}

Re:Double standards (3, Insightful)

Shinobi (19308) | more than 4 years ago | (#28740647)

I never said anything about writing everything in it. But many of us with proficiency in it tend to check what the compiler actually outputs, because we know that the compiler is not smarter than the human who wrote it is. (A behaviour further reinforced by the two smelly piles of fecal matter that are MSVC and GCC). This is also why many of us don't blindly trust optimizations to the compiler either, and always double-check. A disassembler is also useful for tearing through critical pieces of code to see if the compiler has built it in the way you intended.

I've removed quite a few obscure but potentially very nasty bugs in my software by doing that. Then again, I'm a freelancer, I live by my reputation for solid, fault-free code.

Re:Double standards (1)

Vintermann (400722) | more than 4 years ago | (#28740583)

Yeah right, I'm sure you macho-hacker trash can write hand-crafted assembly that is safer than GCC. And I'm sure the guy who found out about this doesn't have a comp sci background at all. Everyone knows it's the hackers that find the real stuff!

Re:Double standards (4, Interesting)

Shinobi (19308) | more than 4 years ago | (#28740721)

Sure. My last entire project has been specifically about that. Been working on a piece of software to go onto an embedded device with deterministic behaviour, with the hardware specs being 32kiBiByte RAM, no cache, 8MHz processor.

Most people I am forced to work with who have a comp sci degree are unable to work under such conditions. On the other hand, EE's and comp.eng graduates tend to be very nice to work with on such projects.

Re:Double standards (1)

Fweeky (41046) | more than 4 years ago | (#28740451)

In my tests, gcc only optimizes out null checks at -O3 or above, which is already known to make potentially unsafe optimizations. Maybe if -Wunreachable-code were part of -Wall it would have been easier to spot.

Re:Double standards (1)

ld a,b (1207022) | more than 4 years ago | (#28740637)

GCC "optimizations" are one of the main reasons OpenBSD specifically is looking forward to replace it with PCC.
When optimizations keep you from knowing what a program will do, they have gone too far.

Re:Double standards (2, Insightful)

Anonymous Coward | more than 4 years ago | (#28739981)

If this had been Windows we'd find out 9 months later after the guy who discovered it informed Microsoft, they stick their fingers up their butt for 3 months. Microsoft would then spend 3 months finding that the code they used to fix the problem (which was copied from a dll they wrote in 2005) causes problems in newer versions of Excel because it uses null pointers to calculate file bloat or something. Then they threaten him with lawsuits for a few months if he releases the information. In a rush to release a fix MS uses a newer bit of code that breaks all versions of Excel because they really dont need another reason for people not to upgrade.

The end result of which is that MS releases a fix mere days after the flaw is "announced".

The Excel bug goes unfixed for 4 years because its a low priority and nobody has found a way to exploit it yet.

Re:Double standards (1, Insightful)

bschorr (1316501) | more than 4 years ago | (#28740593)

How stereotypically /. is this? We have a story about a security flaw in Linux and it somehow turns into a Microsoft-bashing session.

Re:Double standards (2, Insightful)

Pvt_Ryan (1102363) | more than 4 years ago | (#28740597)

To be fair if it was windows we'd never know which bit of the code was exploitable or why just that there was an exploit after all we cant SEE their source.

Good news is that this will be fixed in 2.30.2 in the next month instead of left to be fixed in windows 2012 if ever...

Re:Double standards (0, Insightful)

Anonymous Coward | more than 4 years ago | (#28739987)

Your post will get modded insightful pretty quick even though it's just a dirty trick similar to "oh gosh, I know I'll get mod down for this but".
Look at the number of positive comments regarding the latest build of windows 7 and compare them to the latest linux kernel. They just don't stack up.
Either slashdotters don't run linux anymore, or windows actually grown to a nice product. Either way, stop living in the past.

Re:Double standards (0, Troll)

Dunbal (464142) | more than 4 years ago | (#28740129)

Either slashdotters don't run linux anymore, or windows actually grown to a nice product.

OR, Microsoft has a team of paid shills with several slashdot accounts each to "adjust" moderation in their favor and flame anyone who dares say anything about THAT PIECE OF SHIT SOFTWARE COMPANY we call Microsoft.

Re:Double standards (0, Flamebait)

Hubbell (850646) | more than 4 years ago | (#28740189)

For such a piece of shit company, they sure do have a lot more marketshare than the computing godOS known as Linux.

Re:Double standards (0)

Anonymous Coward | more than 4 years ago | (#28740247)

In the server market? Thanks for playing.

Re:Double standards (3, Insightful)

gilgongo (57446) | more than 4 years ago | (#28740317)

For such a piece of shit company, they sure do have a lot more marketshare than the computing godOS known as Linux.

Microsoft's current market share has nothing to do with quality, and everything to do with monopoly. It doesn't matter whether their product is any good or not, because not only do the vast majority of computer users not even know what Windows is, they wouldn't have the first clue what an alternative to Windows or MS Office would be like.

Time to learn about basic economic theory [wikipedia.org] I think.

Re:Double standards (2, Insightful)

Shamenaught (1341295) | more than 4 years ago | (#28740739)

Well, Microsoft got that market share by providing cheap software, specifically DOS. It was arguably of low quality, but who cares that much about the quality if it's cheap, right?

I don't know if it was originally the plan, but at some point along the way Microsoft realized they had a monopoly. They leveraged their share by putting up prices and using FUD tactics to discourage people from switching. The main issue I have is that although the prices went up, the comparative quality of software didn't. Sure, It looks a lot better than DOS, but that's because modern computers are practically supercomputers compared to what DOS ran on. So you see, having a large market share doesn't mean the company isn't a piece of shit, it just means they can be a piece of shit and get away with it.

Sure, you can argue that a bug in the latest Linux kernel is a sign that there are bugs in lots of OSes. The difference is that with Linux it'll be fixed in a couple of days. Very few people will be using the latest kernel, AFAIK none of the big distros released with it yet, and although some users may have downloaded and compiled the source themselves (I did so myself, as it offered some driver compatibility for new hardware) the architecture is versatile enough that you can simply switch between different kernels, even without fully rebooting, although not completely without disruption.

Re:Double standards (0)

Anonymous Coward | more than 4 years ago | (#28740863)

By that logic, China must produce the highest quality products since everything is made there. Bulk sale is not an indication of quality.

Re:Double standards (4, Funny)

alnjmshntr (625401) | more than 4 years ago | (#28740411)

Right... Because Microsoft are really losing sleep over the negative comments posted on slashdot, so they have assembled a crack team of slashdotters to game the moderation system in their favour.

You have to be kidding me.

Re:Double standards (1)

Pvt_Ryan (1102363) | more than 4 years ago | (#28740621)

What amazes me, is you think they wouldn't.. Credit where credit is due, one thing MS are good at if nothing else is marketing.

Re:Double standards (0)

Anonymous Coward | more than 4 years ago | (#28740115)

You know....you're absolutely correct. Somebody mod this AC up.

Re:Double standards (2, Interesting)

awpoopy (1054584) | more than 4 years ago | (#28740665)

Somebody mod this AC up.

I would love to however, it appears that only people running MS has mod points these days. I spoke unkindly of MS and my karma turned to "bad" AND I haven't seen mod points in three months. Only the shills are being able to use slashdot effectively it seems. That's just my opinion, however I could be wrong.

Re:Double standards (1)

gilgongo (57446) | more than 4 years ago | (#28740291)

If this had been Windows, the article would have been tagged defectivebydesign.

What are you talking about? How is a Linux kernel exploit related to the architecture of DRM [defectivebydesign.org] ??

Re:Double standards (0)

Anonymous Coward | more than 4 years ago | (#28740963)

It's not related. It's just that the Windows lovers of the world are not capable of understanding the derogatory labels we put on them. They only understand that they should be insulted and upset about something related to the products they are fans of.

Expect it to be patched in a matter of days, (-1, Flamebait)

Anonymous Coward | more than 4 years ago | (#28739939)

Not months (hi, Microsoft!)

GG, scrub troll. You lose, we win.

Good find (0, Flamebait)

Anonymous Coward | more than 4 years ago | (#28739941)

After all the crap Brad had to put up with from the SELinux faction, it's good to see technical ability once more scoring points over politics.

(I understand the irony that this comment, is, in itself, purely political)

Just don't use that version (3, Insightful)

BPPG (1181851) | more than 4 years ago | (#28739947)

It's important to note that there is almost never any "preferred" or "special" release of Linux to use. And obviously this flaw doesn't affect people that don't use any security modules.

This is not good news, but it's important news. The kernel's not likely to have a "fixed" re-release for this version, although there probably will be patches for it as well. And when in doubt, just don't upgrade. Not very many machines can take advantage of all of the cool bleeding-edge features that come with each release, anyways. Lots of older versions get "adopted" by someone who will continue to maintain that single kernel release.

Re:Just don't use that version (3, Insightful)

Kjella (173770) | more than 4 years ago | (#28740047)

It's important to note that there is almost never any "preferred" or "special" release of Linux to use. (...) And when in doubt, just don't upgrade. Not very many machines can take advantage of all of the cool bleeding-edge features that come with each release, anyways. Lots of older versions get "adopted" by someone who will continue to maintain that single kernel release.

As a guess pulled out of my nethers 99% use their distro's default shipping kernel, which means there's maybe a dozen kernels in widespread use with a long tail. Unless you're living on the bleeding edge that's what you want to do, otherwise you have to keep up with and patch stuff like this yourself. I'd much rather trust that than not upgrading or picking some random kernel version and hope it's adopted by someone.

Actually, it's already been fixed (5, Informative)

inode_buddha (576844) | more than 4 years ago | (#28740113)

Actually, it's already been fixed as of 2.6.31-rc3. Interestingly enough, the code by itself was fine until gcc tries to re-assign the pointer value upon compiling. Steven J. Vaughn-Nichols had a decent write-up about it in Computerworld.

Wish I had mod points.. nothing to see here! (1)

plasmacutter (901737) | more than 4 years ago | (#28740877)

Actually, it's already been fixed as of 2.6.31-rc3. Interestingly enough, the code by itself was fine until gcc tries to re-assign the pointer value upon compiling. Steven J. Vaughn-Nichols had a decent write-up about it in Computerworld.

And another mountain out of a molehill allowing microsoft astroturfers to troll a flame-war out of a non-event.

Re:Just don't use that version (1)

INT_QRK (1043164) | more than 4 years ago | (#28740209)

I'm just curious about 2.6.30 version. In just ran a > to recheck my version and I'm using 2.6.28-13. I ran update just to make sure, and this is the current version for my distribution. So, can anyone tell me whether 2.6.30 is a stable version in widespread use, or is it a bleeding-edge version under development and test. Finding flaws in DT is what's supposed to happen. Unfortunately the takeaway headline for some will be "see? told you Linux is just as vulnerable as Windows!" Well maintained distributions like Ubuntu and its parent distribution Debian take extraordinary care to not only ensure the most stable functioning software base, but seldom have I read of a major flaw for which I haven't seen the update precede announcement of the bug. In those few cases, I read of the bug, and was able to download the fix in very short order. Neither Windows nor Apple have matched their record of response in my experience.

Re:Just don't use that version (2, Funny)

INT_QRK (1043164) | more than 4 years ago | (#28740227)

don't know why but "uname -a" was replaced by ">" in my above post...something I did

Re:Just don't use that version (1, Informative)

Shamenaught (1341295) | more than 4 years ago | (#28740891)

It is stable, but it will take a little while for the packages to find their way into the network for your particular distribution.

Generally any release with an even number at the end will be a stable release. The kernel development cycle is basically: add functionality (odd releases), make stable (even releases).

As for whether 2.6.30 is really bleeding edge, I wouldn't have said so. It's not yet in wide use, as not that many new distros have been released since it came out. See: Distros are often built on top of a kernel, so changing the kernel just before it's about to be released can rock the boat a little even if the kernel itself is stable. I personally wouldn't bother upgrading unless there's a feature in the kernel that you needed. 2.6.31 could be considered bleeding edge, however, as that's an unstable release that they'll be shoving a lot of new functionality or completing stuff that wasn't ready for 2.6.30.

That said, there were features that I wanted to check-out in the 2.6.30.1 kernel and so I did download and compile it (but only put it on the machine that needed it).

Re:Just don't use that version (2, Informative)

PReDiToR (687141) | more than 4 years ago | (#28740423)

Your distro (lets say Fedora for this example) has to get the sources for a new kernel, apply their own patches, test that the kernel works, package it and then put it out to beta testers to see if it breaks any one of the many configurations of Fedora that are out there.

Sound familiar?

Then they have to upload it to their package management servers and put the fix out there for you to use.

This might not sound like a lot of work, but who needs a new kernel when they are busy with a whole truck full of other packages that people would notice an upgrade in (OpenOffice.org, KDE, Gnome etc.)?

If they keep to a kernel version for as long as possible they don't have to rewrite their own patches for a new version, they don't have to wonder if a new problem that comes through is due to the new kernel and they don't have to expend resources on a fairly back-of-the-store package that people (who use stock kernels) don't care about much.

Contrast that with other users (like myself) who eschew the patches that a distro puts into their kernels and download the latest vanilla sources from kernel.org (usually the same day it comes out), go through the config to make sure nothing major needs tweaking and compile a kernel that will only run at full potential (if I configured everything right ... ) on a very small number of computers, not the whole gamut of x86 based machines (usually) that the Fedora stock kernel is designed for.
Even on my Arch Linux system that is very good at using up to date sources I prefer to roll my own. If you (and others like you) would prefer to run a newer kernel, read up on it (Scroogle Is Your Friend) and don't be afraid to try. The worst that can happen (if you keep your original kernel in the boot menu, and the modules to support it) is that your new shiny kernel sits there and tells you that there is no way on earth it can boot the system and it is having a bit of a panic with itself. Fixed by booting into your stock kernel and trying again.

Good luck with it if you choose to go that direction, and remember to read the changelogs for the newer kernels to see what has been improved and fixed. The latest stable kernel is 2.6.30.1, not 2.6.30. It isn't bleeding edge, it is the latest stable. Bleeding edge kernels have -xxn appended (where xxn is letters and numbers depending on what type of kernel or patches are added).

Re:Just don't use that version (1)

Tanktalus (794810) | more than 4 years ago | (#28740353)

I would expect most distributions to take the fix from .31 and apply it to .30. Most distributions are pretty good at watching for CVEs and other high-importance bug reports and backfitting them. For example, I would expect the fix to show up in the ebuild for Gentoo Real Soon Now .

Re:Just don't use that version (1)

SEWilco (27983) | more than 4 years ago | (#28740491)

It's simpler than not using that version. It's a version of the kernel which has only been distributed in one specialized Red Hat distribution. So it's hard to find a vulnerable machine in the wild. The other vulnerable group are bleeding-edge developers who compiled that kernel, and they'll upgrade as soon as one of them fixes it.

Re:Just don't use that version (1)

thejynxed (831517) | more than 4 years ago | (#28740535)

It is already fixed in 2.6.31-rc3-git3, I believe back on Thursday. This exploit was made generally known on Friday. Now you just get to wait for the distro maintainers to actually implement the patched kernel.

BTW, this issue has been found in -some- kernel versions going back to 2.6.18 or so. Apparently it's not been in every single kernel release, but keeps appearing now and again.

This can happen anywhere in the kernel or relative code that has similar structures, and allows the exploiter to A) cause overruns B) totally trash memory C) access userspace memory data from kernel-land and vice versa, as the kernel thinks it is accessing kernel memory space when it is in fact accessing userland memory space at address 0 (which shouldn't have been able to be mapped by Pulseaudio or any similar program/subsystem).

This particular structure should have never been written like this to begin with. Obvious error, and I am not even a day-to-day programmer.

I always disable those (2, Interesting)

brunes69 (86786) | more than 4 years ago | (#28739985)

I always disable those security modules as they always end up to incompatibilities and other erratic behavior in software.

Exactly what do they do anyway?

Re:I always disable those (4, Funny)

140Mandak262Jamuna (970587) | more than 4 years ago | (#28740107)

They create vulnerabilities by allowing remote code to overload error handlers and thus pwn your system?

Re:I always disable those (2, Interesting)

Antique Geekmeister (740220) | more than 4 years ago | (#28740307)

They ruin otherwise working code that was written in slightly different environments, and for which the very arcane behavior of SELinux has not been tuned. They're also often difficult to write test suites for, especially the unpredictability of SELinux changes, since they affect behavior due to factors entirely outside the control of the particular program author: they affect behavior based on where the package installs the code and what SELinux policies are in place.

It's gotten better: Linux operating system authors have gotten more capable with it, and the software authors have learned not to stuff everything wherevery they feel like (with the exception of Dan Bernstein, but he's loosened his licenses, so we can fix that now).

Just like Linux (0)

Anonymous Coward | more than 4 years ago | (#28739999)

More and More like windows everyday

Re:Just like Linux (1)

Dunbal (464142) | more than 4 years ago | (#28740105)

More and More like windows everyday

      Actually no, this will probably be fixed by later today, as opposed to having to wait for "n" intervals of "patch tuesday"...

Re:Just like Linux (3, Insightful)

Tony Hoyle (11698) | more than 4 years ago | (#28740133)

Unless they're going to add a proper warning for the condition to gcc 'today' it won't, really.

Sure there are enough developers to go over the kernel to make sure such errors haven't been missed elsewhere, but all it takes is one to miss it and it's still there. Then there's all the other software compiled by gcc..

I'm not entirely sure how it can lead to an exploit (short of remapping page zero, which requires root privileges so doesn't really count) but since it has it's going to need a proper fix.

Re:Just like Linux (1)

shentino (1139071) | more than 4 years ago | (#28740201)

It was just a case of overly aggressive optimization. And attempting to dereference a value BEFORE you verify its non nullity is a programming error.

Re:Just like Linux (1, Funny)

Anonymous Coward | more than 4 years ago | (#28740759)

I'm using NoScript and Adblock Plus so I'm not worried.

Serious bug in gcc? (1, Interesting)

Anonymous Coward | more than 4 years ago | (#28740019)

The explanation given by the SANS Internet Storm Center seems strange. Firstly, the code they provide as an example shows one variable being assigned "sk" and then another variable being checked "tun". I think the "if" statement should be checking "sk" and not "tun". Secondly, the assignment could be a perfectly valid assignment of null; "tun->sk" could indeed be null. The compiler should certainly not optimize out the if statement just because the variable has already been assigned. This would be a major fault in the compiler.
Perhaps they have just oversimplified to the point of writing nonsense...

Re:Serious bug in gcc? (4, Informative)

Tony Hoyle (11698) | more than 4 years ago | (#28740077)

gcc is definitely doing the wrong thing here.

Given the code:
a = foo->bar
if(foo) something()

gcc is doing precisely the wrong thing - optimising out the if on the theory that the app would have crashed if it was null.

What it *should* do is throw a warning (even an error, given the clear intent of the code) pointing out that the variable is dereferensed before it is tested.

This kind of error being missed by gcc is going to affect a *lot* of code - it's really not that uncommon a coding error, and is easy to do.

Re:Serious bug in gcc? (1)

shentino (1139071) | more than 4 years ago | (#28740211)

Except that the program really WOULD crash if foo were NULL.

In the kernel, null pointer derefs have no place. It's not valid kernel space, and for userland access you're supposed to use special functions anyway.

Re:Serious bug in gcc? (2, Insightful)

Anonymous Coward | more than 4 years ago | (#28740361)

The point is that GCC silently optimizes it away so the programmer has no idea that it's not even running the code they put in (however incorrect that code is). It's like saying "if there is an error in my code just remove that code and keep the rest without telling me".

Re:Serious bug in gcc? (2, Insightful)

Rockoon (1252108) | more than 4 years ago | (#28740547)

This issue is a bit more complicated than you people are making it out to be.

For the most part, programmers DO WANT this kind of optimization, which is why they use an optimizing compiler. Things like dead-code elimination, constant propogation, and whole program optimizations are important to programmers.

If you don't want this stuff done, you don't reach for an optimizing compiler and then enable those optimizations. Its their purpose. If (something we know at compile time) should *always* be eliminated in a decent optimizing compiler.

Now, should GCC make assumptions in this specific case about the state of the pointer? Probably not. This isnt actualy a case of "something we know at compile time" so its a bug in the optimizer.

Re:Serious bug in gcc? (0)

Anonymous Coward | more than 4 years ago | (#28740545)

I would think the kernel would be the one place where you could expect access to an address close to 0 to succeed.

Re:Serious bug in gcc? (2, Informative)

dakkar (128056) | more than 4 years ago | (#28740087)

The description given by SANS is a bit misleading. What I believe is happening is:

  1. 1) tun is derefenced during the assignment to sk
  2. 2) if tun were NULL, the dereferencing would blow up the process
  3. 3) so the if (!tun) will always be false if we get there (says the compiler)

Since point 2 is mostly true, the compiler is not completely wrong to assume point 3

As Spengler says, a bigger problem is that loading SELinux (or, it looks like, most other security modules) causes the NULL dereference protection to be disabled.

Re:Serious bug in gcc? (1)

shentino (1139071) | more than 4 years ago | (#28740221)

Why the hell is kernel code trying to dereference null pointers in the first place? Last time I checked, zero was in userland.

Re:Serious bug in gcc? (5, Insightful)

Bananenrepublik (49759) | more than 4 years ago | (#28740141)

They were writing nonsense. GCC makes use of the fact that in the C language any pointer that was dereferenced can't be NULL (this is made explicit in the standard). People use C as a high-level assembly where these assumptions don't hold. This is why code that doesn't assume this breaks. This issue came up a few months ago on the GCC lists, where an embedded developer pointed out that he regularly maps memory to the address 0x0, thereby running into issues with this assumption in the optimizers. The GCC developers introduced a command-line flag which tells the computer to not make that assumption, therefore allowing the compiler to be used even in environments where NULL pointers can be valid.

Now, the exploit uses this feature of the compiler (or the C language, if you will) to get the kernel into an unspecified state (which is then exploited) -- the NULL pointer check will be "correctly" optimized away. But in order to do this it first has to make sure that the pointer dereference preceding the NULL pointer check doesn't trap. This needs some mucking around with SELinux, namely one has to map memory to 0x0.

This is a beautiful exploit, which nicely demonstrates how complex interplay between parts can show unforeseen consequences. Linux fixes this by using the aforementioned new compiler option to not have the NULL pointer check optimized away.

Re:Serious bug in gcc? (1)

Ritchie70 (860516) | more than 4 years ago | (#28740193)

Wish I had mod points today. This is a truly clear and understandable explanation of the issues involved.

The embedded market is a very good point - and "embedded" doesn't necessarily mean what people thinks it means. It might, for example, mean that graphics card you just put in your computer that runs code itself.

15 years ago I was dealing with code on a graphics card and, in fact, the video buffer was mapped in at 0x0 - which may have been a questionable choice, except that you could actually SEE a write to a null pointer.... the upper left corner would get garbage.

Re:Serious bug in gcc? (5, Interesting)

TheRaven64 (641858) | more than 4 years ago | (#28740415)

Except that his explanation is wrong. Dereferencing NULL is illegal, but pointer arithmetic on NULL is legal (and, even if it were illegal, would be practically impossible for a compiler to check). This statement is not dereferencing NULL, it is (potentially) performing pointer arithmetic on NULL (adding the offset of the sk field to it) and then dereferencing the result. This may or may not be valid, depending on how NULL is defined (it doesn't have to be 0 in C, although it usually is), what the offset of sk is, and what the memory layout of the target platform is.

On most modern platforms, NULL is defined as (void*)0 and the entire bottom page of memory is mapped as no-access. On some embedded systems, however, the bottom few hundred bytes are used for I/O and you get the addresses of these by adding a value to 0. On these systems it is perfectly valid (and correct) C to define a structure which has the layout of the attached devices and then cast 0 to a pointer to this structure and use that for I/O.

Re:Serious bug in gcc? (1)

Ritchie70 (860516) | more than 4 years ago | (#28740957)

I've re-read these two posts multiple times now and I finally get the subtle distinction being made.

Suppose the following:

struct t { int one; int two; int three; };
struct t* b = 0;

"b->two" is not a dereference of 0. It is a dereference of "0 + the offset of two within the structure t." (Likely of the address 0x4.)

However, "b->one" is a dereference of 0.

So if the element of the structure being dereferenced is the first in the structure, this may be a valid optimization, although the efficiency gained by a jump-if-not-zero being eliminated seems negligible to me, and such an optimization should be explicitly called out in some fashion.

If the element of the structure isn't the first, this isn't a valid optimization to make.

Re:Serious bug in gcc? (2, Informative)

TheSunborn (68004) | more than 4 years ago | (#28740413)

This sound more like a gcc/embeded os bug. There is no requirement in c/c++ that the null pointer is (int)0. That is: It don't have to be all 0 bits.
It just need to be distinct from any valid pointer, so if you run on a platform where you use memory address 0(Valid, but still wierd), you need
to config gcc(If possible, I don't know if gcc supports this) to use an other bit pattern as null pointer(say 0xeffff), and then you need to configure your embeded os, to never
return a memory address/buffer that contain the address you have used as null pointer.

Re:Serious bug in gcc? (3, Informative)

johnw (3725) | more than 4 years ago | (#28740769)

That is: It don't have to be all 0 bits. It just need to be distinct from any valid pointer,

Correct - apart from the "just" bit.

It doesn't need to be all 0 bits.
It does need to be distinct from any valid pointer.

*and*

void *p = 0;

must generate a null pointer, and:

p == 0

must come out true if p is a null pointer. The internal implementation need not be all zeroes, but it does need to look rather like it to source code.

Wait, what? (4, Interesting)

TheRaven64 (641858) | more than 4 years ago | (#28740061)

This code looks right?

struct sock *sk = tun->sk; // initialize sk with tun->sk
...
if (!tun)
return POLLERR; // if tun is NULL return error

So, he's dereferencing tun, and then checking if tun was NULL? Looks like the compiler is performing an incorrect optimisation if it's removing the test, but it's still horribly bad style. This ought to be crashing at the sk = tun->sk line, because the structure is smaller than a page, and page 0 is mapped no-access (I assume Linux does this; it's been standard practice in most operating systems for a couple of decades to protect against NULL-pointer dereferencing). Technically, however, the C standard allows tun->sk to be a valid address, so removing the test is a semantically-invalid optimisation. In practice, it's safe for any structure smaller than a page, because the code should crash before reaching the test.

So, we have bad code in Linux and bad code in GCC, combining to make this a true GNU/Linux vulnerability.

Re:Wait, what? (2, Interesting)

Anonymous Coward | more than 4 years ago | (#28740119)

The patch [kerneltrap.org] .

Re:Wait, what? (4, Insightful)

TheSunborn (68004) | more than 4 years ago | (#28740137)

I think the compiler is correct. If tun is null, then tun->sk is undefined and the compiler can do what even optimization it want.

So when the compiler see tun->sk it can assume that tun is not null, and do the optimization, because IF tun is null, then the program is invoked undefined behavier, which the compiler don't have to preserve/handle. (How do you keep the semantic of an undefined program??)

Re:Wait, what? (1)

snowgirl (978879) | more than 4 years ago | (#28740885)

I think the compiler is correct. If tun is null, then tun->sk is undefined and the compiler can do what even optimization it want.

So when the compiler see tun->sk it can assume that tun is not null, and do the optimization, because IF tun is null, then the program is invoked undefined behavier, which the compiler don't have to preserve/handle. (How do you keep the semantic of an undefined program??)

My favorite expression is that a proper implementation of undefined behavior may be to have monkeys fly out of the user's butt.

I agree, it's not really an error in GCC that someone implemented something wrong. A nice flag complaining that something is dereferenced before it's checked would be pretty nice...

Looking at the code, it's a pretty common behavior of programmers. "I'm setting up my variables, so I may as well initialize them with valid data." The problem is that you don't know if it's valid data if it's not a constant!

Re:Wait, what? (5, Interesting)

pdh11 (227974) | more than 4 years ago | (#28740153)

Technically, however, the C standard allows tun->sk to be a valid address, so removing the test is a semantically-invalid optimisation.

No. Technically, if tun is null, dereferencing it in the expression tun->sk invokes undefined behaviour -- not implementation-defined behaviour. It is perfectly valid to remove the test, because no strictly conforming code could tell the difference -- the game is already over once you've dereferenced a null pointer. This is a kernel bug (and not even, as Brad Spengler appears to be claiming, a new class of kernel bug); it's not a GCC bug.

But as other posters have said, it would indeed be a good security feature for GCC to warn when it does this.

Peter

Re:Wait, what? (3, Informative)

TheRaven64 (641858) | more than 4 years ago | (#28740341)

No. Technically, if tun is null, dereferencing it in the expression tun->sk invokes undefined behaviour -- not implementation-defined behaviour

I've seen a lot of people claiming that, however (as someone who hacks on a C compiler) there are a few things I take issue with in your assertion.

First, NULL is a preprocessor construct, not a language construct; by the time it gets to the compiler the preprocessor has replaced it with a magic constant[1]. The standard requires that it be defined as some value that may not be dereferenced, which is typically 0 (but doesn't have to be, and isn't on some mainframes). Dereferencing NULL is invalid, however that is not what is happening here.

The value &(tun->sk) is the address of tun, plus a fixed offset. The expression &(((struct foo*)0)->bar) is valid C and will give the value of the offset of the sk field in the foo struct. A typical definition of NULL is (void*)0, and &(((struct foo*)(void*)0)->bar) will also give the value of the offset of the bar field.

In this case, it is tun->sk, not &(tun->sk) which is being loaded, however the pointer arithmetic which generates the address happens first. If tun is NULL then this is NULL + {the offset of sk}. While dereferencing NULL is explicitly not permitted, pointer arithmetic on NULL is permitted, and dereferencing any non-NULL memory address is permitted.

This is obvious from an implementation perspective. If pointer arithmetic on the NULL address were not permitted then every single pointer arithmetic expression would require a check at every intermediate stage to make sure that it did not pass through NULL. For example (a - a + a + 1) would be an invalid pointer arithmetic expression on platforms where NULL is address 0 if address computations were not permitted on NULL.

[1] GCC and C++1x both declare a new language keyword for an invalid pointer, but this is not part of standard C.

Re:Wait, what? (1)

TheSunborn (68004) | more than 4 years ago | (#28740461)

But it's (tun->sk) not &(tun->sk). That is: The code is looking at the value of the member sk in the struct pointed to by tun. Looking at this value is undefined if tun is null.
It does not take the address of tun or tun->sk.

Re:Wait, what? (1)

russotto (537200) | more than 4 years ago | (#28740955)

If tun->sk is an array, then tun->sk is equivalent to &(tun->sk). That turns out not to be the case, though.

This optimization seems to be only useful for evil, though. How often does a programmer put in a test for null on something he's already dereferenced when it isn't an error? Maybe there's some common case where this happens, but I can't think of one off the top of my head. Redundant explicit tests for null are another matter, but that would be a different optimization.

Re:Wait, what? (1)

pdh11 (227974) | more than 4 years ago | (#28740479)

While dereferencing NULL is explicitly not permitted, pointer arithmetic on NULL is permitted, and dereferencing any non-NULL memory address is permitted.

Not any non-null memory address -- only one that points into an object. As there is no object whose address is the null pointer, the dereference is still undefined. And the compiler knows that.

Another way of looking at it is that tun->sk is equivalent to (*tun).sk, which is even more clearly undefined in C.

Peter

Re:Wait, what? (2, Informative)

Anonymous Coward | more than 4 years ago | (#28740579)

You are completely wrong and you should learn some C before posting crap like this.

The NULL pointer has the value 0 and no other value. Period. Internally, it can be represented by other bit-patterns than all-0. But the C standard demands that
    void *x = 0;
generates the NULL pointer.

The last paragraph is also completely wrong because you fail to realize that the substraction of two pointers gives an integer and not another pointer.

So: please, please don't post again until you've learnt the absolute basics of the C language to prevent further embarrassment!

Re:Wait, what? (4, Informative)

johnw (3725) | more than 4 years ago | (#28740813)

First, NULL is a preprocessor construct, not a language construct; by the time it gets to the compiler the preprocessor has replaced it with a magic constant[1].

Which must be either "0" or "(void *) 0".

The standard requires that it be defined as some value that may not be dereferenced, which is typically 0 (but doesn't have to be

Not true - the standard requires NULL to be defined as one of the two values given above.

and isn't on some mainframes

There are indeed some platforms where a null pointer is not an all-bits-zero value, but this is achieved by compiler magic behind the scenes. It is still created by assigning the constant value 0 to a pointer, and can be checked for by comparing a pointer with a constant 0.

MOD PARENT UP - MOD GRAND PARENT DOWN! (0)

Anonymous Coward | more than 4 years ago | (#28740927)

Parent is absolutely right and basically everything in grand parent's post is wrong.
It's sad to see that moderators know nothing about the C language and mod grand parent up, but confirms what most people know anyway: slashdot is not the place for geeks anymore it's the place for lamers.

Re:Wait, what? (0)

Anonymous Coward | more than 4 years ago | (#28740941)

The fact that NULL does not have to be 0 is a good point. That means that if(!tun) is bad in terms of portability.

Re:Wait, what? (1, Insightful)

Anonymous Coward | more than 4 years ago | (#28740207)

No, dereferencing a NULL pointer results in undefined behaviour. The GCC compiler is generating code which follows the C standard in this case.

if (tun == null) then the behaviour becomes undefined as soon as the first line is passed.
if (tun != null) then the check is not needed.
Since "assuming tun is a non-NULL pointer" falls under the remit of "undefined" the compiler is acting reasonably in doing that.

"Undefined behaviour" includes anything that the program can possibly do, such as setting your printer on fire and emailing death threats to your grandmother. (Although it would be a malicious compiler which generates code that did that deliberately, it would still follow the standard!)

Therefore the compiler is allowed to assume that the C program guarantees that tun is not NULL at that point. Expecting any specific behaviour, such as the program halting, is outside the C standard. The compiler could optimize out the read to sk if sk is never used, for example, and that would be an entirely reasonable optimization.

Re:Wait, what? (1)

MadShark (50912) | more than 4 years ago | (#28740385)

Wouldn't lint catch typically catch this sort of problem(possible use of a NULL pointer warning)?

CFLAGS (3, Informative)

Epsillon (608775) | more than 4 years ago | (#28740063)

CFLAGS+= -fno-delete-null-pointer-checks

Job done (should work with Gentoo, buggered if I know how to do this in other distros, DYOR), even with -O2/-O3. This is an optimisation/code conflict. The code itself is perfectly valid, so if your CFLAGS are -O -pipe you have nothing to worry about. GCC's info pages show what is enabled at various optimisation levels. -fdelete-null-pointer-checks is enabled at -O2. Of course, this only applies when you compile your own kernel. If vendors are supplying kernels compiled with -O2 without checking what it does to the code then it is obvious who is to blame.

Re:CFLAGS (3, Informative)

Tony Hoyle (11698) | more than 4 years ago | (#28740097)

No. That doesn't fix the problem. All it does is stop the broken optimisation (why the *hell* did someone at gcc think such a thing should be default anyway?)

You need an -ferror-on-bogus-null-pointer-checks parameter so that the code can be fixed.

It's an easy error to make. It's the compilers job to warn you.. in this case not only did it fail to throw a warning it also made the problem worse by 'optimising' it.

Re:CFLAGS (0)

Anonymous Coward | more than 4 years ago | (#28740303)

Where do you place the boundary? Should compilers return an error on "x + 0" and "x * 1"? Such unnecessary constructs could indicate a mistake in the code, right?

And pretty soon, you end up returning an error each time -O3 finds a way to optimize something. Surely the programmer made an error!

Re:CFLAGS (1)

quintus_horatius (1119995) | more than 4 years ago | (#28740289)

All this means is that well-behaved packages (and users) won't accidentally exploit this bug, but it doesn't take away the fact that the kernel shouldn't allow the exploit.

Re:CFLAGS (0)

Anonymous Coward | more than 4 years ago | (#28740713)

I'd just like to say this to all the wankers out there who hate Gentoo because they have this weird prejudiced view that they're all a bunch of over-optimizing speed freaks:

CFLAGS+= -fno-delete-null-pointer-checks

Yes, that would be a Gentoo user using Gentoo's source-based package system to REDUCE an optimization and make the system more secure.

And that's why I like Gentoo, and why the haters can, in fact, go suck it.

what the...?! (0)

Anonymous Coward | more than 4 years ago | (#28740123)

Why the crap doesn't "tun->sk" panic the kernel? They had it coming if the userland can tamper with the kernel's mapping of page 0.

Re:what the...?! (1)

TheRaven64 (641858) | more than 4 years ago | (#28740429)

My (uninformed) guess is that one of these friendly security modules does some NULL-pointer handling and turns something that should be a hard fail into a soft error. There was an OpenSSH vulnerability a couple of years ago like this, where error-recovery code turned something that should have been a crash into a keep-running-in-an-undefined-state.

Can enyone explain this? (1)

bperkins (12056) | more than 4 years ago | (#28740649)

<em> This will cause the kernel to try to read/write data from 0x00000000, which the attacker can map to userland </em>

This was somewhat surprising to me. Digging around a bit, it looks like it has something to do with an seLinux handler.

Can anyone elaborate on this?
Load More Comments
Slashdot Account

Need an Account?

Forgot your password?

Don't worry, we never post anything without your permission.

Submission Text Formatting Tips

We support a small subset of HTML, namely these tags:

  • b
  • i
  • p
  • br
  • a
  • ol
  • ul
  • li
  • dl
  • dt
  • dd
  • em
  • strong
  • tt
  • blockquote
  • div
  • quote
  • ecode

"ecode" can be used for code snippets, for example:

<ecode>    while(1) { do_something(); } </ecode>
Sign up for Slashdot Newsletters
Create a Slashdot Account

Loading...