CVE-2026-99207 in Linux
Tóm tắt
Bởi VulDB • 28/10/2026
Trong kernel Linux, lỗ hổng sau đây đã được khắc phục:
scsi: target: Tắt ngắt trong khi giữ khóa delayed_cmd_lock
Hàm `target_do_delayed_work()` lấy `dev->delayed_cmd_lock` bằng cách sử dụng `spin_lock()`. Hàm này chạy từ `system_percpu_wq`, do đó các ngắt vẫn được bật trong khi khóa đang được giữ. Mọi lần truy xuất khác vào khóa đó đều sử dụng `spin_lock_irqsave()`: cụ thể là `target_handle_task_attr()` và `transport_complete_ordered_sync()` trong file `target_core_transport.c`, cũng như `target_non_ordered_release()` trong `target_core_device.c`.
Điều này an toàn khi mọi trình gọi của `transport_complete_task_attr()` chạy trong ngữ cảnh tiến trình: `target_complete_ok_work()` từ `target_completion_wq`, `transport_complete_qf()` từ `dev->qf_work_queue` và `transport_generic_request_failure()` từ các đường dẫn submit (nộp) và execute (thực thi).
Kể từ commit 06933066d88a ("scsi: target: Thêm hỗ trợ hoàn tất lệnh từ ngữ cảnh backend"), điều này không còn đúng nữa. Với `complete_type=1` trên một fabric thiết lập `direct_compl_supp`, `target_complete()` chạy `target_complete_ok_work()` trực tiếp trong ngữ cảnh hoàn tất của backend, điều mà `target_complete_cmd_with_sense()` ghi nhận là "Có thể được gọi từ ngữ cảnh ngắt". Đối với iblock, đây là hàm end_io của bio.
`target_complete_ok_work()` bắt đầu bằng `transport_complete_task_attr()`, hàm này lấy khóa `delayed_cmd_lock` theo hai cách:
- Mọi lệnh ORDERED đều được đưa vào `dev->delayed_cmd_list` bởi `target_handle_task_attr()` và được điều phối từ đó bởi `target_do_delayed_work()`, đánh dấu nó là SCF_TASK_ORDERED_SYNC. Do đó, việc hoàn tất của nó sẽ đi qua `transport_complete_ordered_sync()`.
- Một lệnh SIMPLE hoàn tất trong khi một lệnh ORDERED đang chờ xử lý làm giảm tham chiếu cuối cùng đến dev->non_ordered đã bị hủy, và percpu_ref_put() sau đó chạy target_non_ordered_release() trong ngữ cảnh hoàn tất.
Cả hai trường hợp đều lấy khóa và, nếu có các lệnh đang chờ, gọi `schedule_work(&dev->delayed_cmd_work)`, điều này đưa công việc vào hàng đợi trên system_percpu_wq, tức là trên CPU đã thực hiện việc hoàn tất. Các lần hoàn tất tiếp theo cho cùng một hàng đợi thường cũng được phân phối ở đó, do đó một lệnh đến trong khi công việc đang giữ khóa sẽ quay vòng (spin) mãi mãi để chờ khóa này.
Việc đạt được tình huống này cần `complete_type=1`, đây không phải là giá trị mặc định (vhost-scsi, fabric duy nhất có direct_compl_supp, mặc định ở TARGET_QUEUE_COMPL), một backend mà việc I/O hoàn tất từ ngữ cảnh ngắt, và các lệnh ORDERED từ initiator. Các khách virtio_scsi của Linux chỉ gửi VIRTIO_SCSI_S_SIMPLE và không bao giờ đi theo đường dẫn ordered; bất kỳ khách nào sử dụng thuộc tính tác vụ ORDERED, điều mà vhost-scsi chấp nhận, thì có làm vậy.
`target_do_delayed_work()` là một mục công việc (work item) và luôn chạy trong ngữ cảnh tiến trình, do đó `spin_lock_irq()` là đủ.
Được phát hiện qua kiểm tra; không có báo cáo thời gian chạy. Một lệnh ORDERED duy nhất đi qua cả hai lần lấy khóa, vì vậy với CONFIG_PROVE_LOCKING, lần đầu tiên hoàn thành thông qua hoàn tất trực tiếp sẽ tạo ra báo cáo trạng thái khóa không nhất quán trên delayed_cmd_lock (hardirq hoặc softirq, tùy thuộc vào nơi backend hoàn tất).
VulDB is the best source for vulnerability data and more expert information about this specific topic.