byt3quester/CVE-2022-22706-poc
GitHub: byt3quester/CVE-2022-22706-poc
针对 Arm Mali GPU 驱动程序 CVE-2022-22706 权限校验缺陷的 PoC,通过构造页缓存可写别名实现非特权进程提权至 root。
Stars: 0 | Forks: 0
# CVE-2022-22706 - 页缓存写入
Arm Mali GPU 驱动程序向用户空间提供了一个其锁定为只读页面的 CPU 可写映射,
因此非特权进程会获得一个页缓存的可写别名,而该页缓存所支持的文件
只能以 `O_RDONLY` 方式打开。
`exploit.c` 清空了 `/etc/passwd` 页缓存中 root 的密码字段,并执行
`su root`。磁盘上的文件从未被修改过。
## 漏洞
关于谁可以写入导入的页面,有两处决策存在冲突。
CPU 映射的可写性来自 `KBASE_REG_CPU_WR`,但锁定操作仅根据 `KBASE_REG_GPU_WR` 来请求写入
权限:
```
/* mali_kbase_mem.c */
pinned_pages = pin_user_pages_remote(
mm, address, alloc->imported.user_buf.nr_pages,
reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0, pages, NULL, NULL);
```
在设置了 `CPU_WR` 且清除了 `GPU_WR` 的情况下进行导入,你会同时得到两部分内容:一个导入的 CPU
可写映射,以及一个在没有 `FOLL_WRITE` 的情况下获取的 `get_user_pages` 锁定。如果没有
`FOLL_WRITE`,`get_user_pages` 永远不会打破只读文件映射上的 COW,它会返回
页缓存页本身。然后,驱动程序将这些确切的页面作为可写页面重新映射到用户空间。
已由 [`5381ff7`](https://android.googlesource.com/kernel/google-modules/gpu/+/5381ff7b4106b277ff207396e293ede2bf959f0c%5E%21/)
("GPUCORE-32592 修复 userbuf 导入以尊重 RO 内存")修复,该补丁改为从
`KBASE_REG_CPU_WR | KBASE_REG_GPU_WR` 而不是仅从 `GPU_WR` 来获取写入权限。
## 利用流程
```
sequenceDiagram
participant U as unprivileged process
participant K as mali_kbase
participant PC as page cache
U->>U: mmap /etc/passwd O_RDONLY, PROT_READ
U->>K: MEM_IMPORT(anon page, CPU_RD|CPU_WR|GPU_RD)
Note over K: address recorded, nothing pinned yet
U->>U: munmap(anon) + mremap file mapping onto that VA
U->>K: mmap(import cookie) → writable CPU mapping
U->>K: JOB_SUBMIT(EXTERNAL_RESOURCES)
K->>PC: pin_user_pages_remote() without FOLL_WRITE
U->>PC: memcpy() through the writable mapping
U->>U: execl("/bin/su", "su", "root")
```
`MEM_IMPORT` 仅记录一个地址;锁定操作发生在稍后的 `JOB_SUBMIT` 时。这个间隙
使得匿名页能够在两者之间被替换为文件映射。
该编辑的长度保持不变,因此 root 行之后的内容不会发生偏移:
```
root:x:0:0:root:/root:/bin/sh ← before
root::0:0:rootx:/root:/bin/sh ← after (empty password)
```
busybox 的 `su` 在密码字段为空时,会在提示之前返回 `CHECKPASS_PW_HAS_EMPTY_PASSWORD`,并且
只有当其恰好为 `x` 时才会读取 `/etc/shadow`。
## 构建与运行
```
gcc -static -o exploit exploit.c
```
将其复制到 VM 中,并作为非特权用户运行:
```
$ ./exploit
```
## 演示

该演示是通过 SSH 以 `user` (uid 1000) 身份登录 QEMU 目标录制的。`./exploit` 修补了 `/etc/passwd` 页缓存中 root 的所在行,并执行了 `su root`,这直接进入了一个 root shell
而无需输入密码。
退出该 shell 并再次运行 `su` 仍然会获得 root 权限:该页面保持缓存状态,因此之后每次对 `/etc/passwd` 的 `open()`/`read()` 操作都会读取到被修补的字节。
在执行 `echo 1 > /proc/sys/vm/drop_caches` 驱逐了该页面并从存储中重新读取文件后,
`su` 会再次要求输入密码。磁盘上的字节从未被触碰过。
## 参考
* [Arm — Mali GPU 驱动程序漏洞](https://developer.arm.com/Arm%20Security%20Center/Mali%20GPU%20Driver%20Vulnerabilities)
* [STAR Labs — Mali-cious Intent:利用 GPU 漏洞 (CVE-2022-22706 / CVE-2021-39793)](https://starlabs.sg/blog/2025/02-mali-cious-intent-exploiting-gpu-vulnerabilities-cve-2022-22706-/-cve-2021-39793/)
* [上游修复 — `5381ff7`](https://android.googlesource.com/kernel/google-modules/gpu/+/5381ff7b4106b277ff207396e293ede2bf959f0c%5E%21/)
标签:ARM架构, CSV导出, Mali驱动, Web报告查看器, 内存管理, 内核漏洞, 安全渗透, 客户端加密, 提权, 身份验证强制