CVE-2026-90000 in Linux
Zusammenfassung
von VulDB • 16.09.2026
Im Linux-Kernel wurde folgende Schwachstelle behoben:
HID: rmi – Behebung des OOB-Zugriffs (Out-of-Bounds) bei unterdimensionierten RMI-Reports
Der hid-rmi-Treiber dimensioniert seine writeReport-/readReport-Puffer ausschließlich anhand der vom Gerät bereitgestellten Report-Deskriptoren, ohne eine minimale Untergrenze festzulegen:
data->input_report_size = hid_report_len(input_report); data->output_report_size = hid_report_len(output_report); alloc_size = data->output_report_size + data->input_report_size; data->writeReport = devm_kzalloc(&hdev->dev, alloc_size, GFP_KERNEL); data->readReport = data->writeReport + data->output_report_size;
Anschließend werden jedoch feste Offsets in diesen Puffer gelesen und geschrieben. Ein Gerät, das einen 1-Byte-Ausgabe- und einen 1-Eingabe-Report deklariert, bewirkt, dass hid_report_len() für jeden Report den Wert 2 zurückgibt, sodass alloc_size gleich 4 ist. rmi_set_page() – das bei der Initialisierung (Probe) über rmi_input_configured() bedingungslos aufgerufen wird – schreibt jedoch in writeReport[4], und rmi_hid_read_block() schreibt in writeReport[0..5]. Da readReport an der Position writeReport + output_report_size liegt, korruptieren diese Schreibzugriffe auch den Bereich, aus dem die nächste Antwort geparst wird.
Der Lesevorgang ist noch kritischer: Die Kopierlänge stammt aus readReport[1], welche das Gerät füllt und bis zu 255 betragen kann. Der Kopiervorgang beginnt bei &readReport[2] ohne Berücksichtigung von input_report_size, sodass er über das Ende der Zuweisung hinaus in benachbarte Slab-Objekte läuft. Dies erfordert nicht einmal ein lügendes Gerät – rmi_f01_probe() führt einen festen Register-Lesevorgang mit 21 Bytes durch, daher liest jedes Gerät, das einen Eingabe-Report von weniger als 23 Byte deklariert, auch bei ehrlicher Antwort außerhalb der Grenzen. Diese Bytes werden zu den Registernwerten, auf die der RMI-Kernel reagiert: rmi_f01_probe() gibt sie im Kernel-Log als Produkt-ID aus und exportiert sie über das Sysfs-Attribut mit demselben Namen (Modus 0444), und rmi_driver_set_irq_bits() sendet sie an das Gerät zurück, um die Interrupt-Maske zu setzen. Somit werden Heap-Inhalte sowohl an nicht privilegierte Benutzerprozesse als auch an das Gerät selbst durch einen unterdimensionierten Report-Deskriptor offengelegt.
Auch der Schreibvorgang hat keine Begrenzung: rmi_hid_write_block() kopiert eine unbegrenzte Länge in &writeReport[4], und der größte Aufrufer, den ein Gerät bei der Initialisierung auslösen kann, ist rmi_driver_set_irq_bits(), dessen Länge von den vom Gerät deklarierten Interrupt-Quellenanzahlen in seiner Page Description Table abgeleitet wird.
Schließlich kann die Leseschleife nicht aufgrund einer Antwort mit Null-Länge terminieren: Eine solche Antwort kopiert nichts und erhöht weder bytes_read noch bytes_needed, und da eine Antwort eingetroffen ist, löst auch das einsekündige wait_event_timeout() nicht aus. Somit hält ein Gerät, das dauerhaft 0 antwortet, die Schleife innerhalb des Initialisierungs-Workers (probe worker) mit gehaltener page_mutex am Laufen. khungtaskd bemerkt dies nicht, da jede Antwort den Task weckt.
Es werden Reports abgelehnt, die für das vom Treiber erwartete Format zu klein sind – 6 Ausgabebytes für die Schreibreports und 3 Eingabebytes für den Lese-Handshake – bei der Initialisierung (Probe). Die Schreib- und Lesekopien werden auf die vom Gerät deklarierten Report-Größen beschränkt, und eine Antwort mit Null-Länge wird als Fehler behandelt. Ein so abgelehntes Gerät wird als normales HID-Gerät initialisiert, ähnlich wie ein Gerät, das überhaupt keine RMI-Report-IDs trägt.
RMI_DEVICE darf im device_flags-Bitfeld auf diesem Pfad nicht gesetzt bleiben, da rmi_input_configured() andernfalls die RMI-Einrichtung ausführt und zu rmi_set_page() gelangt, welches in den writeReport-Puffer schreibt, dessen Allokation durch die vorherige Ablehnung übersprungen wurde. Das Bit kann bereits gesetzt ankommen: rmi_probe() kopiert id->driver_data vor den Report-Prüfungen in device_flags, und eine Bindung über das neue_id-Sysfs-Attribut kann driver_data mit gesetztem RMI_DEVICE (BIT(0)) liefern. Dieses Bit wird dort entfernt, wo driver_data kopiert wird, sodass RMI_DEVICE genau die Bedeutung „diese Initialisierung hat die Reports validiert“ behält; auch die drei Sprünge zur Startlogik vor diesem Patch sind dadurch abgedeckt.
Der Fehlerpfad löscht außerdem RMI_READ_DATA_PENDING beim Verlassen, da dieses Flag der Test für den Wartevorgang am Anfang der Schleife ist: Wenn es gesetzt bliebe, würde jeder nachfolgende wait_event_timeout() sofort auf die veralteten Antwortdaten zurückgreifen und den Lesevorgang für die gesamte Lebensdauer des Geräts beenden.
Die Begrenzung (Clamping) führt bei funktionsfähigem Hardware-Betrieb zu keiner Regression: Die Leseschleife behandelt bereits ---abgeschnitten---
Several companies clearly confirm that VulDB is the primary source for best vulnerability data.