1321 字
7 分钟
使用 syzkaller fuzz Linux RDMA 子系统

现有覆盖率分析#

分析 syzkaller 模糊测试框架对 Linux RDMA (Remote Direct Memory Access) 子系统的覆盖情况,包括已适配的接口、缺失的功能以及各驱动的支持状态。

RDMA 子系统架构#

┌─────────────────────────────────────────────────────────────────┐
│ 用户空间应用 │
├─────────────────────────────────────────────────────────────────┤
│ libibverbs │ librdmacm │ User MAD │ Netlink RDMA │
├──────────────┴─────────────┴────────────┴───────────────────────┤
│ 内核接口 │
│ /dev/infiniband/uverbsX │ /dev/infiniband/rdma_cm │
│ /dev/infiniband/umadX │ NETLINK_RDMA │
├─────────────────────────────────────────────────────────────────┤
│ RDMA Core (ib_core) │
├─────────────────────────────────────────────────────────────────┤
│ 硬件驱动层 │
│ mlx5 │ mlx4 │ rxe │ siw │ hfi1 │ efa │ hns │ ... 等 │
└─────────────────────────────────────────────────────────────────┘

已有的 syzlang 描述#

文件描述
sys/linux/dev_infiniband_rdma.txtuverbs 接口描述
sys/linux/dev_infiniband_rdma_cm.txtRDMA CM 接口描述
sys/linux/socket_netlink_rdma.txtRDMA Netlink 接口描述

已完成适配的接口#

uverbs 接口 (/dev/infiniband/uverbsX)#

设备与上下文管理#

命令Syzlang 函数状态
GET_CONTEXTwrite$MLX5_GET_CONTEXT
QUERY_DEVICE_EXwrite$QUERY_DEVICE_EX
QUERY_PORTwrite$QUERY_PORT

Protection Domain (PD)#

命令Syzlang 函数状态
ALLOC_PDwrite$ALLOC_PD, write$MLX5_ALLOC_PD
DEALLOC_PDwrite$DEALLOC_PD

Address Handle (AH)#

命令Syzlang 函数状态
CREATE_AHwrite$CREATE_AH
DESTROY_AHwrite$DESTROY_AH
MODIFY_AH-
QUERY_AH-

Memory Region (MR)#

命令Syzlang 函数状态
REG_MRwrite$REG_MR
REREG_MRwrite$REREG_MR
DEREG_MRwrite$DEREG_MR
REG_SMR-
QUERY_MR-

Memory Window (MW)#

命令Syzlang 函数状态
ALLOC_MWwrite$ALLOC_MW
DEALLOC_MWwrite$DEALLOC_MW
BIND_MW-

Completion Queue (CQ)#

命令Syzlang 函数状态
CREATE_COMP_CHANNELwrite$CREATE_COMP_CHANNEL
CREATE_CQwrite$CREATE_CQ, write$MLX5_CREATE_CQ
CREATE_CQ_EXwrite$CREATE_CQ_EX
RESIZE_CQwrite$RESIZE_CQ
DESTROY_CQwrite$DESTROY_CQ
POLL_CQwrite$POLL_CQ
REQ_NOTIFY_CQwrite$REQ_NOTIFY_CQ
PEEK_CQ-
MODIFY_CQ (EX)-

Queue Pair (QP)#

命令Syzlang 函数状态
CREATE_QPwrite$CREATE_QP, write$MLX5_CREATE_QP
QUERY_QPwrite$QUERY_QP
MODIFY_QPwrite$MODIFY_QP
DESTROY_QPwrite$DESTROY_QP
OPEN_QP-
MODIFY_QP (EX)-

Work Queue (WQ)#

命令Syzlang 函数状态
CREATE_WQwrite$CREATE_WQ, write$MLX5_CREATE_WQ
MODIFY_WQwrite$MLX5_MODIFY_WQ
DESTROY_WQwrite$DESTROY_WQ

Shared Receive Queue (SRQ)#

命令Syzlang 函数状态
CREATE_SRQwrite$CREATE_SRQ, write$MLX5_CREATE_SRQ
MODIFY_SRQwrite$MODIFY_SRQ
QUERY_SRQwrite$QUERY_SRQ
DESTROY_SRQwrite$DESTROY_SRQ
POST_SRQ_RECVwrite$POST_SRQ_RECV
CREATE_XSRQ-

其他功能#

命令Syzlang 函数状态
POST_SENDwrite$POST_SEND
POST_RECVwrite$POST_RECV
ATTACH_MCASTwrite$ATTACH_MCAST
DETACH_MCASTwrite$DETACH_MCAST
OPEN_XRCDwrite$OPEN_XRCD
CLOSE_XRCDwrite$CLOSE_XRCD
CREATE_FLOWwrite$CREATE_FLOW
DESTROY_FLOWwrite$DESTROY_FLOW
CREATE_RWQ_IND_TBLwrite$CREATE_RWQ_IND_TBL
DESTROY_RWQ_IND_TBLwrite$DESTROY_RWQ_IND_TBL

ioctl 接口#

命令Syzlang 函数状态
COUNTERS_CREATEioctl$CREATE_COUNTERS
COUNTERS_DESTROYioctl$DESTROY_COUNTERS
COUNTERS_READioctl$READ_COUNTERS

RDMA CM 接口 (/dev/infiniband/rdma_cm)#

命令状态说明
CREATE_ID创建 RDMA CM ID
DESTROY_ID销毁 RDMA CM ID
BIND_IP绑定 IP 地址
BIND通用地址绑定
RESOLVE_IP解析 IP 地址
RESOLVE_ADDR解析地址
RESOLVE_ROUTE解析路由
QUERY_ROUTE查询路由
QUERY通用查询
CONNECT建立连接
LISTEN监听连接
ACCEPT接受连接
REJECT拒绝连接
DISCONNECT断开连接
INIT_QP_ATTR初始化 QP 属性
GET_EVENT获取事件
SET_OPTION设置选项
NOTIFY通知
JOIN_IP_MCAST加入 IP 组播
JOIN_MCAST加入组播
LEAVE_MCAST离开组播
MIGRATE_ID迁移 ID
命令状态说明
RDMA_NLDEV_CMD_GET获取设备信息
RDMA_NLDEV_CMD_SET设置设备属性
RDMA_NLDEV_CMD_NEWLINK创建软件 RDMA 设备
RDMA_NLDEV_CMD_DELLINK删除软件 RDMA 设备
RDMA_NLDEV_CMD_PORT_GET获取端口信息
RDMA_NLDEV_CMD_SYS_GET获取系统信息
RDMA_NLDEV_CMD_SYS_SET设置系统属性
RDMA_NLDEV_CMD_RES_GET获取资源信息
RDMA_NLDEV_CMD_RES_QP_GET获取 QP 资源
RDMA_NLDEV_CMD_RES_CM_ID_GET获取 CM ID 资源
RDMA_NLDEV_CMD_RES_CQ_GET获取 CQ 资源
RDMA_NLDEV_CMD_RES_MR_GET获取 MR 资源
RDMA_NLDEV_CMD_RES_PD_GET获取 PD 资源
RDMA_NLDEV_CMD_GET_CHARDEV获取字符设备
RDMA_NLDEV_CMD_STAT_SET设置统计
RDMA_NLDEV_CMD_STAT_GET获取统计
RDMA_NLDEV_CMD_STAT_DEL删除统计
RDMA_NLDEV_CMD_RES_QP_GET_RAW原始 QP 数据
RDMA_NLDEV_CMD_RES_CQ_GET_RAW原始 CQ 数据
RDMA_NLDEV_CMD_RES_MR_GET_RAW原始 MR 数据
RDMA_NLDEV_CMD_RES_CTX_GET获取上下文资源
RDMA_NLDEV_CMD_RES_SRQ_GET获取 SRQ 资源
RDMA_NLDEV_CMD_RES_SRQ_GET_RAW原始 SRQ 数据
RDMA_NLDEV_CMD_STAT_GET_STATUS获取统计状态
RDMA_NLDEV_CMD_NEWDEV新建设备
RDMA_NLDEV_CMD_DELDEV删除设备
RDMA_NLDEV_CMD_MONITOR监控事件

