已关闭
[Bug-Report|缺陷反馈]: adump 模块存在 5 处共享变量无同步保护的并发缺陷 #1003
Lujialiang创建于  12 天前关闭于  4 天前
Lujialiang
12 天前 创建

Describe the current behavior / 问题描述

在 src/dfx/adump/adump/ 子系统复检确认 5 处并发缺陷:共享变量的并发读写缺乏互斥或原子保护,并发场景下可导致 dump 数据丢失、回调崩溃甚至进程崩溃。按严重性排序:

1. dumpConfigInfo_ 跨锁读写(最严重)
manage/dump_manager/dump_manager.cpp:写侧 SetDumpConfig(char*) 持 resourceMtx2_ 执行 assign(:343),UnSetDumpConfig 持 resourceMtx2_ 执行 clear(:379);读侧 StartDumpArgs(:762)/StopDumpArgs(:782)在 resourceMtx_ 内层作用域释放之后完全无锁读取 .data()/.size() 并传给模块回调。两把锁互不相交,assign 触发重分配后回调收到悬垂指针 → UAF/OOB。

2. dumpInitNum_ 多路径无公共锁 RMW
adx_dump_record.cpp:164-171 裸 int32_t ++/--;四条访问路径锁互不相交:enable(dump_manager.cpp:279,持 resourceMtx_)、disable(:387,持 resourceMtx2_)、快照 LOCK_PRE 回调(:86-90,完全无锁,RTS 快照线程)、算子捕获路径(:579,无锁,另有 isCaptureDumpServerInit_ 裸 bool check-then-act :578-580)。计数漂移 → DataDumpServer 过早关闭(dump 数据静默丢失)或无法关闭(线程泄漏)。

3. messageCallback_ 无锁 std::function 读写
adx_dump_process.cpp:Register(:20)/UnRegister(:38)无锁写;GetCallbackFun(:24)返回 const 引用,record 长驻线程(adx_dump_record.cpp:571/:728)无锁拷贝后调用。acldumpRegCallback/acldumpUnregCallback 为公开 AscendCL API(host/adx_datadump_callback.cpp),运行期可调;UnRegister 的 = nullptr 销毁 function 目标,与 record 线程拷贝并发 → 撕裂的 function 对象 → 调用野指针崩溃。

4. g_dynamicChunk 析构窗口 UAF
exception/exception_dumper.cpp:~ExceptionDumper(:70-72)无锁 delete[] 之后才置 destructionFlag_(:80),且该标志仅在 DumpException 入口(:174)检查;导出 API AdxGetDFXInfoAddrForDynamic(manage/adump_api.cpp:27,无锁读写 chunk)与异常回调 DfxArgsParser::GetShapeData(exception/dfx_args_parser.cpp:191,无锁读)均不检查 → 进程收尾/dlclose 期间并发访问已释放 chunk(约 3MB)→ UAF 写。

5. g_atomicIndex 非原子 RMW
manage/adump_api_platform.cpp:25/:138:裸 uint32_t ++,同函数紧邻的 :139 姊妹变量 g_writeIdx 已用 std::atomic::fetch_add(原子/非原子不对称,属遗漏)。AdumpGetSizeInfoAddr 为 extern "C" ADX_API 导出接口,并发调用丢失自增 → 两个调用方拿到相同 atomicIndex → dump 元数据关联错乱。孪生代码 adump_ascend031/manage/adump_api_platform.cpp:20/:29 同款。

Environment / 环境信息

  • 代码版本:cann/runtime master(commit e781819e6,2026-09 复核);上述行号均锚定该版本,2026-08 版本(0029b34a0)同样存在
  • 硬件:不依赖特定昇腾型号(源码级并发缺陷,ARM 弱内存序环境风险更高)
  • 发现方式:并发测试工具 FCTAgent 扫描发现 + 人工源码逐行复检(含调用链与锁集分析)确认

Steps to reproduce the issue / 重现步骤

