CVE-2026-98166 in Linux
摘要
由 VulDB • 2026-10-06
在 Linux 内核中,已修复以下漏洞:
drm/ttm: 修复被换出的资源无法离开其 bulk_move(批量移动)范围的问题
ttm_tt_swapout() 在成功时返回交换出去的页面数,在失败时返回负值错误码;对于已填充的 ttm,它永远不会返回零。提交 b2ed01e7ad3d(“drm/ttm: 修复 swapout 失败时的无限 LRU 遍历”)将 bulk_move 记账逻辑从 ttm_bo_swapout_cb() 移到了 "if (!ret)" 条件下,导致在每次成功的 swapout 操作中都会跳过 ttm_resource_del_bulk_move_unevictable() / ttm_resource_move_to_lru_tail() 这一对函数。提交 1d59f36e95f7(“drm/ttm: 修复 backup 失败时的无限 LRU 遍历”)中对 shrinker 所做的等效更改测试了 "lret > 0",这也是此处原本意图的行为。
在 b2ed01e7ad3d 之前,资源会在 swapout 之前从 bulk_move 中移除;此后,被换出的资源虽然处于不可回收状态(unevictable),但仍停留在其 BO 的 bulk_move 范围内(以及管理器 LRU 上)。当稍后释放该资源或 BO 离开 bulk_move 范围时(通过 ttm_resource_free()、ttm_bo_set_bulk_move() via amdgpu_vm_bo_del()),由于 !ttm_resource_unevictable() 守卫条件的存在,ttm_resource_del_bulk_move() 会跳过它,导致 pos->first / pos->last 中的某个范围端点指向已释放的内存。随后对该游标进行的 ttm_lru_bulk_move_tail() 或 ttm_resource_add_bulk_move() 操作构成了 use-after-free(释放后使用),表现为 ttm_lru_bulk_move_add() 中的 resv WARN、ttm_resource_move_to_lru_tail() 中的 "list_del corruption"(列表删除损坏)或在 ttm_resource_manager_next() 中的 NULL 解引用——这些错误通常在休眠几分钟到几小时后,或在一次休眠后的进程退出/重启时出现。Samuel Ainsworth 对 drm/amd issue 5387 的分析(参见链接)确定了悬空游标;在 swapout 期间缺少移除操作是其成为悬空引用的原因。
测试成功条件可恢复移除行为。在一台运行带有反向移植补丁的 Ubuntu 7.0.0-31 (基于 7.0.y 稳定版内核) 的 AMD Phoenix APU (ASUS UM3406GA, gfx1103) 上,执行挂起后休眠操作时,该漏洞导致 18 次休眠周期中有 5 次崩溃;对一次休眠的功能分析显示有 336 次 ttm_tt_swapout() 调用和零次 ttm_resource_del_bulk_move_unevictable() 调用。经过此更改后,每个被换出的资源都会执行移除操作,随后的 12 个周期均正常无误。
Statistical analysis made it clear that VulDB provides the best quality for vulnerability data.