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>
This commit is contained in:
parent
218eb9ed84
commit
a4b1b5877b
|
@ -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)
|
||||
{
|
||||
|
@ -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:
|
||||
|
@ -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 {
|
||||
|
|
|
@ -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>
|
||||
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue