xorl %eax, %eax

CVE-2009-3547: Linux kernel Pipe NULL Pointer Dereference Race Condition

with 23 comments

This awesome vulnerability was discovered by Earl Chew and quickly noticed and classified as a vulnerability by Eugene Teo of Red Hat.
This vulnerability is extremely straightforward to exploit after all the exploit releases of spender on NULL pointer dereference bugs. So, here is some code from fs/pipe.c as seen in 2.6.29 release of the Linux kernel…

const struct file_operations write_pipefifo_fops = {
   ...
        .open           = pipe_write_open,
   ...
};
   ...
static int
pipe_write_open(struct inode *inode, struct file *filp)
{
        mutex_lock(&inode->i_mutex);
        inode->i_pipe->writers++;
        mutex_unlock(&inode->i_mutex);

        return 0;
}

The code isn’t that hard to understand. When you open a pipe for writing, this routine is called and it will increment the ‘inode->i_pipe->writers’ that represents the current number of writers to that pipe as you might have guessed. Of course, it is doing this in a MUTEX lock to avoid race conditions with other code that might change that counter’s value.
The equivalent functions that release a pipe are the following three:

static int
pipe_read_release(struct inode *inode, struct file *filp)
{
        return pipe_release(inode, 1, 0);
}

static int
pipe_write_release(struct inode *inode, struct file *filp)
{
        return pipe_release(inode, 0, 1);
}

static int
pipe_rdwr_release(struct inode *inode, struct file *filp)
{
        int decr, decw;

        decr = (filp->f_mode & FMODE_READ) != 0;
        decw = (filp->f_mode & FMODE_WRITE) != 0;
        return pipe_release(inode, decr, decw);
}

If a process attempts to open a pipe while another one releases it, and assuming that the release happens first, the ‘open’ routines will lead to a NULL pointer dereference since ‘inode->i_pipe’ would be NULL.
This amazing vulnerability was fixed by applying the following patch:

 pipe_read_open(struct inode *inode, struct file *filp)
 {
-       /* We could have perhaps used atomic_t, but this and friends
-          below are the only places.  So it doesn't seem worthwhile.  */
+       int ret = -ENOENT;
+
        mutex_lock(&inode->i_mutex);
-       inode->i_pipe->readers++;
+
+       if (inode->i_pipe) {
+               ret = 0;
+               inode->i_pipe->readers++;
+       }
+
        mutex_unlock(&inode->i_mutex);
 
-       return 0;
+       return ret;
 }
 
 static int
 pipe_write_open(struct inode *inode, struct file *filp)
 {
+       int ret = -ENOENT;
+
        mutex_lock(&inode->i_mutex);
-       inode->i_pipe->writers++;
+
+       if (inode->i_pipe) {
+               ret = 0;
+               inode->i_pipe->writers++;
+       }
+
        mutex_unlock(&inode->i_mutex);
 
-       return 0;
+       return ret;
 }
 
 static int
 pipe_rdwr_open(struct inode *inode, struct file *filp)
 {
+       int ret = -ENOENT;
+
        mutex_lock(&inode->i_mutex);
-       if (filp->f_mode & FMODE_READ)
-               inode->i_pipe->readers++;
-       if (filp->f_mode & FMODE_WRITE)
-               inode->i_pipe->writers++;
+
+       if (inode->i_pipe) {
+               ret = 0;
+               if (filp->f_mode & FMODE_READ)
+                       inode->i_pipe->readers++;
+               if (filp->f_mode & FMODE_WRITE)
+                       inode->i_pipe->writers++;
+       }
+
        mutex_unlock(&inode->i_mutex);
 
-       return 0;
+       return ret;
 }

