diff options
author | Jiri Kosina <jkosina@suse.cz> | 2012-04-26 18:56:08 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2012-04-27 14:10:09 -0400 |
commit | b6787242f32700377d3da3b8d788ab3928bab849 (patch) | |
tree | 54428bcff5865df64980d0af4423d52b6c1dffa5 /drivers/hid/hidraw.c | |
parent | d4f0e4daf0d867f80c78ca4f9ac03a562e229e72 (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.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index cf7d6d58e79f..36fa77b40ffb 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, | |||
87 | len = list->buffer[list->tail].len > count ? | 87 | len = list->buffer[list->tail].len > count ? |
88 | count : list->buffer[list->tail].len; | 88 | count : list->buffer[list->tail].len; |
89 | 89 | ||
90 | if (copy_to_user(buffer, list->buffer[list->tail].value, len)) { | 90 | if (list->buffer[list->tail].value) { |
91 | ret = -EFAULT; | 91 | if (copy_to_user(buffer, list->buffer[list->tail].value, len)) { |
92 | goto out; | 92 | ret = -EFAULT; |
93 | goto out; | ||
94 | } | ||
95 | ret = len; | ||
93 | } | 96 | } |
94 | ret = len; | ||
95 | 97 | ||
96 | kfree(list->buffer[list->tail].value); | 98 | kfree(list->buffer[list->tail].value); |
97 | list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1); | 99 | list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1); |
@@ -437,19 +439,24 @@ static const struct file_operations hidraw_ops = { | |||
437 | .llseek = noop_llseek, | 439 | .llseek = noop_llseek, |
438 | }; | 440 | }; |
439 | 441 | ||
440 | void hidraw_report_event(struct hid_device *hid, u8 *data, int len) | 442 | int hidraw_report_event(struct hid_device *hid, u8 *data, int len) |
441 | { | 443 | { |
442 | struct hidraw *dev = hid->hidraw; | 444 | struct hidraw *dev = hid->hidraw; |
443 | struct hidraw_list *list; | 445 | struct hidraw_list *list; |
446 | int ret = 0; | ||
444 | 447 | ||
445 | list_for_each_entry(list, &dev->list, node) { | 448 | list_for_each_entry(list, &dev->list, node) { |
446 | list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC); | 449 | if (!(list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC))) { |
450 | ret = -ENOMEM; | ||
451 | break; | ||
452 | } | ||
447 | list->buffer[list->head].len = len; | 453 | list->buffer[list->head].len = len; |
448 | list->head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1); | 454 | list->head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1); |
449 | kill_fasync(&list->fasync, SIGIO, POLL_IN); | 455 | kill_fasync(&list->fasync, SIGIO, POLL_IN); |
450 | } | 456 | } |
451 | 457 | ||
452 | wake_up_interruptible(&dev->wait); | 458 | wake_up_interruptible(&dev->wait); |
459 | return ret; | ||
453 | } | 460 | } |
454 | EXPORT_SYMBOL_GPL(hidraw_report_event); | 461 | EXPORT_SYMBOL_GPL(hidraw_report_event); |
455 | 462 | ||