Kernel Pointer Overflows in Read and Writes

I was looking at some Linux Kernel code today when I came across this piece of code implementing the write operation in a device driver.

if (copy_from_user(writebuf, buffer + writecount, transfer_length) ...

buffer is user controlled.  writecount is derived from the user controlled count parameter that is used the write(…,const char __user *buffer,size_t count,…) operation.

 This type of code of pointer indexing as in buffer + writecount is not uncommon and found in a number of places with the Linux kernel, and presumably many other kernels including NetBSD, OpenBSD, FreeBSD, and perhaps even non Unix Kernels.

 There is an explicit check in the Linux file system layer that validates the count parameter, so that it is not greater than INT_MAX.  The reason for this validation, amongst eliminating a number of kernel bugs when passing large values of count, is that the return value on the read and write operations is of type ssize_t.

ssize_t is a signed integral type and is in the range of INT_MIN and INT_MAX.   Therefore if the return value, which indicates the number of bytes read or written is to fit into size_t, the count parameter must be less than INT_MAX.  The unused bit between INT_MAX and UINT_MAX is used in the return vaue, and indicates the sign.

 Back to the Linux Kernel code..

An interesting thing occurs when we start using buffer + count with large values of count.  It is possible to have pointer overflows and wraparounds.

 In Linux (default build), the userland stack begins at 0xbfffffff and the kernel begins at 0xc0000000. The largest address that a 32 bit pointer can hold is 0xffffffff.  0xffffffff – 0xc0000000 is 0x40000000.  In cases where we use a user supplied count from a read or write operation to index either a kernel buffer or a buffer controlled by userland (at or below 0xbfffffff), count must be less than INT_MAX. 

But 0x40000000 is much less than INT_MAX, and we can have a pointer overflow or wraparound when we use this to index a buffer.

This means that there are number of pointer overflows within the Kernel.  buffer + count can overflow and wraparound when count is greater than 0x40000000.

Is code like this exploitable?

 There is no doubt that code like this is exploitable in the sense that pointer overflows can occur.  But are they exploitable from a malicious attacker’s point of view?  I’m not sure of this, and will have to audit and investigate each case individually.  I suspect that it may be hard to trigger such code without being caught out by memory access concerns.


5 responses to “Kernel Pointer Overflows in Read and Writes

  1. “Ok, so the first person to disclose a Linux kernel zero day exploit in the next week will get 300$ from me direct into their favorite (legitimate) charity’s bank account.

    Ok, fuck it, let’s make it 500$. I’m serious. Ok, fuck it again. ANY kernel exploit for:

    released publicly in the next week gets 500$ of my personal money into their favorite charity’s bank account. That’s right, YOU get to pick the charity. As long as it’s legit and the exploit is released before midnight of November 16th, 2007.”

    hmmm. If ur interested…

    I have a po box/account in belize setup for the ‘save jerome heckencamp’ fund that i probably no longer need 😉

  2. Hi Jody. Canberra must be getting warmer now :-). But then again I thought Sydney was freezing.. As for your challenge, that’s a mighty impressive offer your making 😉

    Does an exploit have to be released, or would a snippet of the vulnerable code be enough? With verification by a vendor? I can’t test the vulnerabilities I have, in terms of exploitation, as the bugs require exotic (non vanilla i386) hardware and/or architectures.

    Would that still count?

    Also, a week is’nt much time to co-ordinate a vendor response (unless the intention is to release a bug without notification). How about a private email to you, with vulnerability details,in less than a week, followed later by a public disclosure 😉

    I’m being so needy with my requests I know! And after such a generous challenge was made..

    Onto the matters of ZDI/IDefense..
    I sent a bug to ZDI last week or two ago, and they responded that they were only interested in remotes (and for the most part, pre-authentication vulnerabilities). I was going to try IDefense, but have not contacted them yet.

  3. Fuck the vultures at ZDI/ID

    Give them to the blackhats 😉

  4. “In Linux (default build), the userland stack begins at 0xbfffffff and the kernel begins at 0xc0000000”

    You mean ends at 0xc0000000 or am I missing something ? Cool stuff there anyway 🙂

  5. He is right… The kernel text starts at 0xc000000 in the i386 architecture. It´s almost the same in many different architectures (like ppc).


    Rodrigo (BSDaemon).

Leave a Reply

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

You are commenting using your 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