特定驱动#

驱动头文件
MLX5mlx5-abi.h, mlx5_user_ioctl_cmds.h
  • mlx5_get_context_cmd
  • mlx5_alloc_pd_cmd
  • mlx5_create_cq_cmd
  • mlx5_create_qp_cmd
  • mlx5_create_dv_qp_cmd
  • mlx5_create_wq_cmd
  • mlx5_modify_wq_cmd
  • mlx5_create_srq_cmd

缺失的接口#

  • uverbs 缺失命令(/dev/infiniband/uverbsX)
  • User MAD 接口 (/dev/infiniband/umadX)
  • 特定驱动
驱动头文件说明
RXErdma_user_rxe.h软件 RoCE
SIWsiw-abi.h软件 iWARP
EFAefa-abi.hAWS 云
HNShns-abi.h华为
ERDMAerdma-abi.h阿里云
MANAmana-abi.hAzure 云
IRDMAirdma-abi.hIntel
HFI1hfi/hfi1_*.hIntel OPA
MLX4mlx4-abi.h老 Mellanox
BNXT_REbnxt_re-abi.hBroadcom
CXGB4cxgb4-abi.hChelsio
MTHCAmthca-abi.h老 Mellanox
OCRDMAocrdma-abi.hEmulex
QEDRqedr-abi.hQLogic
QIBrvt-abi.hIntel
VMW_PVRDMAvmw_pvrdma-abi.hVMware
USNIC-Cisco

软件 RDMA fuzz (rxe、siw)#

为内核启用 RDMA#

编辑 .config

# 基础 RDMA 支持
CONFIG_INFINIBAND=y
CONFIG_INFINIBAND_USER_ACCESS=y
CONFIG_INFINIBAND_USER_MAD=y
CONFIG_INFINIBAND_USER_MEM=y
CONFIG_INFINIBAND_ON_DEMAND_PAGING=y
# 软件驱动
CONFIG_RDMA_RXE=y
CONFIG_RDMA_SIW=y
# Netlink
CONFIG_RDMA_NETLINK=y
make oldconfig
make -j$(nproc)

编写 syzlang#

提取常量并重新构建 syzkaller#

make bin/syz-extract
bin/syz-extract -os linux -arch amd64 -sourcedir <kernel_source_dir> <txt_file>
make generate
make

编辑 syzkaller 运行配置#

编辑.config,指定测试的 syscall

"enable_syscalls": [
"openat$uverbs0",
"openat$rdma_cm",
"write$RDMA*",
"write$RXE*",
"write$SIW*",
"mmap$RXE*",
"mmap$SIW*",
"ioctl$CREATE_COUNTERS",
"ioctl$DESTROY_COUNTERS",
"ioctl$READ_COUNTERS",
"close"
]

QEMU 设置#

openat$uverbs0: failed to open /dev/infiniband/uverbs0: no such file or directory

由于调用的虚拟机还没有创建 RDMA 设备,需要为虚拟机设置启动时自动添加 RDMA(RXE、SIW)设备。

这里以 QEMU 为例,使用 Systemd 服务自动执行配置。

# 登录到虚拟机
sudo nano /usr/local/bin/setup-rdma-links.sh

编辑 /usr/local/bin/setup-rdma-links.sh

#!/bin/bash
# 防止网卡尚未完全就绪
sleep 2
# 创建 RXE 设备(绑定到网络接口 eth0)
rdma link add rxe0 type rxe netdev eth0 2>/dev/null || true
# 创建 SIW 设备(绑定到环回接口 lo)
rdma link add siw0 type siw netdev lo 2>/dev/null || true
exit 0
sudo chmod +x /usr/local/bin/setup-rdma-links.sh
sudo nano /etc/systemd/system/rdma-link-setup.service

