ParseModelDescExtend 解析 om 文件的 PRE_MODEL_DESC_EXTEND 分区:第550行仅校验分区实际 size >= sizeof(ModelExtendHead) 与 magic,第560行直接将文件中声称的 extendDesc->len(uint64)作为 tlvListLen 传入 ParseTlvList,未校验 extendDesc->len <= size - sizeof(ModelExtendHead)。ParseTlvList(第527-547行)内部所有边界检查(CheckLenValid(tlvListLen, ...))均以该声称长度为基准,TlvHead 读取(第530行)与 tlv->data 的处理(ProcFifoInfo)在声称长度超出分区实际大小时越过 om 模型内存缓冲区造成堆越界读。已验证完整可达链:公开 ACL API aclmdlQueryExeOMDesc(api/acl_c/acl_model/model/model.c:203→208)→ GetPartitionSize → GetModelPartitionSize → GetModelAllPartitionSize → GetModelFifoSize(model_desc.c:104,传入经 modelLen 校验的分区 data/size)→ ParseModelDescExtend。用户提供构造的 om 文件即可触发。
核查1模式成立:第550行仅校验分区实际 size >= sizeof(ModelExtendHead),第556行仅校验 magic,第560行将 om 文件中声称的 extendDesc->len(uint64)直接作为 tlvListLen 传入 ParseTlvList;
ParseTlvList(第527-547行)内所有边界检查 CheckLenValid(model_desc.h:18-20,纯算术比较 total/offset/nextLen)均以该声称长度为基准,第530行 TlvHead 读取与第537行 ProcFifoInfo 对 tlv->data 的处理在声称长度超过分区实际大小时越出分区缓冲区。
核查2无防护:无 extendDesc->len 与 size - sizeof(ModelExtendHead) 的比较。
核查3可达链已逐行验证:公开 ACL API aclmdlQueryExeOMDesc(api/acl_c/acl_model/model/model.c:203-208,用户提供 om 文件路径)→ GetPartitionSize(ge_executor.c:97-107,LoadDataFromFile 加载)→ GetModelPartitionSize(model_desc.c:172-178)→ GetModelAllPartitionSize(第130行分区表对 modelLen 校验、第158行 PRE_MODEL_DESC_EXTEND 分支)→ GetModelFifoSize(model_desc.c:94-104,GetPartInfoFromModel 校验分区界内后返回 partition.data/size)→ ParseModelDescExtend;
另有 ParseModelDescExtendInfo(model_parse.c:568)模型加载解析路径。
核查4触发可满足:分区 data+size 虽保证在模型缓冲区界内,但 extendDesc->len 完全由 om 文件内容控制,声明大于分区实际剩余大小时 TlvHead/tlv->data 读取越过模型缓冲区造成堆越界读,构造 om 文件即可触发,缺陷真实
Source(问题源头) runtime/c/executor/model_parse.c:555 行 struct ModelExtendHead *extendDesc = (struct ModelExtendHead *)data,其 len 字段(uint64)直接取自用户提供的 om 文件分区内容
Source(问题源头)
runtime/c/executor/model_parse.c:555 行 struct ModelExtendHead *extendDesc = (struct ModelExtendHead *)data,其 len 字段(uint64)直接取自用户提供的 om 文件分区内容
Sink(问题爆发点) runtime/c/executor/model_parse.c:560 行 ParseTlvList(modelData, data + sizeof(struct ModelExtendHead), extendDesc->len, mdlDesc) 以声称长度为全部边界检查基准;model_parse.c:530 行 struct TlvHead *tlv = (struct TlvHead *)(tlvList + offset) 及后续 tlv->data 读取越过实际分区缓冲区
Sink(问题爆发点)
runtime/c/executor/model_parse.c:560 行 ParseTlvList(modelData, data + sizeof(struct ModelExtendHead), extendDesc->len, mdlDesc) 以声称长度为全部边界检查基准;model_parse.c:530 行 struct TlvHead *tlv = (struct TlvHead *)(tlvList + offset) 及后续 tlv->data 读取越过实际分区缓冲区
传播路径:
可达调用链1 起点:(entry functions) → 终点:ParseModelDescExtend 深度:5
(entry functions)
ParseModelDescExtend
在第560行调用 ParseTlvList 前校验声称长度不超过分区实际剩余大小: if (extendDesc->len > (uint64_t)(size - sizeof(struct ModelExtendHead))) { GELOGE(ACL_ERROR_GE_PARAM_INVALID, "extend len %lu exceeds part size %zu.", extendDesc->len, size); return ACL_ERROR_GE_LOAD_MODEL; } return ParseTlvList(modelData, data + sizeof(struct ModelExtendHead), extendDesc->len, mdlDesc);
我们将尽快根据您的描述确认问题是否存在,请您关注issue状态
缺陷信息
缺陷描述
ParseModelDescExtend 解析 om 文件的 PRE_MODEL_DESC_EXTEND 分区:第550行仅校验分区实际 size >= sizeof(ModelExtendHead) 与 magic,第560行直接将文件中声称的 extendDesc->len(uint64)作为 tlvListLen 传入 ParseTlvList,未校验 extendDesc->len <= size - sizeof(ModelExtendHead)。ParseTlvList(第527-547行)内部所有边界检查(CheckLenValid(tlvListLen, ...))均以该声称长度为基准,TlvHead 读取(第530行)与 tlv->data 的处理(ProcFifoInfo)在声称长度超出分区实际大小时越过 om 模型内存缓冲区造成堆越界读。已验证完整可达链:公开 ACL API aclmdlQueryExeOMDesc(api/acl_c/acl_model/model/model.c:203→208)→ GetPartitionSize → GetModelPartitionSize → GetModelAllPartitionSize → GetModelFifoSize(model_desc.c:104,传入经 modelLen 校验的分区 data/size)→ ParseModelDescExtend。用户提供构造的 om 文件即可触发。
事实核查
数据流证据
传播路径:
调用链
可达调用链1 起点:
(entry functions)→ 终点:ParseModelDescExtend深度:5修复建议
在第560行调用 ParseTlvList 前校验声称长度不超过分区实际剩余大小: if (extendDesc->len > (uint64_t)(size - sizeof(struct ModelExtendHead))) { GELOGE(ACL_ERROR_GE_PARAM_INVALID, "extend len %lu exceeds part size %zu.", extendDesc->len, size); return ACL_ERROR_GE_LOAD_MODEL; } return ParseTlvList(modelData, data + sizeof(struct ModelExtendHead), extendDesc->len, mdlDesc);