针对 CVE-2026-46331(又称 pedit COW)的只读审计脚本——这是 Linux 内核 net/sched 的 act_pedit 动作中的一个部分写时复制(copy-on-write)漏洞,允许本地非特权用户破坏页缓存内存并提权至 root。
____ _____ ____ ___ _____ ____ _____ __
| _ \| ____| _ \_ _|_ _| / ___/ _ \ \ / /
| |_) | _| | | | | | | | | | | | | \ \ /\ / /
| __/| |___| |_| | | | | | |__| |_| |\ V V /
|_| |_____|____/___| |_| \____\___/ \_/\_/
CVE-2026-46331 net/sched act_pedit partial COW
tcf_pedit_act() 在键循环之前,使用 tcfp_off_max_hint 为 skb_ensure_writable() 计算一次 COW 范围。类型化键会添加一个运行时头部偏移,而该提示并未覆盖此偏移,因此最终写入的一部分会落在 COW 区域之外。结果:共享的页缓存页面被涂改,缓存的 setuid 二进制文件(经典目标:/bin/su)可能在内存中被污染。磁盘上的哈希保持干净。文件完整性监控器不会发现它。
与 Dirty COW(CVE-2016-5195)、Dirty Pipe(CVE-2022-0847)、Copy Fail(CVE-2026-31431)和 Dirty Frag(CVE-2026-46300)属于同一类漏洞。入口点不同,但页面所有权失效是相同的。
| CVE | CVE-2026-46331 |
| 组件 | Linux 内核 net/sched / act_pedit |
| 类别 | 部分 COW → 页缓存损坏 → LPE |
| 攻击向量 | 本地(CAP_NET_ADMIN,通常通过非特权 userns 获取) |
| 上游受影响版本 | 5.18 .. 7.1-rc6 |
| 上游修复版本 | 7.1-rc7 |
| 公开 PoC | packet_edit_meme(已在 RHEL 10、Debian 13、Ubuntu 24.04.4 上验证) |
| Red Hat 严重性 | Important |
| SUSE CVSS 3.1 | 7.8 (AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H) |
严格只读的分诊。从不加载模块,从不修改 sysctl,从不执行 PoC。设计为可在生产环境安全运行。
act_pedit 的可达性:
lsmod)modinfo)/boot/config-$(uname -r)、/proc/config.gz、modules.builtin)modprobe.d 中的 install ... /bin/true 覆盖所阻止,或被 blacklist 阻止(在通过其 net-act-pedit 别名自动加载 act_pedit 的内核上,即 6.9+;较旧的内核按名称请求它,blacklist 无法阻止)tc action pedit 规则(仅供参考;不做更改)。user.max_user_namespaces、kernel.unprivileged_userns_clone、user.max_net_namespaces,以及 Ubuntu AppArmor userns 限制。/etc/os-release 的启发式厂商补丁矩阵(RHEL 8/9/10、Debian 11/12/13/14、Ubuntu 18.04→26.04、SUSE、Amazon Linux、Arch 系滚动发行版)。auditd 和 journalctl 进行可选的行为 IoC 搜寻(可通过 --since 和 --until 配置时间窗口)。PATCHED / NOT_APPLICABLE / MITIGATED / VULNERABLE / UNKNOWN。sudo ./cve-2026-46331-audit.sh # full text report
sudo ./cve-2026-46331-audit.sh --json # machine-readable JSON, no banner
sudo ./cve-2026-46331-audit.sh --quiet --no-hunt # one-line verdict for mass scans
sudo ./cve-2026-46331-audit.sh --since 2026-06-01 # widen IoC hunt window
sudo ./cve-2026-46331-audit.sh --since 2026-06-01 --until 2026-09-01 # bounded IoC window
sudo ./cve-2026-46331-audit.sh --no-banner # text report without the ASCII banner
./cve-2026-46331-audit.sh --version # print script version and exit
| 代码 | 含义 |
|---|---|
| 0 | PATCHED 或 NOT_APPLICABLE(内核早于该漏洞) |
| 1 | MITIGATED(缓解措施已生效,内核仍存在漏洞,仍应打补丁) |
| 2 | VULNERABLE(满足一个或多个必需前提条件,无已修复内核) |
| 3 | UNKNOWN(在共享 / CI / Kubernetes 环境中应视为可疑) |
| 4 | ERROR(脚本无法运行;缺少工具或环境异常) |
完整运行结果见 examples/sample-output.txt,JSON 格式见 examples/sample-output.json。
评分由以下各项加权组合而成:
| 信号 | 权重 |
|---|---|
厂商判定 VULNERABLE | +50 |
厂商判定 UNKNOWN | +30 |
act_pedit 已编译进内核 | +25 |
act_pedit 可加载,无覆盖 | +20 |
act_pedit 可加载,覆盖或黑名单已生效 | +5 |
act_pedit 当前已加载 | +5 |
| 非特权 userns+netns 可达,无 AppArmor 门控 | +15 |
| 非特权 userns+netns 可达,AppArmor 门控已生效 | +8 |
| 在排查窗口内发现 IoC | +10 |
上限为 100。在多租户 / CI / Kubernetes 节点上,高于约 70 的任何分数都应视为紧急;低于约 20 通常可确认主机状态正常。
ansible -i inventory all -m script \
-a "cve-2026-46331-audit.sh --json --quiet --no-hunt" \
--become \
| tee /tmp/audit.jsonl
然后用 jq 进行聚合:
grep -v '^[a-z]' /tmp/audit.jsonl | jq -s 'group_by(.verdict) | map({verdict: .[0].verdict, hosts: length})'
- name: audit CVE-2026-46331
ansible.builtin.script: cve-2026-46331-audit.sh --quiet --no-hunt
register: audit
failed_when: audit.rc == 2
changed_when: false
按优先级排序。脚本会根据其发现的内容推荐合适的方案。
# Option 1: block act_pedit if you don't use it.
tc actions list action pedit # MUST be empty before doing this
# 1a) Hard block via modprobe install override (strongest).
echo 'install act_pedit /bin/true' | sudo tee /etc/modprobe.d/disable-act_pedit.conf
# 1b) `blacklist act_pedit` only stops the autoload on kernels 6.9+, which
# request the "net-act-pedit" alias. Older kernels load it by name and
# ignore the blacklist, so prefer 1a. Check your kernel:
modinfo -F alias act_pedit | grep -qx net-act-pedit && echo "blacklist works here"
lsmod | grep -q act_pedit && sudo rmmod act_pedit
# Option 2: restrict unprivileged user namespaces.
# Will break rootless Podman/Docker, browser sandboxes, Flatpak, unprivileged unshare, some CI sandboxes.
sudo sysctl -w user.max_user_namespaces=0 # EL-family
sudo sysctl -w kernel.unprivileged_userns_clone=0 # Debian/Ubuntu
# Option 2b: restrict network namespaces (breaks the CAP_NET_ADMIN acquisition path).
# Less disruptive than disabling all user namespaces, but still breaks some container tooling.
sudo sysctl -w user.max_net_namespaces=0
真正的修复方案是厂商内核更新加重启。重启后执行 uname -r 是唯一能证明修复生效的方式。
这是同一架构性缺陷的第五次迭代。每一次都修复了直接原因,却都没有修复根本原因:零拷贝快速路径在所有权边界之间共享页面,而每个写入者都必须在数百个调用点中先证明隐私性,才能修改字节。
| CVE | 年份 | 子系统 | 原语 |
|---|---|---|---|
| CVE-2016-5195 | 2016 | mm | 只读映射上的 COW 竞态 |
| CVE-2022-0847 | 2022 | pipe / splice | pipe_buffer 标志泄漏进页缓存 |
| CVE-2026-31431 | 2026 | crypto AF_ALG/AEAD | 对只读文件缓存的原地加密 |
| CVE-2026-46300 | 2026 | XFRM ESP-in-TCP | skbuff 共享分片标记丢失 |
| CVE-2026-46331 | 2026 | net/sched act_pedit | 延迟解析的类型化键偏移导致的部分 COW |
内核内 Rust 正是通过所有权类型来解决这一类问题。它不会明天就出现在 net/sched 中。
MIT。参见 LICENSE。
仅供在您拥有或明确获准审计的系统上进行授权的防御性使用。该脚本从不执行公开 PoC,从不修改系统状态,也从不加载模块。请将判定结果视为分诊参考,而非入侵证据或安全证明。