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.txt | uverbs 接口描述 |
sys/linux/dev_infiniband_rdma_cm.txt | RDMA CM 接口描述 |
sys/linux/socket_netlink_rdma.txt | RDMA Netlink 接口描述 |
已完成适配的接口
uverbs 接口 (/dev/infiniband/uverbsX)
设备与上下文管理
| 命令 | Syzlang 函数 | 状态 |
|---|---|---|
| GET_CONTEXT | write$MLX5_GET_CONTEXT | ✅ |
| QUERY_DEVICE_EX | write$QUERY_DEVICE_EX | ✅ |
| QUERY_PORT | write$QUERY_PORT | ✅ |
Protection Domain (PD)
| 命令 | Syzlang 函数 | 状态 |
|---|---|---|
| ALLOC_PD | write$ALLOC_PD, write$MLX5_ALLOC_PD | ✅ |
| DEALLOC_PD | write$DEALLOC_PD | ✅ |
Address Handle (AH)
| 命令 | Syzlang 函数 | 状态 |
|---|---|---|
| CREATE_AH | write$CREATE_AH | ✅ |
| DESTROY_AH | write$DESTROY_AH | ✅ |
| MODIFY_AH | - | ❌ |
| QUERY_AH | - | ❌ |
Memory Region (MR)
| 命令 | Syzlang 函数 | 状态 |
|---|---|---|
| REG_MR | write$REG_MR | ✅ |
| REREG_MR | write$REREG_MR | ✅ |
| DEREG_MR | write$DEREG_MR | ✅ |
| REG_SMR | - | ❌ |
| QUERY_MR | - | ❌ |
Memory Window (MW)
| 命令 | Syzlang 函数 | 状态 |
|---|---|---|
| ALLOC_MW | write$ALLOC_MW | ✅ |
| DEALLOC_MW | write$DEALLOC_MW | ✅ |
| BIND_MW | - | ❌ |
Completion Queue (CQ)
| 命令 | Syzlang 函数 | 状态 |
|---|---|---|
| CREATE_COMP_CHANNEL | write$CREATE_COMP_CHANNEL | ✅ |
| CREATE_CQ | write$CREATE_CQ, write$MLX5_CREATE_CQ | ✅ |
| CREATE_CQ_EX | write$CREATE_CQ_EX | ✅ |
| RESIZE_CQ | write$RESIZE_CQ | ✅ |
| DESTROY_CQ | write$DESTROY_CQ | ✅ |
| POLL_CQ | write$POLL_CQ | ✅ |
| REQ_NOTIFY_CQ | write$REQ_NOTIFY_CQ | ✅ |
| PEEK_CQ | - | ❌ |
| MODIFY_CQ (EX) | - | ❌ |
Queue Pair (QP)
| 命令 | Syzlang 函数 | 状态 |
|---|---|---|
| CREATE_QP | write$CREATE_QP, write$MLX5_CREATE_QP | ✅ |
| QUERY_QP | write$QUERY_QP | ✅ |
| MODIFY_QP | write$MODIFY_QP | ✅ |
| DESTROY_QP | write$DESTROY_QP | ✅ |
| OPEN_QP | - | ❌ |
| MODIFY_QP (EX) | - | ❌ |
Work Queue (WQ)
| 命令 | Syzlang 函数 | 状态 |
|---|---|---|
| CREATE_WQ | write$CREATE_WQ, write$MLX5_CREATE_WQ | ✅ |
| MODIFY_WQ | write$MLX5_MODIFY_WQ | ✅ |
| DESTROY_WQ | write$DESTROY_WQ | ✅ |
Shared Receive Queue (SRQ)
| 命令 | Syzlang 函数 | 状态 |
|---|---|---|
| CREATE_SRQ | write$CREATE_SRQ, write$MLX5_CREATE_SRQ | ✅ |
| MODIFY_SRQ | write$MODIFY_SRQ | ✅ |
| QUERY_SRQ | write$QUERY_SRQ | ✅ |
| DESTROY_SRQ | write$DESTROY_SRQ | ✅ |
| POST_SRQ_RECV | write$POST_SRQ_RECV | ✅ |
| CREATE_XSRQ | - | ❌ |
其他功能
| 命令 | Syzlang 函数 | 状态 |
|---|---|---|
| POST_SEND | write$POST_SEND | ✅ |
| POST_RECV | write$POST_RECV | ✅ |
| ATTACH_MCAST | write$ATTACH_MCAST | ✅ |
| DETACH_MCAST | write$DETACH_MCAST | ✅ |
| OPEN_XRCD | write$OPEN_XRCD | ✅ |
| CLOSE_XRCD | write$CLOSE_XRCD | ✅ |
| CREATE_FLOW | write$CREATE_FLOW | ✅ |
| DESTROY_FLOW | write$DESTROY_FLOW | ✅ |
| CREATE_RWQ_IND_TBL | write$CREATE_RWQ_IND_TBL | ✅ |
| DESTROY_RWQ_IND_TBL | write$DESTROY_RWQ_IND_TBL | ✅ |
ioctl 接口
| 命令 | Syzlang 函数 | 状态 |
|---|---|---|
| COUNTERS_CREATE | ioctl$CREATE_COUNTERS | ✅ |
| COUNTERS_DESTROY | ioctl$DESTROY_COUNTERS | ✅ |
| COUNTERS_READ | ioctl$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 Netlink 接口 (NETLINK_RDMA)
| 命令 | 状态 | 说明 |
|---|---|---|
| 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 | ❌ | 监控事件 |
特定驱动
| 驱动 | 头文件 |
|---|---|
| MLX5 | mlx5-abi.h, mlx5_user_ioctl_cmds.h |
mlx5_get_context_cmdmlx5_alloc_pd_cmdmlx5_create_cq_cmdmlx5_create_qp_cmdmlx5_create_dv_qp_cmdmlx5_create_wq_cmdmlx5_modify_wq_cmdmlx5_create_srq_cmd
缺失的接口
- uverbs 缺失命令(
/dev/infiniband/uverbsX) - User MAD 接口 (
/dev/infiniband/umadX) - 特定驱动
| 驱动 | 头文件 | 说明 |
|---|---|---|
| RXE | rdma_user_rxe.h | 软件 RoCE |
| SIW | siw-abi.h | 软件 iWARP |
| EFA | efa-abi.h | AWS 云 |
| HNS | hns-abi.h | 华为 |
| ERDMA | erdma-abi.h | 阿里云 |
| MANA | mana-abi.h | Azure 云 |
| IRDMA | irdma-abi.h | Intel |
| HFI1 | hfi/hfi1_*.h | Intel OPA |
| MLX4 | mlx4-abi.h | 老 Mellanox |
| BNXT_RE | bnxt_re-abi.h | Broadcom |
| CXGB4 | cxgb4-abi.h | Chelsio |
| MTHCA | mthca-abi.h | 老 Mellanox |
| OCRDMA | ocrdma-abi.h | Emulex |
| QEDR | qedr-abi.h | QLogic |
| QIB | rvt-abi.h | Intel |
| VMW_PVRDMA | vmw_pvrdma-abi.h | VMware |
| USNIC | - | Cisco |
软件 RDMA fuzz (rxe、siw)
为内核启用 RDMA
编辑 .config
# 基础 RDMA 支持CONFIG_INFINIBAND=yCONFIG_INFINIBAND_USER_ACCESS=yCONFIG_INFINIBAND_USER_MAD=yCONFIG_INFINIBAND_USER_MEM=yCONFIG_INFINIBAND_ON_DEMAND_PAGING=y
# 软件驱动CONFIG_RDMA_RXE=yCONFIG_RDMA_SIW=y
# NetlinkCONFIG_RDMA_NETLINK=ymake oldconfigmake -j$(nproc)编写 syzlang
提取常量并重新构建 syzkaller
make bin/syz-extractbin/syz-extract -os linux -arch amd64 -sourcedir <kernel_source_dir> <txt_file>make generatemake编辑 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 0sudo chmod +x /usr/local/bin/setup-rdma-links.shsudo nano /etc/systemd/system/rdma-link-setup.service编辑 Systemd 服务配置
[Unit]Description=Setup RDMA RXE and SIW Links# 确保在网络连接服务启动后才执行After=network-online.target
[Service]Type=oneshotExecStart=/usr/local/bin/setup-rdma-links.shSuccessExitStatus=1
[Install]WantedBy=multi-user.targetsudo systemctl daemon-reload # 重载 Systemd 配置sudo systemctl enable rdma-link-setup.service # 启用服务sudo systemctl start rdma-link-setup.service # 启动服务检查结果
systemctl status rdma-link-setup.servicerdma link showls /dev/infiniband当系统启动时,rdma-link-setup.service 会自动运行,创建 RXE 和 SIW 设备。
运行 fuzz
./bin/syz-manager -config=setting.cfg

模拟 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=yCONFIG_INFINIBAND_ERDMA_SIM=m编译内核
make olddefconfigmake -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_UPibv_devicesls /dev/infiniband/
提取常量并重新构建 syzkaller
make bin/syz-extractbin/syz-extract -os linux -arch amd64 -sourcedir <kernel_source_dir> <txt_file>make generatemake编辑 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

使用 syzkaller fuzz Linux RDMA 子系统
https://tsukiii.cn/posts/syzkaller_rdma/ 部分信息可能已经过时