CVE-2026-31431: Copy Fail
摘要
CVE-2026-31431(Copy Fail)是Linux内核中的一个本地提权漏洞,影响自2017年以来的所有主流发行版,允许非特权用户通过AF_ALG加密子系统对任何可读文件的页缓存进行确定性的4字节写入,从而获得root shell访问权限。
<p><a href="https://lobste.rs/s/ksg1es/cve_2026_31431_copy_fail">评论</a></p>
查看缓存全文
缓存时间: 2026/05/09 00:33
# retr0.zip 资料来源: https://retr0.zip/blog/cve-2026-31431-copy-fail.html
## CVE-2026-31431: Copy Fail
> 2026-05-03
2026年4月29日,Theori (https://theori.io/)公开披露了Copy Fail (https://copy.fail/)(CVE-2026-31431),这是一个影响自2017年以来所有主流Linux发行版的本地权限提升漏洞。内核`authencesn`加密模板中的一个逻辑缺陷,通过`AF_ALG`套接字和`splice()`串联,允许非特权用户对任何可读文件的页缓存进行确定性的4字节写入。一个732字节的Python脚本(https://github.com/theori-io/copy-fail-CVE-2026-31431/blob/main/copy_fail_exp.py)会篡改内存中的`/usr/bin/su`并弹出一个root shell。无需竞争条件、无需偏移量、无需编译。
当我第一次读到Xint的writeup(https://xint.io/blog/copy-fail-linux-distributions)时,我立刻想到了Dirty COW(https://dirtycow.ninja/)(CVE-2016-5341),另一个让所有系统都获得root的页缓存篡改漏洞。但机制完全不同。Dirty COW是写时复制(copy-on-write)错误处理器中的一个竞争条件。两个线程在写错误时竞争`madvise(MADV_DONTNEED)`可以偷偷写入只读映射。Copy Fail完全没有竞争条件,只是一个任何非特权用户都可以调用的确定性系统调用序列。
Dirty COW通过虚拟内存子系统写入,后者至少理解页权限。Copy Fail通过加密子系统写入,后者完全没有页所有权的概念。它只看到一个scatterlist条目然后写入它。
我最初也以为这是一个越界写入(当我看到"在密文边界后写入4字节"时)。其实不是。我们会解释为什么,这也是KASAN八年来从未捕获到它的原因。
Xint的writeup写得很好,但对内核细节讲得很快。我们这里会慢一些,涵盖页缓存、scatterlist、`splice()`和`AF_ALG`/AEAD,这样即使你从未接触过内核MM代码也能理解完整链条。发现的所有功劳归于Taeyang Lee、Theori (https://x.com/theori_io)和Xint Code Research Team (https://x.com/xint_official)。
## 页缓存
每次我们`read()`一个文件时,内核不会去磁盘。它去**页缓存**——一个系统级的文件数据内存缓存,按(inode, offset)对组织。如果该页已经(由任何进程)从之前的读取中缓存了,内核直接返回它。如果没有,它从磁盘读取,缓存起来,然后返回。
```
container 1 container 2 host
+-----------+ +-----------+ +-----------+
| Process A | | Process B | | Process C |
| read() | | execve() | | mmap() |
+-----+-----+ +-----+-----+ +-----+-----+
| | |
+-------------------+-------------------+
|
v
+---------------------------------------------------------+
| Page Cache (RAM) |
| |
| /usr/bin/su +--------+--------+--------+ |
| | | | | |
| | page 0 | page 1 | page 2 | |
| | ELF | .text | .data | |
| +--------+--------+--------+ |
| +---------------------------+-------------+ ^
| | miss | populate | v |
| +-------------+ +-------------+
| | disk | | /usr/bin/su |
| +-------------+ +-------------+
```
这里有两个重要的结构:
- **`struct page`**(https://elixir.bootlin.com/linux/v6.12.10/source/include/linux/mm_types.h#L72):表示一个物理页(通常4096字节)。有`flags`、一个`mapping`指针(回指文件的`address_space`)和一个`index`(该页在文件中的偏移量,以页为单位)。
- **`struct address_space`**(https://elixir.bootlin.com/linux/v6.12.10/source/include/linux/fs.h#L465):与inode关联。它是特定文件的页缓存索引,一个将页偏移量映射到`struct page`指针的radix树(https://en.wikipedia.org/wiki/Radix_tree)。
这个漏洞的关键特性是页缓存在整个系统中共享。如果两个在不同容器、cgroup和用户命名空间中的进程读取同一文件系统上的同一文件,它们将共享相同的物理页。篡改页缓存页(是的,我们就这么叫它,页页页……),所有读取者看到的就是被篡改的状态。
还有一点。页缓存跟踪页是否被修改("脏"位)。当页通过正常写路径(`write()`、`mmap`存储)被弄脏时,内核会标记它为脏并最终将其写回磁盘。但我们即将看到的篡改不通过正常写路径。该页从未被标记为脏,磁盘上的文件也没有被修改,但每个读取它的进程都会得到内存中被篡改的版本。
## Scatterlist
内核经常需要描述跨越多个非连续物理页的缓冲区。`read()`可能返回分散在物理内存中的页的数据。加密操作需要处理分布在不同分配区域中的输入。**Scatterlist**是内核表示这些非连续缓冲区的方式。单个`struct scatterlist`(https://elixir.bootlin.com/linux/v6.12.10/source/include/linux/scatterlist.h#L11)条目描述一个连续块:
```c
struct scatterlist {
unsigned long page_link; // struct page* | flags in low 2 bits
unsigned int offset; // byte offset within the page
unsigned int length; // byte length of this chunk
dma_addr_t dma_address;
};
```
`page_link`字段被重载。低2位编码标志:
- **位0(`SG_CHAIN`(https://elixir.bootlin.com/linux/v6.12.10/source/include/linux/scatterlist.h#L67))**:这个条目是一个指向下一个scatterlist数组的指针。这是多个SG(scatter-gather,内核开发者喜欢他们的两个字母缩写,`sg`、`sk`、`mm`、`vm`)数组链接在一起的方式。
- **位1(`SG_END`(https://elixir.bootlin.com/linux/v6.12.10/source/include/linux/scatterlist.h#L68))**:这是链中的最后一个条目。
高位(在屏蔽低2位后)存储`struct page*`指针。scatterlist链看起来像这样:
```
SG Array 1 SG Array 2
+-------------------------+ +-------------------------+
| sg[0]: page_A off=0 | | sg[0]: page_C off=128 |
| len=4096 | | len=64 [END] |
+-------------------------+ +-------------------------+
| sg[1]: page_B off=0 | ^
| len=512 | |
+-------------------------+ |
| sg[2]: CHAIN |---------+
+-------------------------+
```
`sg_chain()`(https://elixir.bootlin.com/linux/v6.12.10/source/include/linux/scatterlist.h#L238)是创建这些链接的函数,它在一个数组的最后一个条目上设置`SG_CHAIN`位,并指向下一个数组的第一个条目。
为了实际在scatterlist链中的字节偏移处读取或写入数据,内核提供了**`scatterwalk_map_and_copy()`**(https://elixir.bootlin.com/linux/v6.12.10/source/crypto/scatterwalk.c#L55)。它逐条目遍历链,跳过页直到到达目标偏移,然后复制数据进或出。这个函数就是在这个漏洞中最终执行4字节页缓存写入的函数。
## `splice()`: 零拷贝I/O
`splice()`(https://elixir.bootlin.com/linux/v6.12.10/source/fs/splice.c#L1634)系统调用在文件描述符和管道之间移动数据**而不通过用户空间拷贝**。不是`read()`文件数据到用户空间缓冲区然后`write()`到另一个fd,`splice()`传递的是**页引用**。管道持有指向页缓存中相同物理页的指针。
```
splice(file_fd, pipe_wr) splice(pipe_rd, socket_fd)
+----------+ +----------+ +----------+
| File |--->| Pipe |--->| Socket |
| (on disk)| | (in mem) | | (AF_ALG) |
+----------+ +----------+ +----------+
| |
| '---------------'
| same physical pages
|
v
kernel crypto (page cache pages)
receives page cache page refs in its scatterlist
```
当我们将文件`splice()`到管道时,管道的内部缓冲区不会得到数据的拷贝。它得到的是页缓存页本身的引用。然后当我们将管道`splice()`到套接字时,套接字的内部缓冲区(对于AF_ALG的情况是scatterlist)接收那些相同的页缓存页引用。每一步都没有拷贝。内核的加密子系统现在持有我们splice的文件页缓存的直接指针。
没有`splice()`,加密子系统会在拷贝的缓冲区上操作。有了`splice()`,它就在页缓存本身上操作。Dirty COW也使用了传递页引用而不拷贝的相同技巧。不过它是通过VM错误处理器而不是`splice()`。
## AF_ALG 和 AEAD
**AF_ALG**(https://elixir.bootlin.com/linux/v6.12.10/source/include/linux/socket.h#L230)是一个Linux套接字族,向非特权用户空间暴露内核的加密API。任何用户都可以:
```c
int alg_fd = socket(AF_ALG, SOCK_SEQPACKET, 0); // AF_ALG = 38
struct sockaddr_alg sa = { // include/uapi/linux/if_alg.h:19
.salg_family = AF_ALG,
.salg_type = "aead",
.salg_name = "authencesn(hmac(sha256),cbc(aes))"
};
bind(alg_fd, (struct sockaddr *)&sa, sizeof(sa));
```
不需要特权。不需要`CAP_NET_ADMIN`。模块在首次使用时自动加载。AF_ALG的设计目的是让用户空间应用程序可以使用硬件加速加密,而无需编写内核模块。这对我们也很方便。
**AEAD**(带关联数据的认证加密(https://en.wikipedia.org/wiki/Authenticated_encryption#Authenticated_encryption_with_associated_data))是一类同时提供机密性(加密)和完整性(认证标签)的加密算法。AEAD解密输入看起来像:
```
+---------------+--------------------+------------------+
| AAD | Ciphertext | Authentication |
| (auth'd only) | (decrypted+auth'd) | Tag (verified) |
+---------------+--------------------+------------------+
```
AAD(关联数据)经过认证但不加密。它是必须不能被篡改的明文元数据。密文被解密。认证标签通过AAD和密文进行验证以检测篡改。
### `authencesn`
`authencesn`(https://elixir.bootlin.com/linux/v6.12.10/source/crypto/authencesn.c)是一个用于**IPsec ESP with Extended Sequence Numbers**(RFC 4303(https://www.rfc-editor.org/rfc/rfc4303))的特定AEAD模板。每个IPsec数据包携带一个**序列号**来防止重放攻击。最初这是一个32位计数器,但在10 Gbps下32位计数器在不到2秒内就会回绕。RFC 4303引入了**扩展序列号(ESN)**,一个64位计数器分成两半:
```
Full 64-bit ESN: [ seqno_hi (32 bits) | seqno_lo (32 bits) ]
upper 32 bits lower 32 bits
```
只有`seqno_lo`在ESP头中在线传输。发送方和接收方都维护一个共享计数器(安全关联状态),所以`seqno_hi`是隐式的——双方都知道。这节省了在线每包4字节,同时仍获得64位抗重放窗口。
认证哈希需要覆盖**完整的64位序列号**,包括不在数据包中的高位。所以内核必须在计算HMAC之前重建完整的ESN。
在真实IPsec路径(`esp_input_set_header()`(https://elixir.bootlin.com/linux/v6.12.10/source/net/ipv4/esp4.c#L846))中,ESP代码从SA(安全关联)状态获取隐式的`seqno_hi`,将skb头回推4字节(https://elixir.bootlin.com/linux/v6.12.10/source/net/ipv4/esp4.c#L856),并将`seqno_hi`塞入AAD然后传给`authencesn`:
```
ESP header on the wire: [ SPI | seqno_lo | IV | ciphertext | tag ]
^ |
| only 32 bits
AAD reconstructed for HMAC: [ seqno_hi | seqno_lo | SPI ]
bytes 0-3 bytes 4-7 bytes 8-11
(from SA) (from wire) (from wire)
```
现在`authencesn`在AAD的前8字节中有了完整的64位ESN。但ESP的HMAC规范说哈希应该基于`[SPI | seqno_lo | seqno_hi | ciphertext]`计算——一个不同的字节顺序。所以`authencesn`需要在哈希之前**重新排列**这些字节。它通过将调用者的目标缓冲区当作临时空间来实现这一点。
在`crypto_authenc_esn_decrypt()`(https://elixir.bootlin.com/linux/v6.12.10/source/crypto/authencesn.c#L262)中,三个`scatterwalk_map_and_copy()`(https://elixir.bootlin.com/linux/v6.12.10/source/crypto/scatterwalk.c#L55)调用执行这个洗牌(源代码(https://elixir.bootlin.com/linux/v6.12.10/source/crypto/authencesn.c#L293-L295)):
```
Step 1: read tmp[0..1] = dst[0..7] -- grab seqno_hi and seqno_lo
Step 2: write dst[4..7] = tmp[0] -- move seqno_hi to bytes 4-7
Step 3: write dst[assoclen+cryptlen] = tmp[1] -- stash seqno_lo PAST the ciphertext
```
在正常IPsec解密路径中,`dst[assoclen + cryptlen]`指向**认证标签**,即AEAD缓冲区中密文后面的HMAC字节。标签区域是同一内核分配的skb缓冲区的一部分,完全可写,即将用计算的HMAC覆盖。暂时将`seqno_lo`存放在那里是无害的。它是临时空间,将被HMAC比较消耗然后丢弃:
```
Normal IPsec dst buffer (single skb allocation):
+----------+--------------+----------+
| AAD | ciphertext | tag | <-- all one contiguous kernel buffer
+----------+--------------+----------+
| | | |
| assoclen | cryptlen | authsize |
| ^ | |
| | dst[assoclen+cryptlen] = start of tag region
| | safe to use as scratch
```
HMAC之后,`crypto_authenc_esn_decrypt_tail()`(https://elixir.bootlin.com/linux/v6.12.10/source/crypto/authencesn.c#L213)恢复原始布局。它从`dst[assoclen+cryptlen]`读回`seqno_lo`并将原始8字节写回`dst[0..7]`。干净的往返,无副作用。
所有这些都假设`dst`是一个**私有的、可写的缓冲区**——`dst[assoclen + cryptlen]`可以安全写入,因为它是内核拥有的加密缓冲区的标签区域。当有人在该精确偏移处将页缓存页链接到目标scatterlist时,这就坏了。
## 漏洞
### 2017原地优化
2017年,commit `72548b093ee3`(https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=72548b093ee38a6d4f2a19e6ef1948ae05c181f7)给`algif_aead.c`(https://elixir.bootlin.com/linux/v6.12.10/source/crypto/algif_aead.c)——AF_ALG AEAD接口——添加了一个优化。思路很简单。对于解密,不使用单独的输入和输出scatterlist,而是**原地**操作,将`req->src`和`req->dst`都指向同一个scatterlist。这避免了一次分配和一次拷贝。作为性能优化很有意义。
AF_ALG套接字像网络套接字一样工作。用户空间**发送**数据到内核(`sendmsg`/`splice`)并**接收**结果(`recvmsg`)。内核使用网络术语来称呼这两边:
- **TX SGL**(传输scatterlist):保存用户空间*发送*到套接字的数据。这是加密操作的输入——AAD、密文和标签。当数据通过`splice()`到达时,这些scatterlist条目直接指向页缓存页。
- **RX SGL**(接收scatterlist):内核将加密结果*写回*用户空间的缓冲区。这从`recvmsg()`端分配——普通内核内存,不是页缓存。
在`_aead_recvmsg()`(https://elixir.bootlin.com/linux/v6.12.10/source/crypto/algif_aead.c#L88)中的实现:
1. 将AAD和密文从TX SGL拷贝到RX SGL。
2. 使用`sg_chain()`(https://elixir.bootlin.com/linux/v6.12.10/source/crypto/algif_aead.c#L275)将TX SGL中剩余的标签页链接到RX SGL。
3. 设置`req->src = req->dst`——源和目标现在都指向同一个组合scatterlist。
当数据通过`splice()`到达时,TX SGL持有**页缓存页**。链接之后,那些页缓存页现在成为**目标**scatterlist的一部分:
```
req->src --+
|
v
req->dst --> RX Buffer (user memory)
|
+--> TX SGL (page cache pages)
| +----------+----------+
| | AAD | CT |--chain-->|
+----+----------+----------+ |
|
v
RX SGL (after chaining)
+----------------------+
| AAD | CT | tag pages |
+----------------------+
^
|
page cache pages
now in destination!
```
`req->src`和`req->dst`现在指向同一个组合的scatterlist,其中包括页缓存页。
在正常的IPsec路径中,`dst[assoclen + cryptlen]`指向标签区域——一个内核分配的安全可写的缓冲区。但在这里,当`scatterwalk_map_and_copy()`尝试执行Step 3时:
```c
write dst[assoclen+cryptlen] = tmp[1] -- stash seqno_lo PAST the ciphertext
```
它不是写到一个私有内核缓冲区。它写的是**页缓存页**。
`assoclen`和`cryptlen`来自TX SGL——即来自用户通过`splice()`发送的页缓存页。`dst`(= `req->dst` = `req->src` = TX SGL)也是同一个scatterlist。所以`dst[assoclen + cryptlen]`是对页缓存中某个位置的4字节写入。
4字节。确定性的。写到任何可读文件的页缓存中。在`splice()`之后,无需权限。
这意味着:任何非特权用户可以:
1. 使用`splice()`将任意可读文件读入AF_ALG套接字
2. 触发原地AEAD解密
3. 让`authencesn`的代码将4字节写入页缓存,超出密文边界
然后:
4. 另一个进程读取同一个文件(读取同一个页缓存页)
5. 获得被篡改的数据
PoC直接指向`/usr/bin/su`。篡改其`.text`段中的几个字节,跳转到堆栈上的shellcode。root。
整个利用链条:
```
1. 打开 /usr/bin/su,read() 一点点 (将页缓存加载到内存)
2. socket(AF_ALG), bind("authencesn(...)")
3. splice(su_fd, pipe) -- TX SGL 现在有 su 的页缓存页
4. sendmsg(alg_fd, tag) -- 发送一个伪造的 AEAD 消息:
- 短的 AAD (4字节)
- 短的密文 (4字节)
- 伪造的标签 (16字节)
5. _aead_recvmsg():
- 拷贝 AAD+CT 到 RX SGL
- 链接触发标签页 -> 组合 scatterlist
- req->src = req->dst = 组合 scatterlist
6. crypto_authenc_esn_decrypt():
- Step 3: scatterwalk_map_and_copy(dst, assoclen+cryptlen, 4)
- 写入 4 字节到页缓存中的某个偏移量
7. 另一个进程 execve("/usr/bin/su")
- 内核从页缓存读取 ELF
- 读取被篡改的字节
- 跳转到错误位置
8. segfault 或 root shell
```
实际利用代码(来自theori的仓库)非常简短:
```python
import socket
import os
import struct
# 1. Load the target file into page cache
su = open("/usr/bin/su", "rb")
su.read(4096)
# 2. Set up AF_ALG socket
sock = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
sock.bind(("aead", "authencesn(hmac(sha256),cbc(aes))"))
...
# 3. Splice the file into the socket
os.splice(su.fileno(), pipe[1], 4096)
# 4. Send trigger message
sock.sendmsg([aad, ct, tag])
# 5. Result: 4-byte write into /usr/bin/su's page cache
```
利用非常稳定,没有竞争条件——所有syscall都是确定性的。覆盖4字节可以可靠地跳转到shellcode。成功。
这是内核加密子系统中一个漂亮的逻辑漏洞。二十年来的"优化"突然在八年后的实际攻击中显现。
### 为什么 KASAN 没有捕获它
KASAN(内核地址 sanitizer)是一个动态内存错误检测器,可以捕获越界写入、释放后使用等问题。它通过在每次内存访问时验证访问是否在有效范围内来工作。
问题在于:`scatterwalk_map_and_copy()`是一个通用的scatterlist遍历函数,它本身不知道缓冲区在哪里或它们是什么。它只是按照scatterlist的指示写入。KASAN只能检查通过`kmalloc`、`vmalloc`等分配的内存的边界。对于通过页缓存(通过`folio`、`page`等)映射的内存,KASAN没有边界的概念——它不知道一个scatterlist条目是否应该只在该页的`offset`到`offset+length`范围内写入。
`dst[assoclen + cryptlen]`是一个有效的scatterlist写入——`assoclen + cryptlen`确实在scatterlist的范围内。问题在于scatterlist本身指向页缓存页,而代码假设它指向一个内核私有缓冲区。KASAN没有看到"越界",因为在scatterlist的上下文中没有越界——它只在页的边界内。这类似于一个逻辑漏洞,而不是典型的内存损坏。 KASAN无法捕获这类问题。
Dirty COW和Copy Fail都是通过绕过内核通常的安全检查来实现权限提升的——Dirty COW通过VM子系统,Copy Fail通过crypto子系统。两者的核心区别在于:Dirty COW依赖竞争条件,而Copy Fail使用确定性的系统调用序列,不存在竞争。这使问题更隐蔽,也更难被检测工具发现。
### 修复
该漏洞已在Linux内核6.12.11及更新版本中修复(commit `fdb2d5c...`)。修复方案在scatterlist处理中添加了验证,确保目标scatterlist不会意外引用页缓存页,从而在写入前进行边界检查。
根本问题在于:AF_ALG接口允许用户控制scatterlist的内容,而crypto代码假设这些scatterlist指向可信的内核缓冲区。当这个假设被打破时(比如通过splice()),就会产生安全漏洞。
### 时间线
- **2024年10月**:Taeyang Lee发现该漏洞
- **2025年1月**:向Linux内核安全团队报告
- **2025年4月**:修复方案开始审查
- **2026年4月29日**:公开披露
- **2026年5月3日**:本文发布
### 结论
Copy Fail是一个优雅的漏洞,展示了内核不同子系统之间交互的复杂性。通过将页缓存、scatterlist、splice()和AF_ALG接口串联起来,攻击者可以绕过诸多安全机制,获得对任意可读文件的确定性写入能力。关键问题是内核代码对scatterlist Buffer来源的假设——当用户能够控制scatterlist的内容时,这些假设就会失效。
Dirty COW和Copy Fail都利用了内核中"数据应该来自哪里"的隐式假设。Dirty COW破坏这些假设的手段是竞态条件,而Copy Fail则是逻辑缺陷。在现代内核中,许多优化(如原地解密)都依赖于这类假设,攻击者只需找到一处失效点就能突破整个系统。
感谢 Taeyang Lee、Theori 和 Xint Code Research Team 的发现和披露。
### 参考资料
- 原始披露:https://copy.fail/
- Theori漏洞报告:https://theori.io/blog/copy-fail
- Xint分析:https://xint.io/blog/copy-fail-linux-distributions
- 利用代码:https://github.com/theori-io/copy-fail-CVE-2026-31431
- 内核修复:https://git.kernel.org/.../fdb2d5c...
- 原始commit(原地优化):https://git.kernel.org/.../72548b093ee3
- `scatterwalk_map_and_copy`:https://elixir.bootlin.com/linux/v6.12.10/source/crypto/scatterwalk.c#L55
- `authencesn`:https://elixir.bootlin.com/linux/v6.12.10/source/crypto/authencesn.c
- `algif_aead.c`:https://elixir.bootlin.com/linux/v6.12.10/source/crypto/algif_aead.c
- RFC 4303 (ESN):https://www.rfc-editor.org/rfc/rfc4303
相似文章
Copy Fail 2: Electric Boogaloo
Copy Fail 2 是一个针对 Linux 内核 xfrm 子系统中非特权本地权限提升(LPE)漏洞的概念验证利用程序,攻击者可利用该漏洞在现代发行版上获取 root 权限。
Podman无根容器与Copy Fail漏洞
本文讨论了Copy Fail漏洞,这是一个影响Podman无根容器的安全漏洞。
你给我一个u32。我让你成为root。 (io_uring ZCRX freelist LPE)
Linux内核io_uring子系统中通过零拷贝接收freelist漏洞实现的本地权限提升利用。
Dirtyfrag:通用 Linux 本地权限提升漏洞
一份名为“Dirty Frag”的报告详细描述了一种通用的 Linux 本地权限提升(LPE)漏洞。该漏洞通过串联两个内核错误,可在主要发行版上获取 root 访问权限。披露信息指出,由于保密期失效,目前尚无针对此关键安全问题的补丁。
Anthropic Claude Code 泄露揭示严重命令注入漏洞
在 Anthropic 的 Claude Code CLI 和 SDK 中发现了严重命令注入漏洞(CVE-2026-35022,CVSS 9.8),攻击者能够通过环境变量、文件路径和身份验证助手执行任意命令并窃取凭据。这些缺陷使得在 CI/CD 环境中能够进行毒化流水线执行攻击,需要立即修补和配置更改。