### 脏牛漏洞提权原理

**1. 什么是写时复制（CoW）？**

在 Linux 系统中，当一个进程需要复制一个文件或共享内存区域时，内核并不会立刻为新进程分配独立的内存空间并复制数据。相反，它会让两个进程共享同一块物理内存

只有当其中一个进程**尝试修改**这块内存中的数据时，内核才会触发“写时复制”机制：

- 内核会为这个正在尝试写入的进程**创建一个新的物理内存副本**
- 这样，原始进程的数据保持不变，而新进程可以在自己的私有内存副本上进行修改，而互不影响

这个机制极大地节省了内存和时间，提高了系统的效率

**2. 漏洞是如何产生的？**

“脏牛”漏洞的本质就在于**写时复制（CoW）机制的一个缺陷**

当一个非特权用户尝试访问一个只读文件（例如 `/etc/passwd`）时，内核会映射这个文件的内存页。按照 CoW 机制，用户无法修改它

然而，内核在处理以下两个操作时，存在一个**竞争条件**：

- **操作一：** 一个线程使用 `madvise(MADV_DONTNEED)` 系统调用来**丢弃**一个内存页。这个调用告诉内核：我不需要这个页了，你可以把它从内存中释放掉
- **操作二：** 另一个线程尝试**执行写入操作**，触发 CoW 机制，申请一个新的私有内存页

正常的流程应该是：如果一个线程在尝试写入，内核会先为其分配新的内存，然后再进行写入。但是，这个漏洞的巧妙之处在于，通过精巧地控制这两个操作的执行时机，可以制造出一个“时间窗口”

攻击者利用这个时间窗口，在内核准备为写入操作分配新内存之前，通过 `madvise()` 使得内核错误地**取消了 CoW 的正常流程**。结果是，内核没有为写入操作创建一个私有的内存副本，而是**直接在原始的只读内存页上进行了写入**

**3. 如何利用这个漏洞？**

攻击者利用这个漏洞的流程通常如下：

1. **选择目标文件：** 攻击者选择一个具有 root 权限的只读文件，例如 `/etc/passwd`，该文件包含了系统用户的账户信息
2. **多线程并发：** 攻击者启动两个线程，一个线程不断地尝试对 `/etc/passwd` 进行写入操作（例如，写入一个新的 root 用户账户），另一个线程则持续调用 `madvise()` 来触发竞争条件
3. **成功写入：** 在竞争条件被触发的瞬间，写入操作会绕过 CoW 机制，直接修改 `/etc/passwd` 的内存内容
4. **获取权限：** 攻击者随后会利用修改后的文件，通过新的 root 用户账户成功登录系统，从而获得 root 权限