Thread (9 messages) 9 messages, 5 authors, 2d ago

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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help