xorl %eax, %eax

CVE-2011-0521: Linux kernel av7110 Array Index Integer Overflow

with 2 comments

This is a neat missing boundary check discovered by Dan Carpenter (aka error27) that affects Linux kernel prior to 2.6.38-rc2 release. The vulnerability resides in the code of the av7110 kernel module which is used by some DVB (Digital Video Broadcasting) cards. The exact code can be found at drivers/media/dvb/ttpci/av7110_ca.c like this.

static int dvb_ca_ioctl(struct file *file, unsigned int cmd, void *parg)
{
        struct dvb_device *dvbdev = file->private_data;
        struct av7110 *av7110 = dvbdev->priv;
        unsigned long arg = (unsigned long) parg;

        dprintk(8, "av7110:%p\n",av7110);

        switch (cmd) {
    ...
        case CA_GET_SLOT_INFO:
        {
                ca_slot_info_t *info=(ca_slot_info_t *)parg;

                if (info->num > 1)
                        return -EINVAL;
                av7110->ci_slot[info->num].num = info->num;
                av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ?
                                                        CA_CI_LINK : CA_CI;
                memcpy(info, &av7110->ci_slot[info->num], sizeof(ca_slot_info_t));
                break;
        }
    ...
        default:
                return -EINVAL;
        }
        return 0;
}

This IOCTL handler contains the above command (CA_GET_SLOT_INFO) which directly uses a user derived integer (info->num) as an index value for the ‘av7110->ci_slot[]’ array. Additionally, it performs a write operation in this location using the aforementioned user controlled integer value. If we have a look at drivers/media/dvb/ttpci/av7110.h header file we will see this definition.

/* place to store all the necessary device information */
struct av7110 {

        /* devices */
    ...
        /* CA */

        ca_slot_info_t          ci_slot[2];
    ...
};

That said, by providing any negative value, the attacker can perform a fairly reliable arbitrary kernel memory write. Of course, the fix to this bug was to add the missing boundary check.

 		ca_slot_info_t *info=(ca_slot_info_t *)parg;
 
-		if (info->num > 1)
+		if (info->num < 0 || info->num > 1)
 			return -EINVAL;
 		av7110->ci_slot[info->num].num = info->num;

This way it only allows positive values of either 0 or 1.

Written by xorl

April 23, 2011 at 11:16

Posted in bugs, linux

2 Responses

Subscribe to comments with RSS.

  1. xorl, you’ve described this vuln twice :)
    here and in january (https://xorl.wordpress.com/2011/01/30/cve-2011-0521-linux-kernel-av7110-dvb-invalid-array-index-value/)

    ooo

    February 28, 2012 at 11:55

  2. LOL!!!
    Nice one, didn’t even notice this!

    xorl

    March 16, 2012 at 17:06


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