news 2026/9/13 13:57:01

飞桨安全公告 PDSA-2023-002 深度解读:paddle.flip 空指针解引用漏洞(CVE-2023-38670)分析与修复

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
飞桨安全公告 PDSA-2023-002 深度解读:paddle.flip 空指针解引用漏洞(CVE-2023-38670)分析与修复

飞桨安全公告 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-38670

PDSA-2023-002 是飞桨官方发布的安全公告之一,对应 CVE 编号CVE-2023-38670,公告原文位于 security/advisory/pdsa-2023-002.md(另有中文版 security/advisory/pdsa-2023-002_cn.md)。核心信息如下:

条目内容
公告编号PDSA-2023-002
CVE 编号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 等数据类型,别名input
axislist / tuple / int需要翻转的轴,支持负数索引(从末尾倒数),别名dims
namestr,可选算子名称,默认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], dtype=int64, place=Place(cpu), stop_gradient=True, [[[10, 11], [8 , 9 ]], [[6 , 7 ], [4 , 5 ]], [[3 , 2 ], [0 , 1 ]]]) >>> out = paddle.flip(tmp, -1) >>> print(out) Tensor(shape=[3, 2, 2], dtype=int64, place=Place(cpu), stop_gradient=True, [[[11, 10], [9 , 8 ]], [[7 , 6 ], [5 , 4 ]], [[3 , 2 ], [1 , 0 ]]])

可以看到,axis既可以是列表[0, 1](同时翻转多个轴),也可以是负数-1(翻转最后一维),返回张量与输入数据类型一致。

2.2 底层 Kernel 实现链路

paddle.flip的 Python 层最终会映射到 PHI(Paddle High-level IR)算子体系中名为flip的 Kernel。当前仓库中该算子实现了多后端版本:

  • CPU Kernel:paddle/phi/kernels/cpu/flip_kernel.cc
  • GPU Kernel:paddle/phi/kernels/gpu/flip_kernel.cu
  • XPU Kernel:paddle/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::vector<int>& axis, DenseTensor* out) { auto x_dims = x.dims(); const int total_dims = x_dims.size(); std::bitset<dim_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.data<T>(); T* out_data = dev_ctx.template Alloc<T>(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]; } }

关键点在于:

  1. axis在 C++ 层以std::vector<int>形式接收,且 Kernel 内部直接假设axis是一个合法的整数向量;
  2. 负数轴通过dim += total_dims归一化后,直接作为std::bitset<64>的下标使用;
  3. Kernel 通过x.data<T>()获取输入数据指针后立即解引用(x_data[dst_offset]),全程没有对非法axis值或异常输入形态做防御性校验

该 Kernel 注册支持的数据类型包括floatdoubleint32_tint64_tboolcomplex64complex128(见 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的合法输入约定

  1. x是一个只含一个张量的元组(tuple),而不是直接传入的 Tensor。官方签名的第一个参数类型是Tensor,这里却传入了(paddle.to_tensor(...),)这种包装形态;
  2. axis是一个形状为[3, 3]的 int32 Tensor,而官方签名要求axis必须是intlist/tuple。这里传入了形状完全不匹配的张量,且数值随机取遍 int32 全范围(-21474836482147483647),其中包含了大量远超张量维度的非法轴值(如负数、大于等于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.data<T>()返回的指针必然有效,紧接着的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 paddlepaddle(CPU 版)或对应平台的 GPU 安装包;
  • 评估暴露面:如果业务代码中存在将外部输入直接传入paddle.flip(尤其是将axis参数交由模型配置、用户请求数据驱动)的场景,应优先排查并在升级前做好临时防护。

5.3 临时规避写法(升级前)

在无法立即升级的情况下,务必保证paddle.flip的调用符合 API 约定:

import paddle x = paddle.to_tensor([[1, 2, 3], [4, 5, 6]], dtype='int64') # ✅ 正确: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,), axis=paddle.to_tensor([0]))

这条防御性约束同样适用于项目中的其他飞桨算子调用:对来自外部输入的任何张量形状、轴参数,先做类型与取值范围校验,再进入框架 API

六、仓库中的回归测试与验证

当前仓库保留了flip算子的完整测试资产,可作为理解正常行为与验证修复的参考:

  • API 级测试:test/legacy_test/test_flip.py —— 覆盖静态图(paddle.static)与动态图两种执行模式,验证paddle.flipoutput.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-002(CVE-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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 13:55:12

ROS Service服务通信机制全解析:从一问一答到工程落地

ROS 通信机制 —— Service&#xff08;服务&#xff09;从“一问一答”到工程落地做ROS开发的人应该都有这种经历&#xff1a;刚开始接触话题&#xff08;Topic&#xff09;时觉得一切都能用Topic搞定&#xff0c;后来在项目里遇到“我需要一个结果”的场景时&#xff0c;才发…

作者头像 李华
网站建设 2026/9/13 13:53:20

爱因斯坦棋中的期望搜索算法原理与实现

简介&#xff1a;本资源是一款面向计算机博弈大赛参赛者、AI算法学习者及棋类编程爱好者的爱因斯坦棋智能对战软件&#xff0c;聚焦期望搜索算法在不确定博弈环境中的实践应用。项目基于Python实现&#xff0c;集成Pygame图形界面&#xff0c;提供智能策略分析、实时步法建议与…

作者头像 李华
网站建设 2026/9/13 13:50:46

架构师的自我克制:永远不要为不存在的高并发场景提前引入复杂中间件

架构师的自我克制&#xff1a;永远不要为不存在的高并发场景提前引入复杂中间件在很多技术团队的方案评审中&#xff0c;常常充斥着各种脱离业务实际的“过度设计幻想”&#xff1a; 一个日均只有几万次点击的内部管理后台&#xff0c;方案里画着全套的 Kafka、Flink 实时流计算…

作者头像 李华
网站建设 2026/9/13 13:49:29

SLAM回环检测原理与工程实践:从词袋模型到ORB-SLAM应用解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 13:46:11

电路元器件目标检测为何必须用VOC格式数据集

简介&#xff1a;本资源是一套面向电子工程、计算机视觉与AI算法开发者的标准化电路元器件图像数据集&#xff0c;采用PASCAL VOC格式构建&#xff0c;专为元器件目标检测、识别与分类任务提供高质量训练基础。数据集覆盖电阻、电容、二极管、晶体管等典型元件&#xff0c;配套…

作者头像 李华