codenote / google-security-research

Automatically exported from code.google.com/p/google-security-research
0 stars 0 forks source link

PicoLCD HID device driver pool overflow #101

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Nexus 7 config show enabled by default:

CONFIG_HID_PICOLCD=y

Structure with raw event registered:

From /devices/hid/hid-picolcd_core.c

static struct hid_driver picolcd_driver = {
    .name =          "hid-picolcd",
    .id_table =      picolcd_devices,
    .probe =         picolcd_probe,
    .remove =        picolcd_remove,
    .raw_event =     picolcd_raw_event,
#ifdef CONFIG_PM
    .suspend =       picolcd_suspend,
    .resume =        picolcd_resume,
    .reset_resume =  picolcd_reset_resume,
#endif
};
…

static int picolcd_raw_event(struct hid_device *hdev,
        struct hid_report *report, u8 *raw_data, int size)
{
    struct picolcd_data *data = hid_get_drvdata(hdev);
    unsigned long flags;
    int ret = 0;

    if (!data)
        return 1;

    if (report->id == REPORT_KEY_STATE) {
        if (data->input_keys)
            ret = picolcd_raw_keypad(data, report, raw_data+1, size-1);
    } else if (report->id == REPORT_IR_DATA) {
        ret = picolcd_raw_cir(data, report, raw_data+1, size-1);
    } else {
        spin_lock_irqsave(&data->lock, flags);
        /*
         * We let the caller of picolcd_send_and_wait() check if the
         * report we got is one of the expected ones or not.
         */
        if (data->pending) {
            // data->pending->raw_data fixed size 64 byte buffer
            // believe size can be > 65 bytes

            memcpy(data->pending->raw_data, raw_data+1, size-1);
            data->pending->raw_size  = size-1;
            data->pending->in_report = report;
            complete(&data->pending->ready);
        }
        spin_unlock_irqrestore(&data->lock, flags);
    }

    picolcd_debug_raw_event(data, hdev, report, raw_data, size);
    return 1;
}

From /devices/hid/hid-picolcd.h

struct picolcd_data {
    struct hid_device *hdev;
#ifdef CONFIG_DEBUG_FS
    struct dentry *debug_reset;
    struct dentry *debug_eeprom;
    struct dentry *debug_flash;
    struct mutex mutex_flash;
    int addr_sz;
#endif
    u8 version[2];
    unsigned short opmode_delay;
    /* input stuff */
    u8 pressed_keys[2];
    struct input_dev *input_keys;
#ifdef CONFIG_HID_PICOLCD_CIR
    struct rc_dev *rc_dev;
#endif
    unsigned short keycode[PICOLCD_KEYS];

#ifdef CONFIG_HID_PICOLCD_FB
    /* Framebuffer stuff */
    struct fb_info *fb_info;
#endif /* CONFIG_HID_PICOLCD_FB */
#ifdef CONFIG_HID_PICOLCD_LCD
    struct lcd_device *lcd;
    u8 lcd_contrast;
#endif /* CONFIG_HID_PICOLCD_LCD */
#ifdef CONFIG_HID_PICOLCD_BACKLIGHT
    struct backlight_device *backlight;
    u8 lcd_brightness;
    u8 lcd_power;
#endif /* CONFIG_HID_PICOLCD_BACKLIGHT */
#ifdef CONFIG_HID_PICOLCD_LEDS
    /* LED stuff */
    u8 led_state;
    struct led_classdev *led[8];
#endif /* CONFIG_HID_PICOLCD_LEDS */

    /* Housekeeping stuff */
    spinlock_t lock;
    struct mutex mutex;
    struct picolcd_pending *pending;
    int status;
#define PICOLCD_BOOTLOADER 1
#define PICOLCD_FAILED 2
#define PICOLCD_CIR_SHUN 4
};

…

struct picolcd_pending {
    struct hid_report *out_report;
    struct hid_report *in_report;
    struct completion ready;
    int raw_size;
    u8 raw_data[64];
};

Original issue reported on code.google.com by scvi...@google.com on 25 Aug 2014 at 5:42

GoogleCodeExporter commented 9 years ago

Original comment by scvi...@google.com on 25 Aug 2014 at 5:50

GoogleCodeExporter commented 9 years ago

Original comment by scvi...@google.com on 5 Sep 2014 at 8:26

GoogleCodeExporter commented 9 years ago

Original comment by haw...@google.com on 11 Sep 2014 at 9:25

GoogleCodeExporter commented 9 years ago

Original comment by scvi...@google.com on 13 Jan 2015 at 12:19