As you can see, it is a simple series of NULL checks against ‘inode->i_pipe’ on pipe_read_open(), pipe_write_open() and pipe_rdwr_open().
This results in a completely user control increment of an arbitrary value located at ‘NULL->readers’ of ‘NULL->writers’. Does this reminds you anything? :P
There might also be easier ways to exploit this. Anyway, too bad that such a nice bug was killed. :(

Written by xorl

November 3, 2009 at 21:14

Posted in bugs, linux

23 Responses

Subscribe to comments with RSS.

  1. readers and writers aren’t pointers, they’re just elements of the NULL structure. Causing them to be incremented doesn’t increment anything in the kernel, but these two fields need to be set properly to pass checks to allow exploitation in pipe_write for example.

    You’ll see — when/if I release my exploit ;)

    spender

    November 3, 2009 at 21:45

  2. Nice to know :)

    I’ll start developing mine tomorrow since I’m going to sleep now.

    cheers.

    xorl

    November 3, 2009 at 21:55

  3. BTW, Eugene deserves no credit for finding anything. He read the twitter of me and Fotis Loukos — the proof is right there in the bugzilla history. These plagiarists are pathetic.

    On another note, if you’ve started the exploit yet you may have noticed the rather extreme version/config dependency. I’ve left the 2.4 version broken in my exploit with some comments/hints. I’d like you to fix it :) It should be more of a challenge than exploiting a recent kernel.

    spender

    November 4, 2009 at 12:53

  4. I didn’t knew that about Eugene Teo but in any case, since I cannot prove that he’s reading your twitter, (I pretend to simply not even see the reference to fotisl) I have to give him credit since he was the “first” one who classified it as a vulnerability.

    I don’t know about 2.4 kernels, I haven’t looked at it in 2.4 at all. Nevertheless, thanks for the heads up.

    xorl

    November 4, 2009 at 22:25

  5. Yea he classified it as a vulnerability a day after I was talking about it and wrote the exploit for it ;) Like I said, just look at the bugzilla history entry, it says the source for the information was twitter. What other twitter account was discussing it then?

    Either way, the exploit is now live, complete with OpenBSD history lesson.

    spender

    November 5, 2009 at 00:49

  6. Yea, you’re probably right about the twitter in redhat’s bugzilla.

    Jesus Mr. spender! STOP RELEASING EXPLOITS!!!

    xorl

    November 5, 2009 at 00:52

  7. So you like writing about public exploits, but you don’t want anyone to release any? :) How can we appease you? :p

    Look at it this way: there’s a direct correlation between public exploits being released and preventive measures being added to all systems. Without any tangible risk, the people getting paid to improve security browse slashdot all day, because they’re doing a good job.

    The exploits I’ve released have been for kernels hardly anyone uses or for bug classes they should already be protected from. But we can agree to disagree ;)

    spender

    November 5, 2009 at 01:19

  8. Well, to begin with, I don’t “like” writing about public exploits. I just think that the posts are more complete when the reader understands how the vulnerabilities could be abused (even though I strongly disagree with releasing exploit codes).

    Your statement is indeed accurate but it’s sad that you’re assisting in killing such awesome vulnerabilities. Of course, we have a different point of view in that topic and because of this, that conversation could continue till the end of time.

    xorl

    November 5, 2009 at 01:34

  9. Maybe I’m missing something, but are you sure that your analysis is right? For me it seems that you cannot change an arbitrary value in memory with that but you will increment NULL + offset of readers or writers in one. I think that the key of the fix here is the return ENOENT when i_pipe is NULL, thus not giving an fd when trying to open that pipe inode that is currently being released.

    dreyer

    November 5, 2009 at 13:50

  10. spender is wa whore ;)

    smilingjim

    November 5, 2009 at 15:22

  11. My analysis was flawed in that increment concept as it was quickly spotted by spender if you have a look at his initial comment.
    Yeap, the patch is a common check against NULL pointers where if i_pipe is NULL, it will just unlock the MUTEX and return with -ENOENT.

    xorl

    November 5, 2009 at 20:30

  12. Spender,
    Congratulations on your discovery. I’m sure your 400 friends on twitter are pleased.

    It is also well known that you desire glory for all your bug discoveries, nobody cares; shut the fuck up, stop looking for blogs that talk about bugs and don’t give you credit, remember the redstack episode? all your “bugs” were ideas that pipacs discovered eitherway, so why are you looking for glory in places that you are clueless in. Funny how the full expanse of your bugs are null pointer dereferences alone.

    Sigh, I’ve seen this a billion times; if you want credit make an advisory, otherwise stop crying. A lot of us read xorl first thing in the morning and last thing at night, and we’re all sick of seeing your blathering rhesus monkey attitude on it, it makes us sick.

    I’ve warned you before. I shan’t warn you again, nobody cares about your fag shit.

    Also, congratulations on your discovery, and your youtube video + your NULL pointer dereference framework, a lot of good hard work went into it.

    C’est la vie.

    Keen Observer

    November 5, 2009 at 21:01

  13. “Keen Observer”: you should worry about yourself and not others, especially when you have no idea what you’re talking about. You remember redstack so well but forget that perf_counter wasn’t a null pointer dereference. Neither was the SGI GRU exploit. I give credit in every exploit where it’s due. You claim I desire glory for all my bug discoveries, but then say I should start publishing advisories. How would you not consider that a form of desiring glory? I’ve probably been following this blog for longer than you have — I didn’t go “hunting” for anything, as it pops up on my RSS feed. I contributed an accurate analysis of the vulnerability — what purpose have you served here?

    You’re just yet another person who does nothing and likes to complain about other people who actually do something (which is why you post under a fake pseudonym).

    I’m very scared of your warning — can we please escalate that to the point where you actually do something?

    Thanks.

    spender

    November 5, 2009 at 23:22

  14. Sure, where would you like to meet?

    Keen Observer

    November 6, 2009 at 01:38

  15. Oh, and I wasn’t aware that perf_counter was your discovery either; I must get my facts straight henceforth. Now please stop trolling, and tweet about it :)

    Keen Observer

    November 6, 2009 at 01:39

  16. No comment? Oh well, I’m pretty sure you’re a capable lad; but try looking for glory on your twitter instead of making gesticulative horse sounds on xorl’s blog, xorl is good people, we don’t need your nonsense each time we want to have a good read on a public bug, why don’t you blog about it instead, or tweet about it, being as tweeting and youtube’ing is what you do best.

    Also, it’s funny how you say that I post under a fake pseudonym, whereas “spender” is not your real name, nor is “pipacs” his. If you didn’t desire glory for your exploits, why public exploits at all? Because, if you didn’t someone else would? Why don’t you go back to doing grsecurity kernel development instead of playing god of the exploitation scene.

    In your opinion, you’re the only person doing anything whatsoever, the latest and greatest. It won’t be long before that Windows Vista machine of yours is compromised; Try this:

    Stop posting exploits
    Stop twittering
    Stop reading oss-security
    Stop reading LKML
    Stop glory hunting

    And go back to what you were doing, vis-avis grsecurity.

    Keen Observer

    November 7, 2009 at 02:35

  17. Keen Observer must be str0ke speaking from heaven cuz that’s exactly what jesus would say about spender and his man glorification of the scene.

    spender get a room with yourself you flaming fag!

    titties mcgee

    November 7, 2009 at 05:02

  18. lolz

    solstice

    November 7, 2009 at 06:21

  19. well said keen observer

    anonymous

    November 7, 2009 at 06:25

  20. keen observer u r such a LOSER … get a life u fag
    @spender .. just ignore this useless fag.

    HND

    November 8, 2009 at 11:38

  21. Thanx alot for this post

    مدونة

    مدونة

    November 9, 2009 at 11:31

  22. spender is hilarious as usually. damn whitehats they are all alike :)

    lol

    June 26, 2010 at 12:30

  23. Thank you for this useful post

    viktor

    August 16, 2011 at 10:08


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s