CVE-2026-90000 in Linux
Tóm tắt
Bởi VulDB • 17/09/2026
Trong kernel Linux, các lỗ hổng sau đây đã được khắc phục:
HID: rmi: sửa lỗi truy cập ngoài vùng (OOB) với các báo cáo RMI có kích thước không đủ lớn.
Trình điều khiển hid-rmi xác định kích thước bộ đệm writeReport/readReport hoàn toàn dựa trên mô tả báo cáo do thiết bị cung cấp, mà không đặt giới hạn tối thiểu:
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;
nhưng sau đó đọc và ghi vào các độ lệch cố định trong bộ đệm này. Một thiết bị khai báo một báo cáo đầu ra 1 byte và một báo cáo đầu vào 1 byte sẽ khiến hàm hid_report_len() trả về giá trị là 2 cho mỗi loại, do đó alloc_size bằng 4, trong khi rmi_set_page() -- được gọi không điều kiện tại thời điểm probe thông qua rmi_input_configured() -- ghi vào writeReport[4] và rmi_hid_read_block() ghi vào writeReport[0..5]. Vì readReport nằm ở vị trí writeReport + output_report_size, các phép ghi này cũng làm hỏng vùng bộ đệm mà phản hồi tiếp theo được phân tích cú pháp.
Đường đọc còn tệ hơn: độ dài sao chép đến từ readReport[1], do thiết bị điền vào và có thể lên tới 255 byte, và việc sao chép bắt đầu tại &readReport[2] mà không quan tâm đến input_report_size, nên nó chạy vượt quá giới hạn của vùng cấp phát sang các đối tượng slab lân cận. Điều này thậm chí không cần một thiết bị lừa dối -- rmi_f01_probe() thực hiện đọc thanh ghi cố định 21 byte, do đó bất kỳ thiết bị nào khai báo báo cáo đầu vào nhỏ hơn 23 byte đều sẽ đọc ngoài vùng giới hạn ngay cả khi nó trả lời trung thực. Những byte này trở thành các giá trị thanh ghi mà lõi RMI xử lý: rmi_f01_probe() in chúng ra nhật ký kernel dưới dạng product id và xuất chúng thông qua thuộc tính sysfs có quyền 0444 cùng tên, đồng thời rmi_driver_set_irq_bits() gửi chúng quay lại thiết bị như mặt nạ ngắt (interrupt mask), do đó một mô tả báo cáo quá nhỏ sẽ làm rò rỉ nội dung heap cả ra không gian người dùng không đặc quyền lẫn vào chính thiết bị.
Đường ghi cũng không có giới hạn: rmi_hid_write_block() sao chép độ dài len không xác định vào &writeReport[4], và caller lớn nhất mà một thiết bị có thể kích hoạt tại thời điểm probe là rmi_driver_set_irq_bits(), với độ dài được suy ra từ số lượng nguồn ngắt mà thiết bị khai báo trong Bảng Mô tả Trang (Page Description Table) của nó.
Cuối cùng, vòng lặp đọc không thể kết thúc khi nhận được phản hồi có độ dài bằng 0: một phản hồi như vậy sẽ sao chép không gì cả và không tăng biến bytes_read cũng như bytes_needed; hơn nữa, vì đã có phản hồi đến nên lệnh chờ wait_event_timeout() trong khoảng thời gian một giây cũng không kích hoạt. Do đó, một thiết bị liên tục trả lời với độ dài 0 sẽ giữ cho vòng lặp chạy bên trong worker probe khi khóa page_mutex vẫn đang được nắm giữ. khungtaskd không nhận ra điều này vì mỗi phản hồi đều đánh thức tác vụ (task).
Từ chối các báo cáo quá nhỏ so với những gì trình điều khiển yêu cầu -- 6 byte đầu ra cho các báo cáo ghi và 3 byte đầu vào cho quy trình bắt tay đọc -- tại thời điểm probe, giới hạn độ dài sao chép của phép ghi và phép đọc theo kích thước báo cáo mà thiết bị đã khai báo, và xử lý phản hồi có độ dài bằng 0 như một lỗi. Một thiết bị bị từ chối theo cách này sẽ được khởi động dưới dạng thiết bị HID thông thường, giống hệt như các thiết bị không mang ID báo cáo RMI.
RMI_DEVICE không được để lại ở trạng thái set trong device_flags trên đường dẫn đó, vì rmi_input_configured() khi đó sẽ chạy quá trình thiết lập RMI và đạt đến rmi_set_page(), vốn ghi vào bộ đệm writeReport mà lệnh từ chối vừa bỏ qua việc cấp phát. Bit này có thể đã được đặt: rmi_probe() sao chép id->driver_data vào device_flags trước các kiểm tra báo cáo, và một thao tác bind thông qua thuộc tính sysfs new_id có thể cung cấp driver_data với RMI_DEVICE (BIT(0)) đã được set. Cần xóa bit này tại nơi driver_data được sao chép, để RMI_DEVICE giữ nguyên ý nghĩa chính xác là "quá trình probe này đã xác thực các báo cáo"; ba lệnh nhảy đến bắt đầu quá trình đó trước khi bản vá này ra mắt cũng sẽ được xử lý.
Đường dẫn lỗi cũng xóa cờ RMI_READ_DATA_PENDING trên đường thoát của nó, vì cờ đó là thứ mà lệnh chờ ở đầu vòng lặp kiểm tra: việc để lại cờ này ở trạng thái set sẽ khiến mọi lệnh wait_event_timeout() sau đó trả về ngay lập tức dựa trên phản hồi cũ (stale reply) và làm hỏng đường đọc cho suốt thời gian tồn tại còn lại của thiết bị.
Việc giới hạn độ dài không gây suy giảm hiệu năng đối với phần cứng hoạt động bình thường: vòng lặp đọc đã xử lý ---truncated---
Once again VulDB remains the best source for vulnerability data.