xorl %eax, %eax

CVE-2011-0712: Linux kernel ALSA caiaq USB Driver String Buffer Overflow

leave a comment »

I decided to write about this because of this tweet by MWR Security Labs. The issue was reported by Rafa of the aforementioned company and part of the vulnerable code is available in sound/usb/caiaq/audio.c file.

int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)
{
        int i, ret;

        dev->n_audio_in  = max(dev->spec.num_analog_audio_in,
                               dev->spec.num_digital_audio_in) /
                                CHANNELS_PER_STREAM;
    ...
        dev->pcm->private_data = dev;
        strcpy(dev->pcm->name, dev->product_name);
    ...
        return 0;
}

This is the initialization routine of caiaq USB driver uses the insecure strcpy() routine to copy the device’s product name to the ALSA sound card name field. Here is the definition of the product name member:

#define CAIAQ_USB_STR_LEN 0xff
    ...
struct snd_usb_caiaqdev {
        struct snd_usb_audio chip;
    ...
        char product_name[CAIAQ_USB_STR_LEN];
    ...
        /* ALSA */
        struct snd_pcm *pcm;
    ...
};

Which resides in sound/usb/caiaq/device.h header file, and the sound card name field is defined in include/sound/pcm.h like this:

struct snd_pcm {
        struct snd_card *card;
    ...
        char name[80];
    ...
#endif
};

This vulnerability was patched by replacing the buggy strcpy() call.

        dev->pcm->private_data = dev;
-       strcpy(dev->pcm->name, dev->product_name);
+       strlcpy(dev->pcm->name, dev->product_name, sizeof(dev->pcm->name));
 
        memset(dev->sub_playback, 0, sizeof(dev->sub_playback));

In addition, the equivalent MIDI initialization routine contained the same vulnerability as you can see below.

int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device)
{
        int ret;
        struct snd_rawmidi *rmidi;

        ret = snd_rawmidi_new(device->chip.card, device->product_name, 0,
                                        device->spec.num_midi_out,
                                        device->spec.num_midi_in,
                                        &rmidi);
    ...
        strlcpy(rmidi->name, device->product_name, sizeof(rmidi->name));
    ...
        device->rmidi = rmidi;

        return 0;
}

Where the device name field of raw MIDI structure is also 80 Bytes long as we can read in include/sound/rawmidi.h header file. Once again, the fix was similar to the previous one.

                return ret;
 
-       strcpy(rmidi->name, device->product_name);
+       strlcpy(rmidi->name, device->product_name, sizeof(rmidi->name));
 
        rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX;

This vulnerability affects Linux kernel prior to 2.6.38-rc4-next-20110215 release. It’s important to note here that in Linux kernel strcpy() routine is written in assembly in most architectures. Consequently, as Eugene Teo quickly pointed out, this is architecture specific.
The reason I’m blogging about this is because MWR Security Labs released an advisory stating that this could result in kernel code execution using a special USB device that they have developed. I found it quite interesting exploitation approach although not very useful in real life.

Written by xorl

March 12, 2011 at 20:10

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