diff options
| author | David Herrmann <dh.herrmann@gmail.com> | 2013-12-19 06:09:32 -0500 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2014-02-17 15:17:55 -0500 |
| commit | a4b1b5877b514b276f0f31efe02388a9c2836728 (patch) | |
| tree | a09dd741c0a2b98db2ab8f71b45c5dc92efcc02c | |
| parent | 218eb9ed840c6279686ed6b0c3e31a083e241ff9 (diff) | |
HID: Bluetooth: hidp: make sure input buffers are big enough
HID core expects the input buffers to be at least of size 4096
(HID_MAX_BUFFER_SIZE). Other sizes will result in buffer-overflows if an
input-report is smaller than advertised. We could, like i2c, compute the
biggest report-size instead of using HID_MAX_BUFFER_SIZE, but this will
blow up if report-descriptors are changed after ->start() has been called.
So lets be safe and just use the biggest buffer we have.
Note that this adds an additional copy to the HIDP input path. If there is
a way to make sure the skb-buf is big enough, we should use that instead.
The best way would be to make hid-core honor the @size argument, though,
that sounds easier than it is. So lets just fix the buffer-overflows for
now and afterwards look for a faster way for all transport drivers.
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
| -rw-r--r-- | net/bluetooth/hidp/core.c | 16 | ||||
| -rw-r--r-- | net/bluetooth/hidp/hidp.h | 4 |
2 files changed, 18 insertions, 2 deletions
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 292e619db896..d9fb93451442 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
| @@ -430,6 +430,16 @@ static void hidp_del_timer(struct hidp_session *session) | |||
| 430 | del_timer(&session->timer); | 430 | del_timer(&session->timer); |
| 431 | } | 431 | } |
| 432 | 432 | ||
| 433 | static void hidp_process_report(struct hidp_session *session, | ||
| 434 | int type, const u8 *data, int len, int intr) | ||
| 435 | { | ||
| 436 | if (len > HID_MAX_BUFFER_SIZE) | ||
| 437 | len = HID_MAX_BUFFER_SIZE; | ||
| 438 | |||
| 439 | memcpy(session->input_buf, data, len); | ||
| 440 | hid_input_report(session->hid, type, session->input_buf, len, intr); | ||
| 441 | } | ||
| 442 | |||
| 433 | static void hidp_process_handshake(struct hidp_session *session, | 443 | static void hidp_process_handshake(struct hidp_session *session, |
| 434 | unsigned char param) | 444 | unsigned char param) |
| 435 | { | 445 | { |
| @@ -502,7 +512,8 @@ static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb, | |||
| 502 | hidp_input_report(session, skb); | 512 | hidp_input_report(session, skb); |
| 503 | 513 | ||
| 504 | if (session->hid) | 514 | if (session->hid) |
| 505 | hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0); | 515 | hidp_process_report(session, HID_INPUT_REPORT, |
| 516 | skb->data, skb->len, 0); | ||
| 506 | break; | 517 | break; |
| 507 | 518 | ||
| 508 | case HIDP_DATA_RTYPE_OTHER: | 519 | case HIDP_DATA_RTYPE_OTHER: |
| @@ -584,7 +595,8 @@ static void hidp_recv_intr_frame(struct hidp_session *session, | |||
| 584 | hidp_input_report(session, skb); | 595 | hidp_input_report(session, skb); |
| 585 | 596 | ||
| 586 | if (session->hid) { | 597 | if (session->hid) { |
| 587 | hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1); | 598 | hidp_process_report(session, HID_INPUT_REPORT, |
| 599 | skb->data, skb->len, 1); | ||
| 588 | BT_DBG("report len %d", skb->len); | 600 | BT_DBG("report len %d", skb->len); |
| 589 | } | 601 | } |
| 590 | } else { | 602 | } else { |
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h index ab5241400cf7..8798492a6e99 100644 --- a/net/bluetooth/hidp/hidp.h +++ b/net/bluetooth/hidp/hidp.h | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #define __HIDP_H | 24 | #define __HIDP_H |
| 25 | 25 | ||
| 26 | #include <linux/types.h> | 26 | #include <linux/types.h> |
| 27 | #include <linux/hid.h> | ||
| 27 | #include <linux/kref.h> | 28 | #include <linux/kref.h> |
| 28 | #include <net/bluetooth/bluetooth.h> | 29 | #include <net/bluetooth/bluetooth.h> |
| 29 | #include <net/bluetooth/l2cap.h> | 30 | #include <net/bluetooth/l2cap.h> |
| @@ -179,6 +180,9 @@ struct hidp_session { | |||
| 179 | 180 | ||
| 180 | /* Used in hidp_output_raw_report() */ | 181 | /* Used in hidp_output_raw_report() */ |
| 181 | int output_report_success; /* boolean */ | 182 | int output_report_success; /* boolean */ |
| 183 | |||
| 184 | /* temporary input buffer */ | ||
| 185 | u8 input_buf[HID_MAX_BUFFER_SIZE]; | ||
| 182 | }; | 186 | }; |
| 183 | 187 | ||
| 184 | /* HIDP init defines */ | 188 | /* HIDP init defines */ |
