summaryrefslogtreecommitdiffstats
path: root/drivers/hid/hidraw.c
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2012-04-27 00:56:08 +0200
committerJiri Kosina <jkosina@suse.cz>2012-04-27 20:10:09 +0200
commitb6787242f32700377d3da3b8d788ab3928bab849 (patch)
tree54428bcff5865df64980d0af4423d52b6c1dffa5 /drivers/hid/hidraw.c
parentd4f0e4daf0d867f80c78ca4f9ac03a562e229e72 (diff)
HID: hidraw: add proper error handling to raw event reporting
If kmemdup() in hidraw_report_event() fails, we are not propagating this fact properly. Let hidraw_report_event() and hid_report_raw_event() return an error value to the caller. Reported-by: Oliver Neukum <oneukum@suse.de> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hidraw.c')
-rw-r--r--drivers/hid/hidraw.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index cf7d6d58e79..36fa77b40ff 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -87,11 +87,13 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count,
len = list->buffer[list->tail].len > count ?
count : list->buffer[list->tail].len;
- if (copy_to_user(buffer, list->buffer[list->tail].value, len)) {
- ret = -EFAULT;
- goto out;
+ if (list->buffer[list->tail].value) {
+ if (copy_to_user(buffer, list->buffer[list->tail].value, len)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ ret = len;
}
- ret = len;
kfree(list->buffer[list->tail].value);
list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1);
@@ -437,19 +439,24 @@ static const struct file_operations hidraw_ops = {
.llseek = noop_llseek,
};
-void hidraw_report_event(struct hid_device *hid, u8 *data, int len)
+int hidraw_report_event(struct hid_device *hid, u8 *data, int len)
{
struct hidraw *dev = hid->hidraw;
struct hidraw_list *list;
+ int ret = 0;
list_for_each_entry(list, &dev->list, node) {
- list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC);
+ if (!(list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC))) {
+ ret = -ENOMEM;
+ break;
+ }
list->buffer[list->head].len = len;
list->head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1);
kill_fasync(&list->fasync, SIGIO, POLL_IN);
}
wake_up_interruptible(&dev->wait);
+ return ret;
}
EXPORT_SYMBOL_GPL(hidraw_report_event);