CVE-2022-50480CVE-2022-50480是Linux内核pl353-smc(Static Memory Controller)驱动中的一个引用计数泄漏漏洞,位于pl353_smc_probe()函数中。该漏洞源于在遍历设备树子节点时,for_each_available_child_of_node()循环的break路径缺少对应的of_node_put()调用,导致设备树节点引用未被正确释放,从而造成引用计数泄漏。
pl353-smc是Xilinx Zynq系列SoC中用于控制静态存储设备(如NOR Flash、SRAM等)的外设控制器。该驱动在系统启动或设备热插拔时被调用,pl353_smc_probe()函数负责遍历设备树中所有可用的子节点,并为每个匹配的子节点创建平台设备。
该漏洞的影响范围限于本地攻击场景,需要低权限即可触发。虽然机密性和完整性不受影响,但可能导致系统可用性下降,因为泄漏的引用计数会持续占用内核内存资源,长期运行可能导致内存耗尽或系统不稳定。该漏洞已在多个稳定内核版本中得到修复,包括5.10.x、5.15.x、5.19.x及6.0.x等系列。
该漏洞的技术原理涉及Linux内核设备树(Device Tree)API的引用计数管理机制。在Linux内核中,for_each_available_child_of_node()宏在遍历设备树时会获取子节点的引用计数(reference count),按照内核编码规范,每次获取引用都必须在不再使用时通过of_node_put()释放,否则将导致引用计数泄漏。
在pl353_smc_probe()函数中,原有代码逻辑如下:
1. 使用for_each_available_child_of_node()遍历设备树的可用子节点
2. 在循环中调用of_match_node()匹配兼容的设备节点
3. 当匹配成功时,调用of_platform_device_create()创建平台设备
4. 如果匹配失败(!match),则通过break跳出循环
问题在于break跳出循环时,'child'节点引用未被释放。虽然of_platform_device_create()会为'child'创建一个新的引用(该函数内部已考虑了引用计数管理),但在!match路径下没有创建新引用,却也没有调用of_node_put()释放原有引用,导致引用计数永久增加。
利用方式:攻击者无需特殊权限即可触发,只需在受影响系统上加载或初始化pl353-smc驱动即可导致每次匹配失败时泄漏一个引用计数。虽然单次泄漏影响有限,但通过反复触发(如设备热插拔、模块重载等),可以累积大量泄漏的引用计数,最终耗尽内核内存资源,影响系统可用性。