abdelkabirouadoukou/CVE-2026-31431-Analysis-and-Fix

GitHub: abdelkabirouadoukou/CVE-2026-31431-Analysis-and-Fix

深入剖析 Linux 内核 CVE-2026-31431 本地提权漏洞的根因、利用路径及内核级修复方案。

Stars: 0 | Forks: 0

# CVE-2026-31431 "Copy Fail" — 技术深入解析 **严重程度:** CVSS 7.8 (高) **类型:** 本地权限提升 **引入版本:** Linux 4.14 (2017) **修复版本:** commit `a664bf3d603d` ## 1. 背景 CVE-2026-31431 是 Linux 内核 `algif_aead` 模块中的一个本地权限提升漏洞,该模块是内核用户空间 crypto API (`AF_ALG`) 的 AEAD 套接字接口。 该漏洞允许非特权用户利用 Linux 内核 Crypto API 中的 `AF_ALG` 地址族,对支持文件内存副本的页缓存执行受控的 4 字节写入。通过替换存储在页缓存中可读可执行文件的内存副本中的代码,当任何特权进程随后运行该文件的受损版本时,攻击者即可提升用户权限。 与需要赢得竞态条件的 Dirty Cow (CVE-2016-5195) 不同,Copy Fail 是一个直截了当的逻辑缺陷。它的触发无需竞态、重试或容易导致崩溃的时间窗口。 ## 2. 根本原因 — 2017 年的就地处理优化 ### 2.1 改变了什么 Commit `72548b093ee3` ("crypto: algif_aead - switch to in-place processing") 引入了一项优化,在 `aead_recvmsg()` 内部设置了 `req->src == req->dst`,从而取消了独立的输出缓冲区分配。 这项优化导致 `req->src` 和 `req->dst` 指向同一个组合的 scatterlist。因此,来自 `splice()` 调用的页缓存页面被错误地直接链接到了可写的目标 scatterlist 中。 ### 2.2 隐式不变量 内核的 AEAD API 定义了明确的输出契约:目标缓冲区接收 `AAD || 明文`,严格等于 `assoclen + (cryptlen - authsize)` 字节。然而,API 本身并没有任何机制来强制执行此契约,也没有文档将其作为一项要求。该设计假设所有 AEAD 算法都会将其写入操作限制在预期的目标范围内。但有一个算法没有遵守。 ## 3. 受影响的文件 ``` crypto/ ├── algif_aead.c ← in-place scatterlist bug (primary) └── authencesn.c ← out-of-bounds scratch write (trigger) ``` ## 4. 存在漏洞的代码 ### 4.1 `crypto/algif_aead.c` — 就地赋值 ``` /* VULNERABLE — post-2017 in-place path */ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, int flags) { /* ... */ /* * When userspace calls splice(2) on a file, areq->tsgl contains * page cache pages of that file. Setting dst = src hands those * page cache pages to the crypto engine as a writable output * buffer. */ aead_request_set_crypt(req, areq->tsgl, /* src */ areq->tsgl, /* dst — identical pointer; root cause */ areq->cryptlen, iv); } ``` ### 4.2 `crypto/authencesn.c` — 越界暂存写入 `authencesn` 模板是 IPsec 用于支持扩展序列号 (ESN) 的 AEAD 包装器。IPsec 使用 64 位序列号,分为高半部分 (`seqno_hi`,AAD 的 0–3 字节) 和低半部分 (`seqno_lo`,4–7 字节)。传输格式仅携带 `seqno_lo`;`seqno_hi` 是隐式的。 ``` /* crypto/authencesn.c — scratch write past output boundary */ static int crypto_authenc_esn_decrypt(struct aead_request *req) { /* ... */ /* * authencesn temporarily stores seqno_hi at offset * (assoclen + cryptlen) in req->dst — one word past the * legitimate output region. * * Under normal operation: hits kernel-owned memory. * With in-place scatterlist: hits a page cache page. */ scatterwalk_map_and_copy(&seqno_hi, req->dst, req->assoclen + req->cryptlen, /* out-of-bounds offset */ sizeof(seqno_hi), /* 4 bytes */ 1 /* write */); /* authencesn does not restore these bytes on the failing path */ } ``` ## 5. 修复方案 **上游修复:** commit `a664bf3d603d` — 回退了 2017 年的优化。 ### 5.1 `crypto/algif_aead.c` — 分离 Scatterlists ``` /* FIXED — separate src and dst */ aead_request_set_crypt(req, areq->tsgl, /* src — may contain page cache pages; read-only */ areq->rsgl, /* dst — freshly allocated kernel buffer; writable */ areq->cryptlen, iv); ``` **效果:** 页缓存页面保留在 `src` 中,crypto 引擎只会对其进行读取。在 `assoclen + cryptlen` 处的 `authencesn` 暂存写入现在将落在进程拥有的内核分配缓冲区中。写入路径永远无法触及任何页缓存页面。 ## 6. 漏洞利用路径 以下描述了 4 字节写入如何实现完整的权限提升。 | 步骤 | 操作 | |------|--------| | 1 | 打开一个配置为 `authencesn(hmac(sha256),cbc(aes))` 的 `AF_ALG` 套接字 | | 2 | 将一个可读的 setuid 二进制文件(例如 `/usr/bin/sudo`)通过 `splice()` 切入套接字 — 这会将其页缓存页面放入 `areq->tsgl` 中 | | 3 | 构造 `assoclen` + `cryptlen`,使得暂存写入偏移量与二进制文件缓存映像中的目标字节对齐 | | 4 | 调用 `recvmsg()` — 触发解密路径,`authencesn` 将 4 个受攻击者控制的字节写入页缓存 | | 5 | 磁盘上的文件**保持不变**;完整性检查器、`inotify` 和 `inode` 时间戳均不受影响 | | 6 | 随后对该二进制文件的任何执行都会映射已修改的页缓存页面 — 被修补的代码将以 `euid=0` 运行 | 写入操作最终落在内存中被拼接文件的缓存数据中,完全绕过了文件的权限限制。 ## 7. 向 LKML 提交补丁 ### 7.1 确定维护者 ``` ./scripts/get_maintainer.pl crypto/algif_aead.c # Herbert Xu # linux-crypto@vger.kernel.org ``` ### 7.2 验证补丁 ``` ./scripts/checkpatch.pl 0001-crypto-algif_aead-revert-inplace.patch ``` ### 7.3 Commit 消息格式 ``` crypto: algif_aead - restore separate src/dst scatterlists in recvmsg Commit 72548b093ee3 ("crypto: algif_aead - switch to in-place processing") set req->src == req->dst inside aead_recvmsg(). When the caller uses splice(2), the source scatterlist contains page cache pages of the spliced file. With the in-place optimization, those same pages become the writable destination passed to the AEAD transform. authencesn writes 4 bytes at offset (assoclen + cryptlen) into req->dst as scratch space for Extended Sequence Number rearrangement and does not restore them on the error path. With page cache pages present in dst, this write bypasses the VFS permission layer and corrupts the in-memory image of the spliced file without modifying the on-disk inode. An unprivileged local user can exploit this to overwrite arbitrary bytes in the page cache of any readable setuid binary and escalate privileges to root. Restore separate src and dst scatterlists so that page cache pages are confined to the read-only source path. Fixes: 72548b093ee3 ("crypto: algif_aead - switch to in-place processing") Cc: stable@vger.kernel.org # 4.14+ Reported-by: Taeyang Lee Signed-off-by: Your Name ``` ### 7.4 通过 `git send-email` 发送 ``` git send-email \ --to=herbert@gondor.apana.org.au \ --cc=linux-crypto@vger.kernel.org \ --cc=stable@vger.kernel.org \ 0001-crypto-algif_aead-revert-inplace.patch ``` ### 7.5 Commit 消息约定 | 元素 | 目的 | |---------|---------| | `subsystem: file - verb phrase` 主题 | 必需格式;不超过 72 个字符 | | `Fixes: ("original title")` | 触发自动的稳定版回移工具 | | `Cc: stable@vger.kernel.org` | 标记补丁以回移至 LTS 分支 | | `Reported-by:` | 归属于发现者 | | `Signed-off-by:` | 开发者出身证明 — 必需 | ## 8. 受影响的版本与缓解措施 受影响的内核包括从 Linux 4.14 到 7.0-rc 的版本,6.18.22 之前的所有 6.18.x 版本,以及 6.19.12 之前的 6.19.x 版本。 **临时缓解措施**(大多数系统无需重启): ``` echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.conf rmmod algif_aead 2>/dev/null || true ``` 此应对措施不会影响 dm-crypt/LUKS、kTLS、IPsec/XFRM、OpenSSL、GnuTLS、NSS 或 SSH。 ## 9. 参考 - Theori/Xint 公告:`xint.io/blog/copy-fail-linux-distributions` - NVD 条目:`nvd.nist.gov/vuln/detail/CVE-2026-31431` - 上游修复:commit `a664bf3d603d` (主线) - 引入该漏洞的 commit:`72548b093ee3` (Linux 4.14, 2017)
标签:0day挖掘, AF_ALG, algif_aead, Copy Fail, Crypto API, CVE-2026-31431, CVSS 7.8, Linux内核漏洞, Web报告查看器, 任意地址写, 内核安全, 安全渗透, 提权漏洞, 本地提权, 漏洞分析, 网络安全, 路径探测, 逻辑漏洞, 隐私保护, 页缓存