/assign @Reyn52166


你好,该安全问题已收到,我们排查一下TprtCqHandleGetCqe 相关代码


@syaunfang
当前问题产生的前提是TprtCqReportRecv属于api,并且接受外部入参。
事实上,tprt_api.h里面声明的接口,并非外部api,头文件不会对外发布,so文件也只被runtime内部代码调用,在当前的调用路径上
XpuDriver::LogicCqReportV2 ->TprtCqReportRecv->TprtCqHandleGetCqe
LogicCqReportV2的内存report 和reportCnt是匹配的,并且内存足够存放。所以不存在代码问题。


@sunnana_004434229 针对这些问题,可能产生了误解,需将tprt_api.h改名或增加说明,为内部api,非外部可见。


@syaunfang 感谢反馈。针对该问题,我们已完成初步分析并形成统一整改方案:计划将 libxpu_tprt.so 调整为仅构建期使用的静态库,内部链接到 Runtime v100/v200,同时隐藏 Tprt*、cce::tprt::*等动态符号,并清理相关安装及打包清单,确保交付包不再包含 libxpu_tprt.so 或 libxpu_tprt.a。
该方案将收口 TprtCqReportRecv、TprtSqPushTask 等内部接口通过动态链接或 dlsym 被外部直接调用的路径,并保留现有 Runtime 内部调用链。后续还将补充必要的输入健壮性检查,并完成动态依赖、符号表、安装包、功能回归及升级回滚验证。目前正在修改代码并进行依赖和兼容性确认,有进一步进展会及时同步。


@syaunfang 您好,TPRT 内部接口暴露问题已完成整改和验证,相关修改已提交代码仓,如果您后续有新的进展或诉求,欢迎随时重新开启此 Issue 或提交新的 Issue,我们会继续为您跟进。


【runtime】TPRT-003: CQ 报告接收接口缓冲区越界写入
基本信息
src/tprt/feature/src/tprt_cqhandle.ccTprtCqHandle::TprtCqHandleGetCqe漏洞描述
TprtCqHandleGetCqe函数将内部完成队列(CQ)中的 CQE 报告条目写入用户提供的缓冲区cqeAddr。循环写入的数量由min(队列可用条目数, cqeInfo->cqeNum)决定。核心问题:
cqeNum完全由用户控制,API 仅验证其非零(cqeNum != 0)和缓冲区指针非空(cqeAddr != nullptr),但从未验证cqeAddr指向的缓冲区实际大小是否能容纳cqeNum个TprtCqeReport_t结构体。攻击者可声明一个较大的
cqeNum(如 1024),同时提供一个远小于所需空间的缓冲区。当内部队列中存在足够多的待报告 CQE 时,函数将向缓冲区写入超出其边界的数据,造成堆或栈缓冲区溢出。漏洞代码
文件:
src/tprt/feature/src/tprt_cqhandle.cc,第 60-78 行void TprtCqHandle::TprtCqHandleGetCqe(TprtReportCqeInfo_t* cqeInfo) { uint16_t cqTail = cqTail_.load(); uint16_t cqHead = cqHead_.load(); if (cqTail == cqHead) { cqeInfo->reportCqeNum = 0U; return; } const uint32_t queueDepth = TprtManage::Instance()->TprtGetSqMaxDepth(); uint32_t reportCqeNum = 0U; const std::lock_guard<std::mutex> lock(cqQueueLock_); while ((cqHead != cqTail) && (reportCqeNum < cqeInfo->cqeNum)) { // 漏洞点:未验证 cqeAddr 缓冲区是否能容纳 reportCqeNum+1 个元素 (TprtPtrToPtr<TprtCqeReport_t*>(cqeInfo->cqeAddr))[reportCqeNum] = cqQueue_[cqHead]; ++reportCqeNum; cqHead = (cqHead + 1U) % queueDepth; } cqeInfo->reportCqeNum = reportCqeNum; cqHead_.store(cqHead); }数据流分析
攻击场景
前置条件
TprtCqReportRecv公开 API攻击步骤
TprtCqeReport_t(约 28 字节)TprtReportCqeInfo_t,设置cqeAddr指向该小缓冲区,cqeNum = 1024TprtCqReportRecv影响
SQCQ_MAX_DEPTH = 1024,每个TprtCqeReport_t为 14 字节(packed),最大可越界写入约 14,308 字节taskSn,errorCode,errorType,sqeType,sqId,sqHead),非攻击者直接可控内容现有缓解措施
cqeInfo != nullptrcqeInfo->cqeNum != 0cqeInfo->cqeAddr != nullptrcqHead != cqTail循环条件缺失的关键检查: 无
cqeNum上限验证,无缓冲区大小验证。置信度评分明细
{ "id": "TPRT-003", "confidence": 75, "status": "LIKELY", "veto_applied": false, "scoring_details": { "base": 30, "reachability": 30, "controllability": 25, "mitigations": -10, "context": 0, "cross_file": 0 } }TprtCqReportRecv为extern "C"公开 API,用户应用可直接调用cqeAddr(目标地址)和cqeNum(写入数量)均由用户完全控制TprtCqReportRecv→TprtCqHandleGetCqe,无中间安全检查修复建议
在
TprtCqReportRecv(API 入口层)添加cqeNum上限验证:// tprt_api.cc - TprtCqReportRecv 函数中,在现有检查之后添加: if (cqeInfo->cqeNum > SQCQ_MAX_DEPTH) { TPRT_LOG(TPRT_LOG_ERROR, "cqeNum[%u] exceeds max depth[%u], device_id=%u.", cqeInfo->cqeNum, SQCQ_MAX_DEPTH, devId); return TPRT_INPUT_INVALID; }此修复将
cqeNum限制在队列最大深度范围内。由于调用方按约定应分配至少cqeNum * sizeof(TprtCqeReport_t)大小的缓冲区,限制cqeNum上限可确保写入量不会超过合理预期。