Skip to content

Commit

Permalink
HID: Bluetooth: hidp: make sure input buffers are big enough
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David Herrmann authored and Jiri Kosina committed Feb 17, 2014
1 parent 218eb9e commit a4b1b58
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 2 deletions.
16 changes: 14 additions & 2 deletions net/bluetooth/hidp/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,16 @@ static void hidp_del_timer(struct hidp_session *session)
del_timer(&session->timer);
}

static void hidp_process_report(struct hidp_session *session,
int type, const u8 *data, int len, int intr)
{
if (len > HID_MAX_BUFFER_SIZE)
len = HID_MAX_BUFFER_SIZE;

memcpy(session->input_buf, data, len);
hid_input_report(session->hid, type, session->input_buf, len, intr);
}

static void hidp_process_handshake(struct hidp_session *session,
unsigned char param)
{
Expand Down Expand Up @@ -502,7 +512,8 @@ static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
hidp_input_report(session, skb);

if (session->hid)
hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
hidp_process_report(session, HID_INPUT_REPORT,
skb->data, skb->len, 0);
break;

case HIDP_DATA_RTYPE_OTHER:
Expand Down Expand Up @@ -584,7 +595,8 @@ static void hidp_recv_intr_frame(struct hidp_session *session,
hidp_input_report(session, skb);

if (session->hid) {
hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1);
hidp_process_report(session, HID_INPUT_REPORT,
skb->data, skb->len, 1);
BT_DBG("report len %d", skb->len);
}
} else {
Expand Down
4 changes: 4 additions & 0 deletions net/bluetooth/hidp/hidp.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#define __HIDP_H

#include <linux/types.h>
#include <linux/hid.h>
#include <linux/kref.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/l2cap.h>
Expand Down Expand Up @@ -179,6 +180,9 @@ struct hidp_session {

/* Used in hidp_output_raw_report() */
int output_report_success; /* boolean */

/* temporary input buffer */
u8 input_buf[HID_MAX_BUFFER_SIZE];
};

/* HIDP init defines */
Expand Down

0 comments on commit a4b1b58

Please sign in to comment.