summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2013-08-26 16:29:00 +0200
committerPeter Wu <lekensteyn@gmail.com>2013-08-26 16:50:54 +0200
commit7b4d06aed068de9b2d44f726aefeb34f5414109d (patch)
tree565cee286650bc107fe06b276c500f5917aad88a
parent00e4e5cdc593cfae27779b9013bc6701d9da9d57 (diff)
downloadlinux-7b4d06aed068de9b2d44f726aefeb34f5414109d.tar.gz
HID: logitech-dj: validate output report
Userspace can write data of arbitrary size and contents using the hidraw API. This patch adds validation of the data length and prevents reading too many bytes for short messages. The full report is now also copied, previously the last byte was missing from the report. I assume that 1 (report type) + report_count equals HIDPP_REPORT_LONG_LENGTH (or HIDPP_REPORT_SHORT_LENGTH for short reports). Signed-off-by: Peter Wu <lekensteyn@gmail.com>
-rw-r--r--drivers/hid/hid-logitech-dj.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
index 1f8d48acde7b..57470e36e147 100644
--- a/drivers/hid/hid-logitech-dj.c
+++ b/drivers/hid/hid-logitech-dj.c
@@ -696,25 +696,32 @@ static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
struct dj_receiver_dev *djrcv_dev = djdev->dj_receiver_dev;
struct hid_report* report;
struct hid_report_enum *output_report_enum;
+ u8 report_id = buf[0];
int i;
/* Called by hid raw to send data */
dbg_hid("%s\n", __func__);
- switch (buf[0]) {
+ switch (report_id) {
case REPORT_ID_HIDPP_SHORT:
+ if (count < HIDPP_REPORT_SHORT_LENGTH)
+ return -1;
+ break;
case REPORT_ID_HIDPP_LONG:
+ if (count < HIDPP_REPORT_LONG_LENGTH)
+ return -1;
break;
default:
return -1;
}
output_report_enum = &djrcv_dev->hdev->report_enum[HID_OUTPUT_REPORT];
- report = output_report_enum->report_id_hash[buf[0]];
+ report = output_report_enum->report_id_hash[report_id];
hid_set_field(report->field[0], 0, djdev->device_index);
- for (i = 2; i < HIDPP_REPORT_LONG_LENGTH - 1; i++)
- hid_set_field(report->field[0], i-1, buf[i]);
+ /* report type and device index are already set, append remaining data */
+ for (i = 1; i < report->field[0]->report_count; i++)
+ hid_set_field(report->field[0], i, buf[i + 1]);
hid_hw_request(djrcv_dev->hdev, report, HID_REQ_SET_REPORT);