编辑 Systemd 服务配置

[Unit]
Description=Setup RDMA RXE and SIW Links
# 确保在网络连接服务启动后才执行
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/setup-rdma-links.sh
SuccessExitStatus=1
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload # 重载 Systemd 配置
sudo systemctl enable rdma-link-setup.service # 启用服务
sudo systemctl start rdma-link-setup.service # 启动服务

检查结果

systemctl status rdma-link-setup.service
rdma link show
ls /dev/infiniband

当系统启动时,rdma-link-setup.service 会自动运行,创建 RXE 和 SIW 设备。

运行 fuzz#

./bin/syz-manager -config=setting.cfg

image-20251126232050832

image-20251126232224688

模拟 ERDMA 设备 fuzz#

ERDMA (Elastic RDMA) 是阿里云提供的弹性 RDMA 适配器驱动,位于 Linux 内核的 drivers/infiniband/hw/erdma/ 目录。该驱动需要特定的阿里云硬件环境才能运行,尝试创建一个 ERDMA 模拟驱动,实现不依赖硬件在 QEMU 虚拟机中运行,并使用 syzkaller 进行 fuzz 测试。

创建一个独立模块,仅模拟接口层。

```
linux-6.16.9/drivers/infiniband/hw/erdma/
├── erdma_sim.c # 新增:模拟驱动源码 (567 行)
├── Kconfig # 修改:添加 CONFIG_INFINIBAND_ERDMA_SIM
├── Makefile # 修改:添加编译规则
└── ... (原有 ERDMA 文件)
syzkaller/
├── sys/linux/dev_infiniband_erdma.txt # 新增:syzlang 描述
└── setting.cfg # 修改:启用 ERDMA syscalls
```

编辑内核源码#

编写 syzlang#

编译与部署#

编辑 .config,设置 ERDMA 编译选项。

CONFIG_INFINIBAND_ERDMA=y
CONFIG_INFINIBAND_ERDMA_SIM=m

编译内核

make olddefconfig
make -j$(nproc)

安装模块

# 复制到目标系统
scp -P <port> -i ~/image/bullseye.id_rsa drivers/infiniband/hw/erdma/erdma_sim.ko root@localhost:/root/
# 加载模块
insmod /root/erdma_sim.ko

验证设备加载情况

rdma link show # link erdma_sim1/1 state ACTIVE physical_state LINK_UP
ibv_devices
ls /dev/infiniband/

image-20251126234315486

提取常量并重新构建 syzkaller#

make bin/syz-extract
bin/syz-extract -os linux -arch amd64 -sourcedir <kernel_source_dir> <txt_file>
make generate
make

编辑 syzkaller 运行配置#

"enable_syscalls": [
"openat$uverbs0",
"write$QUERY_DEVICE_EX",
"write$QUERY_PORT",
"write$ALLOC_PD",
"write$DEALLOC_PD",
"write$CREATE_CQ",
"write$DESTROY_CQ",
"write$CREATE_QP",
"write$DESTROY_QP",
"write$MODIFY_QP",
"write$POST_SEND",
"write$POST_RECV",
"write$REG_MR",
"write$DEREG_MR",
"mmap$ERDMA_CQ",
"mmap$ERDMA_SQ",
"mmap$ERDMA_RQ",
"close"
]

QEMU 设置#

和上文一样,设置开启自动加载模块。直接在刚刚的/usr/local/bin/setup-rdma-links.sh中添加语句。

insmod /root/erdma_sim.ko

运行 fuzz#

./bin/syz-manager -config=setting.cfg

image-20251126234252873

image-20251126234259900

使用 syzkaller fuzz Linux RDMA 子系统
https://tsukiii.cn/posts/syzkaller_rdma/
作者
Tsuki
发布于
2025-11-27
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时