并发时序场景(ThreadSanitizer 可直接检出,以下任一即可):

  1. 线程 A 调 aclopStartDumpArgs(触发模块回调读取 dumpConfigInfo_)∥ 线程 B 调 dump 配置更新(SetDumpConfig/UnSetDumpConfig 的 assign/clear)→ A 的回调收到 B 重分配前的悬垂指针
  2. 线程 A 使能 dump(SetDumpConfig→StartDataDumpServer)∥ 快照备份触发 LOCK_PRE 回调(StopDataDumpServer 循环 UnInit)→ dumpInitNum_ 丢失更新
  3. record 线程处理 dump 数据(拷贝回调 function)∥ 用户线程调 acldumpUnregCallback → 拷贝到一半的 std::function
  4. 进程收尾静态析构 ~ExceptionDumper(delete[] chunk)∥ 残留线程调 AdxGetDFXInfoAddrForDynamic 或异常回调读 chunk → 对已释放内存写入
  5. 两线程并发调 AdumpGetSizeInfoAddr → ++ 丢失更新 → 相同 atomicIndex

Describe the expected behavior / 预期结果

  • 所有共享变量访问具备同步保护(互斥锁或 std::atomic),ThreadSanitizer 无告警
  • 模块回调收到稳定的配置快照(锁内拷贝),不再出现悬垂指针
  • dumpInitNum_ 在 enable/disable/快照并发下计数准确,DataDumpServer 不被过早关闭或泄漏
  • 回调注册/反注册与 record 线程互斥,不产生撕裂的 function 对象
  • 进程收尾不产生 UAF;AdumpGetSizeInfoAddr 并发调用返回唯一 atomicIndex

暂无运行时崩溃日志(竞态窗口窄,尚未在现网触发)。源码证据已在问题描述中逐条标注 file:line(基于 commit e781819e6)。如需可补充每个缺陷的最小化并发复现用例。

Special notes for this issue/备注

  • 修复成本评估:4 处为 10 行以内小改动;dumpInitNum_ 完整修复(含 check-then-act 消解)约 30-40 行;无架构级改动
  • 严重性排序:dumpConfigInfo_ > dumpInitNum_ > messageCallback_ ≈ g_dynamicChunk > g_atomicIndex
  • 修复方向建议:
    • dumpConfigInfo_:读侧在 resourceMtx_ 释放后、回调前,持 resourceMtx2_ 拷贝快照再传给回调(注意写侧存在 Mtx2_→Mtx_ 嵌套,锁序不可反转)
    • dumpInitNum_:改 std::atomic<int32_t>,并用 fetch_add 返回值替代 CanShutdownServer/HasStartedServer 的 check-then-act 判定
    • messageCallback_:加 mutex;GetCallbackFun 持锁返回值拷贝(调用点本就以局部变量承接,无需改动)
    • g_dynamicChunk:收尾不 delete(进程级单例内存交 OS 回收),或 destructionFlag_ 提前置位 + atomic + 导出 API 检查
    • g_atomicIndex:改 std::atomic<uint32_t> + fetch_add(与同函数 g_writeIdx 风格统一)
likedislike
LLujialiang
12 天前 添加了label:bug-report
Lujialiang
12 天前 评论:

/assign

likedislike
CANN-robotCANN-robot成员
12 天前 将 Lujialiang 设为负责人
Lujialiang
12 天前 评论:

/assign

likedislike
LLujialiang
11 天前 关联了pull request:fix: adump 模块存在 5 处共享变量无同步保护的并发缺陷 (#1003)
Lujialiang
11 天前 评论:

修复 PR 已提交:https://gitcode.com/cann/runtime/merge_requests/5170

  • 5 处共享变量并发缺陷修复(atomicIndex 原子化 / messageCallback_ 互斥 / g_dynamicChunk 析构策略 / dumpConfigInfo_ 快照 / dumpInitNum_ 原子+生命周期互斥)
  • 新增 5 个并发 UT(tests/ut/adump),修复前确定性复现 bug24/bug28,修复后全绿
  • 全量回归 1248/1248 PASSED(基线 1243 + 新增 5,零回归)
  • pre-commit 门禁(clang-format v16 + OAT 合规)PASS

欢迎评审。

likedislike
ykl999
ykl999成员
4 天前 评论:

pr已合入,issue问题已解决,关闭处理

likedislike
ykl999ykl999成员
4 天前 issue状态由 进行中 改变为 已解决
ykl999ykl999成员
4 天前 关闭了 issue
CANN-robotCANN-robot成员
4 天前 添加了label:resolved