lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250710-report-size-null-v2-4-ccf922b7c4e5@kernel.org>
Date: Thu, 10 Jul 2025 16:01:36 +0200
From: Benjamin Tissoires <bentiss@...nel.org>
To: Jiri Kosina <jikos@...nel.org>, Alan Stern <stern@...land.harvard.edu>, 
 Shuah Khan <shuah@...nel.org>
Cc: linux-input@...r.kernel.org, linux-kernel@...r.kernel.org, 
 linux-kselftest@...r.kernel.org, Benjamin Tissoires <bentiss@...nel.org>
Subject: [PATCH v2 4/4] selftests/hid: add a test case for the recent
 syzbot underflow

Syzbot found a buffer underflow in __hid_request(). Add a related test
case for it.

It's not perfect, but it allows to catch a corner case when a report
descriptor is crafted so that it has a size of 0.

Signed-off-by: Benjamin Tissoires <bentiss@...nel.org>
---
 tools/testing/selftests/hid/tests/test_mouse.py | 70 +++++++++++++++++++++++++
 1 file changed, 70 insertions(+)

diff --git a/tools/testing/selftests/hid/tests/test_mouse.py b/tools/testing/selftests/hid/tests/test_mouse.py
index 66daf7e5975ca50f0b065080669d7f6123fb177f..eb4e15a0e53bd5f3c8e0ea02365ff9da7eead93d 100644
--- a/tools/testing/selftests/hid/tests/test_mouse.py
+++ b/tools/testing/selftests/hid/tests/test_mouse.py
@@ -439,6 +439,68 @@ class BadResolutionMultiplierMouse(ResolutionMultiplierMouse):
         return 32  # EPIPE
 
 
+class BadReportDescriptorMouse(BaseMouse):
+    """
+    This "device" was one autogenerated by syzbot. There are a lot of issues in
+    it, and the most problematic is that it declares features that have no
+    size.
+
+    This leads to report->size being set to 0 and can mess up with usbhid
+    internals.  Fortunately, uhid merely passes the incoming buffer, without
+    touching it so a buffer of size 0 will be translated to [] without
+    triggering a kernel oops.
+
+    Because the report descriptor is wrong, no input are created, and we need
+    to tweak a little bit the parameters to make it look correct.
+    """
+
+    # fmt: off
+    report_descriptor = [
+        0x96, 0x01, 0x00,              # Report Count (1)                    0
+        0x06, 0x01, 0x00,              # Usage Page (Generic Desktop)        3
+        # 0x03, 0x00, 0x00, 0x00, 0x00,  # Ignored by the kernel somehow
+        0x2a, 0x90, 0xa0,              # Usage Maximum (41104)               6
+        0x27, 0x00, 0x00, 0x00, 0x00,  # Logical Maximum (0)                 9
+        0xb3, 0x81, 0x3e, 0x25, 0x03,  # Feature (Cnst,Arr,Abs,Vol)          14
+        0x1b, 0xdd, 0xe8, 0x40, 0x50,  # Usage Minimum (1346431197)          19
+        0x3b, 0x5d, 0x8c, 0x3d, 0xda,  # Designator Index                    24
+    ]
+    # fmt: on
+
+    def __init__(
+        self, rdesc=report_descriptor, name=None, input_info=(3, 0x045E, 0x07DA)
+    ):
+        super().__init__(rdesc, name, input_info)
+        self.high_resolution_report_called = False
+
+    def get_evdev(self, application=None):
+        assert self._input_nodes is None
+        return (
+            "Ok"  # should be a list or None, but both would fail, so abusing the system
+        )
+
+    def next_sync_events(self, application=None):
+        # there are no evdev nodes, so no events
+        return []
+
+    def is_ready(self):
+        # we wait for the SET_REPORT command to come
+        return self.high_resolution_report_called
+
+    def set_report(self, req, rnum, rtype, data):
+        if rtype != self.UHID_FEATURE_REPORT:
+            raise InvalidHIDCommunication(f"Unexpected report type: {rtype}")
+        if rnum != 0x0:
+            raise InvalidHIDCommunication(f"Unexpected report number: {rnum}")
+
+        if len(data) != 1:
+            raise InvalidHIDCommunication(f"Unexpected data: {data}, expected '[0]'")
+
+        self.high_resolution_report_called = True
+
+        return 0
+
+
 class ResolutionMultiplierHWheelMouse(TwoWheelMouse):
     # fmt: off
     report_descriptor = [
@@ -975,3 +1037,11 @@ class TestMiMouse(TestWheelMouse):
             # assert below print out the real error
             pass
         assert remaining == []
+
+
+class TestBadReportDescriptorMouse(base.BaseTestCase.TestUhid):
+    def create_device(self):
+        return BadReportDescriptorMouse()
+
+    def assertName(self, uhdev):
+        pass

-- 
2.49.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