CVE-2023-53669CVE-2023-53669是Linux内核TCP子系统中存在的一个内存管理漏洞。该漏洞位于skb_copy_ubufs()函数中,与BIG TCP特性存在兼容性问题。当TCP发送零拷贝(tx zerocopy)使用大页(hugepages)且skb长度超过约68KB时,skb_copy_ubufs()函数会发生崩溃。
该漏洞的根本原因在于skb_copy_ubufs()函数的设计假设存在缺陷。该函数原本假设可以使用最多MAX_SKB_FRAGS个order-0页面来复制所有负载数据。然而,当启用BIG TCP特性后,单个skb可以容纳高达512KB的数据,这远远超出了原有假设所能处理的范围。当数据量超过order-0页面所能承载的容量时,函数会因无法正确分配足够的内存而导致系统崩溃。
该漏洞由David Ahern发现并报告。在Google内部环境中,由于使用了CONFIG_MAX_SKB_FRAGS=45配置并将gso_max_size限制为180000,因此未触发此漏洞。该漏洞的CVSS评分为5.5,属于中危级别。虽然需要本地低权限访问才能触发,但由于可用性影响为高,攻击者仍可能利用此漏洞导致系统拒绝服务(DoS)。
从技术层面分析,该漏洞涉及Linux内核网络栈中的内存管理机制。skb_copy_ubufs()函数负责在TCP零拷贝发送过程中复制用户态缓冲区数据到内核管理的skb(socket buffer)结构中。
在原始实现中,skb_copy_ubufs()使用MAX_SKB_FRAGS个order-0页面(每个页面4KB)来存储复制的数据。MAX_SKB_FRAGS默认值通常为17,因此理论上最多只能处理约68KB的数据(17 × 4KB)。
BIG TCP是Linux 5.16引入的特性,允许单个TCP skb承载更大的数据量,最高可达512KB。当使用TCP零拷贝发送且数据量超过68KB时,skb_copy_ubufs()尝试使用order-0页面分配内存,但分配的页面数量不足以容纳全部数据,导致内存越界访问或分配失败,最终引发系统崩溃。
漏洞利用条件包括:1)系统启用BIG TCP特性;2)使用TCP零拷贝发送(SO_ZEROCOPY);3)发送的数据包大小超过约68KB;4)使用大页(hugepages)内存。
修复方案v1使用更高阶(higher order)的页面分配来满足大skb的需求,但遗漏了__GFP_COMP标志位,导致内存泄漏。v2版本补充了__GFP_COMP标志,确保页面在释放时能够正确处理复合页(compound pages),避免了内存泄漏问题。