xorl %eax, %eax

CVE-2010-3849: Linux kernel PF_ECONET NULL Pointer Dereference

leave a comment »

This is the next vulnerability being killed by Nelson Elhage. While reading econet_sendmsg() (check out CVE-2010-3848) is almost impossible to avoid noticing this comment:

        /*
         *      Get and verify the address.
         */

        mutex_lock(&econet_mutex);

        if (saddr == NULL) {
                struct econet_sock *eo = ec_sk(sk);

                addr.station = eo->station;
                addr.net     = eo->net;
                port         = eo->port;
                cb           = eo->cb;
        } else {
                if (msg->msg_namelen < sizeof(struct sockaddr_ec)) {
                        mutex_unlock(&econet_mutex);
                        return -EINVAL;
                }
                addr.station = saddr->addr.station;
                addr.net = saddr->addr.net;
                port = saddr->port;
                cb = saddr->cb;
        }
   ...
        if (dev->type == ARPHRD_ECONET) {
                /* Real hardware Econet.  We're not worthy etc. */
#ifdef CONFIG_ECONET_NATIVE
   ...
                /* BUG: saddr may be NULL */
                eb->cookie = saddr->cookie;
                eb->sec = *saddr;
                eb->sent = ec_tx_done;

You can read that there is an initial check of ‘saddr’ being NULL that initializes ‘addr’ appropriately. However, In case of a hardware ECONET type, it will initialize ‘eb’ structure’s members without any checks. There is even a comment to help us out. To fix this, the NULL checking code was changed.

        mutex_lock(&econet_mutex);
 
-       if (saddr == NULL) {
-               struct econet_sock *eo = ec_sk(sk);
-
-               addr.station = eo->station;
-               addr.net     = eo->net;
-               port         = eo->port;
-               cb           = eo->cb;
-       } else {
-               if (msg->msg_namelen < sizeof(struct sockaddr_ec)) {
-                       mutex_unlock(&econet_mutex);
-                       return -EINVAL;
-               }
-               addr.station = saddr->addr.station;
-               addr.net = saddr->addr.net;
-               port = saddr->port;
-               cb = saddr->cb;
-       }
+        if (saddr == NULL || msg->msg_namelen < sizeof(struct sockaddr_ec)) {
+                mutex_unlock(&econet_mutex);
+                return -EINVAL;
+        }
+        addr.station = saddr->addr.station;
+        addr.net = saddr->addr.net;
+        port = saddr->port;
+        cb = saddr->cb;
 
        /* Look for a device with the right network number. */

This way, if either ‘saddr’ is NULL or ‘msg->msg_namelen’ is less than the size of ‘sockaddr_ec’ structure it will immediately return with ‘-EINVAL’ (Invalid Argument) before reaching the code that triggers the NULL pointer dereference. If this is not the case, it will initialize the appropriate structures using ‘saddr’.

About these ads

Written by xorl

December 1, 2010 at 07:35

Posted in bugs, linux

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

Follow

Get every new post delivered to your Inbox.

Join 68 other followers