已关闭
[Bug-Report|缺陷反馈]: 不安全的动态库加载(CWE-426):`dlopen()`使用裸库名 libruntime.so,以及LoadTilingLibrary() 对外接收任意 so 路径并 dlopen(),仅 realpath() 无完整性校验 #529
P1GGYii创建于  4月23日关闭于  6月8日
P1GGYii
4月23日 创建

Thanks for sending an issue! Please fill in the following template to help quickly solve your problem.

Describe the current behavior / 问题描述 (Mandatory / 必填)

BUG1

文件1:impl/adv_api/tiling/hccl/hccl_symbol_loader.h
文件2: impl/adv_api/tiling/hccl/hccl_tiling.cpp

在文件2中存在调用

auto getSocVerFunc =
  HcclSymbolLoader::GetInstance().Load<void (*)(char*, uint32_t)>(
    "libruntime.so", "rtGetSocVersion");

Load函数实现为文件1中
HcclSymbolLoader::Load(const std::string& soName, ...) 使用 dlopen(soName.c_str(), ...) 加载动态库,其中 soName 是函数入参(变量)。
dlopen() 接收裸库名时,将触发动态链接器的库搜索路径解析。如果库搜索路径(例如 LD_LIBRARY_PATH、RUNPATH/RPATH、默认搜索目录的顺序)被攻击者影响,可能优先解析到攻击者植入的同名 libruntime.so,从而造成库注入 → 任意代码执行(RCE)。

BUG2

文件1:impl/utils/context/context_builder.cpp
文件2: docs/api/context/GetTilingFunc.md

LoadTilingLibrary() 存在可能接收外部传入的 tilingSoPath,对其仅做空指针/长度检查,并调用 realpath() 将其解析为绝对路径后直接执行:

handle = dlopen(absFilePath.c_str(), RTLD_LAZY);

在这种情况下并不能保证该路径位于受信目录、也不能验证该 .so 是否可信,或者说是否被篡改。在攻击者能够控制/影响 tilingSoPath 指向,或能够在目标路径放置恶意 .so 的情况下,就会出现任意代码执行(RCE)的情况:恶意 .so 在 dlopen() 时执行(构造函数/初始化代码等),权限为 SDK/宿主进程权限,以及进一步的敏感信息泄露、结果篡改、持久化植入等。

Environment / 环境信息 (Mandatory / 必填)

Steps to reproduce the issue / 重现步骤 (Mandatory / 必填)

Describe the expected behavior / 预期结果 (Mandatory / 必填)

  1. 不直接 dlopen(soName)。若 soName 不是绝对路径,则在受信目录 allowlist 中解析成绝对路径后再加载;若无法解析到受信目录内,则拒绝。对最终 realpath 结果做 allowlist 校验。
  2. 可做完整性校验:对允许加载的 tiling so 做签名/哈希校验,或提供“仅加载签名插件”开关。或者添加受信目录白名单校验。

Special notes for this issue/备注 (Optional / 选填)

likedislike
P1GGYii
4月23日 评论:

您好,感谢您的时间,另一个类型问题错误如下:

空指针解引用(CWE-476)

malloc() 失败未中止导致空指针被传入文件读取(潜在崩溃/DoS)

文件:impl/utils/context/context_builder_impl.cpp
函数:context_ascendc::ContextBuilderImpl::AddInputTd(int32_t, ge::DataType, ge::Format, ge::Format, gert::StorageShape, const std::string &filePath)

AddInputTd(..., filePath)中,代码使用 malloc() 分配缓冲区用于读取二进制文件。但当 malloc() 返回 nullptr 时,函数仅记录日志而未返回或进行错误处理,仍继续调用 ReadBinFile(),把空指针作为读入目标缓冲区传入,导致在 ReadBinFile() 内部可能对空指针写入,从而触发未定义行为。

分配点(source):在 AddInputTd(..., filePath) 中分配缓冲区:

void *buffer = malloc(static_cast<size_t>(tensorSize));

错误处理缺失(missing check/early return):当 malloc 失败时只打印日志,不中止流程:

if (buffer == nullptr) {
    CXT_ASCENDC_LOGE("AddInputTd %d failed, alloc device memory failed.", index);
}
// 这里没有 return / 没有置 errFlag_ / 没有 free(也无从 free)

危险调用(sink):继续将 buffer 传入 ReadBinFile():

if (!context_ascendc::DataUtils::ReadBinFile(filePath, buffer, static_cast<size_t>(tensorSize))) {
    ...
}

触发点(dereference/write to nullptr):ReadBinFile() 内部无 buf == nullptr 防护,直接进行读入:

inFile.read(reinterpret_cast<char *>(buf), bufferLen);

应该在buffer为空时提前返回。

likedislike
pandengpandeng成员
4月25日 将 myx_32 设为负责人
pandengpandeng成员
4月25日 将 zhangyike 设为负责人
pandeng
pandeng成员
4月25日 评论:

@P1GGYii 你好,感谢关注。
@myx_32 会处理您的第一个问题的bug1
@zhangyike 会处理您的第二个问题。

likedislike
zhangyike成员
5月11日 评论:

非常感谢您反馈的问题。相关的修复代码已经合入主分支,问题应该已经解决。

likedislike
Zzhangyike成员
5月11日 issue状态由 待办的 改变为 已解决
Zzhangyike成员
5月11日 关闭了 issue
Zzhangyike成员
5月11日 issue状态由 已解决 改变为 待办的
Zzhangyike成员
5月11日 重新打开了 issue
myx_32成员
5月19日 评论:

方案分析中

likedislike
myx_32成员
6月8日 评论:

非常感谢您反馈的问题。相关的修复代码已经合入主分支,问题应该已经解决。

likedislike
Mmyx_32成员
6月8日 issue状态由 待办的 改变为 已完成
Mmyx_32成员
6月8日 关闭了 issue
CANN-robotCANN-robot成员
6月8日 添加了label:Accepted
CANN-robotCANN-robot成员
6月8日 添加了label:resolved