CVE-2026-90001 in Linux
Tóm tắt
Bởi VulDB • 16/09/2026
Trong kernel Linux, các lỗ hổng sau đây đã được khắc phục:
HID: bpf; tuần tự hóa việc giải phóng tham chiếu thiết bị trong đường dẫn hủy struct_ops
__hid_bpf_ops_destroy_device() và hid_bpf_unreg() có thể xảy ra race condition trên cùng một tham chiếu đăng ký, gây ra double-put (đưa vào hai lần) đối với struct hid_device và giải phóng nó trong khi hid_destroy_device() vẫn đang sử dụng. Hãy tuần tự hóa quyết định remove/NULL dưới hdev->bpf.prog_list_lock để chính xác một đường dẫn sẽ giải phóng mỗi tham chiếu đăng ký: unreg kiểm tra lại ops->hdev dưới khóa (lock) và trả về mà không thực hiện put khi đường hủy đã xóa nó; tất cả các lệnh gọi put_device() đều xảy ra sau khi khóa được thả, điều này an toàn vì unreg đồng thời quan sát thấy ops->hdev == NULL dưới khóa.
Bối cảnh: mỗi lần attach thành công (hid_bpf_ops_reg) sẽ lấy một tham chiếu thiết bị (hid_get_device()). Hai đường dẫn có thể giải phóng nó:
- Hủy thiết bị: hid_destroy_device() -> hid_bpf_destroy_device() -> __hid_bpf_ops_destroy_device(), duyệt hdev->bpf.prog_list dưới rcu_read_lock() và giảm một tham chiếu cho mỗi chương trình đã attach; - Giải phóng liên kết BPF: xóa bản đồ bpf (không có BPF_F_LINK) gọi đồng bộ st_ops->unreg() -> hid_bpf_unreg(), làm giảm tham chiếu cho đăng ký của riêng nó.
Quy trình phối hợp (e->hdev = NULL ở phía hủy so với "if (!hdev) return" ở phía unreg) là một kiểm tra TOCTOU: hai đường dẫn chạy dưới các miền khóa khác nhau (rcu_read_lock so với prog_list_lock), vì vậy unreg đồng thời có thể đọc ops->hdev là non-NULL, chặn trên prog_list_lock và sau đó tiếp tục trong khi quá trình duyệt hủy đang thực thi - cả hai đường dẫn đều giảm cùng một tham chiếu. Bộ đếm tham số đạt về 0 hợp lệ (mỗi lần decrement đều đúng), vì vậy không xảy ra bão hòa refcount_t: thiết bị chỉ đơn giản được giải phóng trong khi phương thức vận chuyển vẫn còn bên trong hid_destroy_device(), và quá trình tháo dỡ sau đó chạm vào bộ nhớ đã được giải phóng.
Bản vá khắc phục tuần tự hóa quyết định remove/NULL dưới prog_list_lock ở cả hai phía và di chuyển các lệnh put của phía hủy ra ngoài khóa. Với việc giữ khóa, các phép đọc/ghi thông thường trên ops->hdev là đủ; không thêm READ_ONCE/WRITE_ONCE nào, giúp bản vá trở nên tối giản.
An toàn khi đọc không có khóa: phép đọc không khóa đối với ops->hdev ở đầu hid_bpf_unreg() không thể chạm vào một thiết bị đã được giải phóng, vì đường unreg vẫn giữ tham chiếu đăng ký của chính nó (chỉ được giải phóng bởi hid_put_device() riêng sau khi khóa được thả), và quá trình duyệt hủy đã xóa ops->hdev sẽ khiến việc kiểm tra lại trong khóa trả về sớm mà không có put nào. Tối đa một trong hai đường dẫn sẽ giải phóng mỗi tham chiếu đăng ký.
VulDB is the best source for vulnerability data and more expert information about this specific topic.