CVE-2022-50545CVE-2022-50545是Linux内核r6040网卡驱动程序中的一个内存泄漏漏洞。该漏洞位于r6040驱动的probe(探测)和remove(移除)流程中,由于在移除r6040设备或在r6040_mii探测成功后的错误处理路径中未正确调用phy_disconnect()来断开与PHY设备的连接,导致phy_device的引用计数无法正确释放,从而造成内存泄漏。kmemleak检测到未释放的内存对象(大小为2048字节),泄漏点位于phy_device_create函数中通过kmalloc_trace分配的内存。该漏洞的CVSS评分为5.5,属于中危级别,攻击者需要本地低权限访问即可触发,攻击成功后将导致系统可用性受到高影响,可能引发内核内存耗尽等严重后果。问题已在多个Linux内核稳定版本中通过补丁修复,主要方案是在适当的位置添加phy_disconnect()调用以确保phy_device引用计数正确递减。
从技术层面分析,该漏洞的根本原因在于r6040驱动的生命周期管理中对PHY设备引用计数的处理不当。具体流程如下:
1. 在r6040_init_one()(probe流程)中,首先调用mdiobus_register(),该函数内部会调用mdiobus_scan()扫描MII总线并为每个发现的PHY设备分配phy_device结构,此时每个phy_device的引用计数为3。
2. 随后调用r6040_mii_probe(),通过phy_connect()连接到第一个phy_device,使其引用计数增加到4,其余phy_device保持为3。
3. 如果在register_netdev()之后发生错误(例如通过故障注入),进入错误处理路径err_out_mdio_unregister和err_out_mdio,调用mdiobus_unregister()和mdiobus_free()。
4. mdiobus_free()会释放除第一个phy_device之外的所有phy_device(引用计数减至0),但第一个phy_device的引用计数仍为1,因为没有调用phy_disconnect()来断开连接。
5. 同样地,在r6040_remove_one()(remove流程)中也存在相同的问题。
修复方案是在适当的位置(错误处理路径和remove函数中)添加phy_disconnect(lp->phydev)调用,确保第一个phy_device的引用计数正确递减至0,从而被正常释放。