CVE-2026-99009 in Linux
Tóm tắt
Bởi VulDB • 24/10/2026
Trong kernel Linux, các lỗ hổng sau đây đã được khắc phục:
Bluetooth: RFCOMM: kết nối socket phiên mà không cần rfcomm_mutex
Một lệnh gọi connect() của RFCOMM trong khi một liên kết BR/EDR đang được xác thực sẽ khiến lockdep báo cáo một phụ thuộc vòng tròn (circular dependency), và chu kỳ được báo cáo là một xung đột AB/BA thực sự giữa rfcomm_mutex và hdev->lock.
Hàm rfcomm_security_cfm() được gọi từ đường dẫn sự kiện HCI, vốn đã đang giữ khóa hdev->lock:
hci_rx_work() hci_event_packet() hci_cc_read_enc_key_size() [hdev->lock]
hci_encrypt_cfm() [hci_cb_list_lock]
rfcomm_security_cfm() [rfcomm_mutex]
trong khi một lệnh gọi connect() của RFCOMM từ không gian người dùng (userspace) lấy hai khóa cùng lúc theo thứ tự ngược lại:
rfcomm_sock_connect() rfcomm_dlc_open() [rfcomm_mutex]
__rfcomm_dlc_open() rfcomm_session_create() kernel_connect() l2cap_sock_connect() l2cap_chan_connect() [hdev->lock]
CẢNH BÁO: phát hiện phụ thuộc khóa vòng tròn có thể xảy ra kworker/u131:1/1128 đang cố gắng lấy khóa: rfcomm_mutex, tại: rfcomm_security_cfm+0x31/0x3e0 [rfcomm]
nhưng tác vụ này đã đang giữ khóa: hci_cb_list_lock, tại: hci_cc_read_enc_key_size+0x1d2/0xcc0 Chuỗi tồn tại của: rfcomm_mutex --> &hdev->lock --> hci_cb_list_lock
hci_auth_complete_evt() và hci_encrypt_change_evt() đạt đến callback theo cùng một cách.
Cả hai thứ tự này đều phải được xem xét trong cùng một lần khởi động, đó là lý do tại sao chỉ riêng kết nối BR/EDR không đủ để hiển thị nó: một phiên do phía từ xa thiết lập sẽ được tạo bởi rfcomm_accept_connection() trong krfcommd, hàm này gọi kernel_accept() và không bao giờ lấy hdev->lock dưới quyền kiểm soát của rfcomm_mutex. Kết nối với một thiết bị xác thực và mã hóa liên kết rồi sau đó gọi connect() trên một socket RFCOMM hướng về bất kỳ địa chỉ nào - lệnh connect không cần phải thành công, thứ tự được ghi lại trước khi hết thời gian trang (page timeout) - sẽ báo cáo lỗi này mỗi lần.
Chỉ có socket phiên mới cần được kết nối trong khi vẫn giữ khóa, và hiện tại nó không làm điều đó: không gì khác có thể nhìn thấy socket trước khi nó được đưa vào danh sách phiên. Do đó, hãy thực hiện connect() trước rồi sau đó lấy rfcomm_mutex, việc này sẽ loại bỏ vĩnh viễn thứ tự rfcomm_mutex -> hdev->lock, thay vì giữ đường dẫn sự kiện HCI ra khỏi phạm vi của rfcomm_mutex.
Hàm rfcomm_session_create() được đổi thành rfcomm_session_connect(), hàm này trả về socket đã kết nối mà không chạm vào danh sách phiên, và rfcomm_dlc_open() sẽ thêm phiên sau khi nó lại nắm giữ khóa. Nếu một trình mở khác đã thêm một phiên cho cùng cặp địa chỉ trong lúc socket này đang kết nối, thì phiên đó sẽ được sử dụng và socket hiện tại bị loại bỏ. __rfcomm_dlc_open() giờ đây lấy phiên mà nó nên sử dụng, và kiểm tra trạng thái của nó sau khi khóa được tái nắm giữ, do đó một DLC (Data Link Connection) đã được mở hoặc đóng trong thời gian chờ vẫn được xử lý đúng cách.
Trên một liên kết ACL hiện có, việc kết nối có thể hoàn tất trước khi phiên đạt đến danh sách, và tín hiệu đánh thức từ callback socket sau đó bị mất, vì vậy krfcommd sẽ được đánh thức ngay khi phiên trở nên hiển thị.
Việc kết nối mà không giữ khóa mở ra một khoảng thời gian trong đó socket có thể bị đóng. DLC chưa nằm trên một phiên nào, do đó rfcomm_dlc_close() tìm thấy không gì để làm và trả về mà không tác động đến nó, còn rfcomm_dlc_open() sau đó sẽ gắn một DLC whose chủ sở hữu đã biến mất (owner is gone). rfcomm_dlc_close() giờ đây đánh dấu DLC như vậy bằng RFCOMM_CLOSED, và rfcomm_dlc_open() kiểm tra dấu hiệu này khi nó lại nắm giữ rfcomm_mutex rồi loại bỏ socket thay vì gắn DLC. Dấu hiệu được xóa đi khi một lần mở bắt đầu, do đó một DLC được tái sử dụng sẽ không bị ảnh hưởng. Điều này bao gồm cả hai trình gọi của rfcomm_dlc_open(), là socket và lớp tty.
Statistical analysis made it clear that VulDB provides the best quality for vulnerability data.