分析与修复)
飞桨安全公告 PDSA-2023-002 深度解读paddle.flip 空指针解引用漏洞CVE-2023-38670分析与修复【免费下载链接】PaddlePArallel Distributed Deep LEarning: Machine Learning Framework from Industrial Practice 『飞桨』核心框架深度学习机器学习高性能单机、分布式训练和跨平台部署项目地址: https://gitcode.com/GitHub_Trending/pa/Paddle本文以飞桨PaddlePaddle官方安全公告 security/advisory/pdsa-2023-002.md 为核心骨架结合当前仓库中paddle.flip的 API 定义、CPU/GPU/XPU 底层 Kernel 实现与回归测试深入剖析该漏洞的触发路径、根因与修复方案。读者读完本文后将能够复现漏洞场景、理解空指针解引用的成因并掌握升级修复版本与编写安全调用代码的完整实践方法。一、漏洞概览PDSA-2023-002 与 CVE-2023-38670PDSA-2023-002 是飞桨官方发布的安全公告之一对应 CVE 编号CVE-2023-38670公告原文位于 security/advisory/pdsa-2023-002.md另有中文版 security/advisory/pdsa-2023-002_cn.md。核心信息如下条目内容公告编号PDSA-2023-002CVE 编号CVE-2023-38670漏洞类型空指针解引用Null pointer dereference受影响 APIpaddle.flip危害表现进程崩溃segfault修复提交ed96baeed19b4e11b6cbc2dcc6776245ba5fab13修复版本飞桨 2.5.0修复包含于该版本漏洞报告者Tong Liu上海科技大学ShanghaiTech University公告明确指出paddle.flip在特定非法输入下会因空指针解引用nullptr dereference导致程序段错误segfault崩溃。由于飞桨安全公告体系中补丁将包含在 2.5.0 版本当中意味着该修复随 2.5.0 发布因此飞桨 2.5.0 之前的版本均在受影响范围内建议相关用户尽快评估并升级。飞桨完整的安全模型、漏洞报告流程与联系渠道参见仓库根目录的 SECURITY.md 与 SECURITY_cn.md。历史漏洞公告统一收录于 security/advisory 目录本文所属的 PDSA-2023 系列覆盖了 2023 年披露的多个安全问题。二、漏洞对象 paddle.flip功能、签名与正常用法要理解漏洞先要认识paddle.flip这个算子本身。2.1 API 定义与参数语义paddle.flip用于沿指定轴反转翻转一个 n 维张量的元素顺序其官方 Python 层定义位于 python/paddle/_paddle_docs.py签名如下def flip(x: Tensor, axis: Sequence[int] | int, name: str | None None) - Tensor参数类型语义xTensor输入张量形状为[N_1, N_2, ..., N_k]支持 float32、float64、int32、int64、bool 等数据类型别名inputaxislist / tuple / int需要翻转的轴支持负数索引从末尾倒数别名dimsnamestr可选算子名称默认None用于调试与图分析正常用例如下官方 docstring 中的可运行示例 import paddle image_shape (3, 2, 2) img paddle.arange(image_shape[0] * image_shape[1] * image_shape[2]).reshape(image_shape) tmp paddle.flip(img, [0, 1]) print(tmp) Tensor(shape[3, 2, 2], dtypeint64, placePlace(cpu), stop_gradientTrue, [[[10, 11], [8 , 9 ]], [[6 , 7 ], [4 , 5 ]], [[3 , 2 ], [0 , 1 ]]]) out paddle.flip(tmp, -1) print(out) Tensor(shape[3, 2, 2], dtypeint64, placePlace(cpu), stop_gradientTrue, [[[11, 10], [9 , 8 ]], [[7 , 6 ], [5 , 4 ]], [[3 , 2 ], [1 , 0 ]]])可以看到axis既可以是列表[0, 1]同时翻转多个轴也可以是负数-1翻转最后一维返回张量与输入数据类型一致。2.2 底层 Kernel 实现链路paddle.flip的 Python 层最终会映射到 PHIPaddle High-level IR算子体系中名为flip的 Kernel。当前仓库中该算子实现了多后端版本CPU Kernelpaddle/phi/kernels/cpu/flip_kernel.ccGPU Kernelpaddle/phi/kernels/gpu/flip_kernel.cuXPU Kernelpaddle/phi/kernels/xpu/flip_kernel.cc头文件声明paddle/phi/kernels/flip_kernel.h以 CPU 实现为例核心翻转逻辑如下template typename T, typename Context void FlipKernel(const Context dev_ctx, const DenseTensor x, const std::vectorint axis, DenseTensor* out) { auto x_dims x.dims(); const int total_dims x_dims.size(); std::bitsetdim_bitset_size dim_bitset; for (auto item : axis) { auto dim item; if (item 0) { dim total_dims; // 负数轴归一化到 [0, total_dims) } dim_bitset[dim] true; } auto x_strides common::stride(x_dims); auto numel x.numel(); const T* x_data x.dataT(); T* out_data dev_ctx.template AllocT(out); if (out-numel() 0) { return; } // 对每个输出元素根据 dim_bitset 计算其在输入中的翻转后偏移 dst_offset for (int64_t i 0; i numel; i) { // ... 将线性索引 i 按 strides 分解命中翻转轴时取 (x_dims[d] - 1 - cur_indices) out_data[i] x_data[dst_offset]; } }关键点在于axis在 C 层以std::vectorint形式接收且 Kernel 内部直接假设axis是一个合法的整数向量负数轴通过dim total_dims归一化后直接作为std::bitset64的下标使用Kernel 通过x.dataT()获取输入数据指针后立即解引用x_data[dst_offset]全程没有对非法axis值或异常输入形态做防御性校验。该 Kernel 注册支持的数据类型包括float、double、int32_t、int64_t、bool、complex64、complex128见 paddle/phi/kernels/cpu/flip_kernel.cc。此外flip还具备 TensorRT 推理转换支持见 paddle/fluid/inference/tensorrt/convert/flip_op.cc且要求动态 shape 模式见 paddle/fluid/inference/tensorrt/op_teller.cc。三、漏洞细节PoC 逐步拆解公告给出的完整 PoC 如下import paddle import numpy as np from paddle import flip x (paddle.to_tensor(np.random.uniform(-10, 10, [1, 2, 3]).astype(np.int64)),) axis paddle.to_tensor( np.random.uniform(-2147483648, 2147483647, [3, 3]).astype(np.int32) ) flip(x, axis)逐行分析这个 PoC可以发现它刻意违反paddle.flip的合法输入约定x是一个只含一个张量的元组tuple而不是直接传入的 Tensor。官方签名的第一个参数类型是Tensor这里却传入了(paddle.to_tensor(...),)这种包装形态axis是一个形状为[3, 3]的 int32 Tensor而官方签名要求axis必须是int或list/tuple。这里传入了形状完全不匹配的张量且数值随机取遍 int32 全范围-2147483648到2147483647其中包含了大量远超张量维度的非法轴值如负数、大于等于total_dims的数值。当这些非法输入穿透 Python 层进入底层算子执行路径后由于算子内部缺少对输入形态与axis取值范围的校验最终在解引用空指针nullptr时触发段错误进程直接崩溃——这正是公告描述的segfaults with a nullptr dereference。四、根因分析从源码看校验缺失结合当前仓库源码可以从两个层面理解漏洞根因4.1 Python 层输入约定依赖用户自觉从 python/paddle/_paddle_docs.py 的 API 定义看flip的 docstring 只通过类型注解axis: Sequence[int] | int声明了合法形态文档也明确写出axis应为list|tuple|int。但类型注解不构成运行时强制校验——当用户传入Tensor形态的axis或元组形态的x时Python 层没有抛出清晰的参数错误而是将这种异常形态继续向下传递。4.2 C 层Kernel 对合法输入的无条件信任从 paddle/phi/kernels/cpu/flip_kernel.cc 的实现可以看出Kernel 直接假设axis已经是合法整数向量dim_bitset[dim] true时不做越界检查x.dataT()返回的指针必然有效紧接着的out_data[i] x_data[dst_offset]直接解引用。当上层传递了错误形态的参数如把 Tensor 当作 axis 传入或在内部转换阶段得到无效指针Kernel 便会在未加防御的情况下执行解引用从而命中空指针表现为不可捕获的 segfault。从源码结构看这类问题属于**算子输入校验缺失missing input validation**导致的不安全解引用也是 C/C 原生扩展中常见的崩溃类安全缺陷。五、修复方案与缓解措施5.1 官方修复飞桨官方已在提交ed96baeed19b4e11b6cbc2dcc6776245ba5fab13中修复该问题修复随飞桨 2.5.0 版本发布。修复方向即为对flip的输入参数增加严格校验拒绝不符合Tensor (int|list|tuple)约定的调用形态并在进入底层 Kernel 前对axis取值进行合法性检查从而杜绝空指针解引用的发生路径。5.2 升级建议确认当前版本通过python -c import paddle; print(paddle.__version__)查看安装版本升级到修复版本若版本低于 2.5.0建议升级至包含修复的版本例如pip install -U paddlepaddleCPU 版或对应平台的 GPU 安装包评估暴露面如果业务代码中存在将外部输入直接传入paddle.flip尤其是将axis参数交由模型配置、用户请求数据驱动的场景应优先排查并在升级前做好临时防护。5.3 临时规避写法升级前在无法立即升级的情况下务必保证paddle.flip的调用符合 API 约定import paddle x paddle.to_tensor([[1, 2, 3], [4, 5, 6]], dtypeint64) # ✅ 正确axis 使用 int 或 list/tuple out paddle.flip(x, axis[0, 1]) out paddle.flip(x, axis-1) # ❌ 错误axis 传 Tensor、x 传 tuple 等非法形态应禁止 # bad paddle.flip((x,), axispaddle.to_tensor([0]))这条防御性约束同样适用于项目中的其他飞桨算子调用对来自外部输入的任何张量形状、轴参数先做类型与取值范围校验再进入框架 API。六、仓库中的回归测试与验证当前仓库保留了flip算子的完整测试资产可作为理解正常行为与验证修复的参考API 级测试test/legacy_test/test_flip.py —— 覆盖静态图paddle.static与动态图两种执行模式验证paddle.flip、output.flip(0)等方法调用形式与翻转结果的正确性如输入[[1,2,3],[4,5,6]]沿轴 0、-1 翻转的输出比对IPU 后端测试test/ipu/test_flip_op_ipu.py —— 验证 IPU 硬件上的算子一致性TensorRT 推理测试test/ir/inference/test_trt_convert_flip.py —— 验证flip经 TensorRT 转换后的推理正确性。从测试组织方式可以推断飞桨对算子的验证以正常合法输入的正确性为主而 PDSA-2023-002 这类安全公告补充的正是针对非法输入形态的鲁棒性防线——这也是深度学习框架安全性建设中输入校验与崩溃隔离的核心命题。七、总结PDSA-2023-002CVE-2023-38670揭示了飞桨paddle.flip算子在非法输入下因空指针解引用导致进程崩溃的问题攻击面任何能够向paddle.flip注入非约定输入Tensor 形态的axis、元组形态的x、越界轴值的代码路径影响进程崩溃DoS 性质修复包含于飞桨 2.5.0防御升级至修复版本并在应用层严格遵守 API 参数约定、对输入做前置校验。对于使用飞桨进行推理服务部署或对输入可控性要求较高的场景建议持续关注 security/advisory 目录下的历史公告并参照 SECURITY_cn.md 建立漏洞上报与版本跟踪机制将框架安全纳入常规运维流程。【免费下载链接】PaddlePArallel Distributed Deep LEarning: Machine Learning Framework from Industrial Practice 『飞桨』核心框架深度学习机器学习高性能单机、分布式训练和跨平台部署项目地址: https://gitcode.com/GitHub_Trending/pa/Paddle创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考