Re: [PATCH v2] Bluetooth: HIDP: fix missing length checks in hidp_input_report()
From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Date: 2026-05-20 22:03:23
Also in:
lkml, stable
Hi Muhammad, On Wed, May 20, 2026 at 5:41 PM Muhammad Bilal [off-list ref] wrote:
quoted hunk ↗ jump to hunk
hidp_input_report() reads keyboard and mouse payload data from an skb without first verifying that skb->len contains enough data. hidp_recv_intr_frame() pulls the 1-byte HIDP header before dispatching to hidp_input_report(). If a paired device sends a truncated packet, the handler reads beyond the valid skb data, resulting in an out-of-bounds read of skb data. The OOB bytes may be interpreted as phantom key presses or spurious mouse movement. Add a check that skb->len is non-zero before the type switch, and per-report-type minimum length checks before accessing the payload. Cc: stable@vger.kernel.org Signed-off-by: Muhammad Bilal <redacted> --- net/bluetooth/hidp/core.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 976f91eeb..03838a6ff 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c@@ -179,12 +179,22 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb) { struct input_dev *dev = session->input; unsigned char *keys = session->keys; - unsigned char *udata = skb->data + 1; - signed char *sdata = skb->data + 1; - int i, size = skb->len - 1; + unsigned char *udata; + signed char *sdata; + int i, size; + + if (!skb->len) + return; + + udata = skb->data + 1; + sdata = skb->data + 1; + size = skb->len - 1;
If you use skb_pull_data, you won't need to use pointer arithmetic, or store the actual size.
quoted hunk ↗ jump to hunk
switch (skb->data[0]) { case 0x01: /* Keyboard report */ + if (size < 8) + break; + for (i = 0; i < 8; i++) input_report_key(dev, hidp_keycode[i + 224], (udata[0] >> i) & 1);@@ -213,6 +223,9 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb) break; case 0x02: /* Mouse report */ + if (size < 3) + break; + input_report_key(dev, BTN_LEFT, sdata[0] & 0x01); input_report_key(dev, BTN_RIGHT, sdata[0] & 0x02); input_report_key(dev, BTN_MIDDLE, sdata[0] & 0x04); --2.54.0
-- Luiz Augusto von Dentz