Chase's Daily Chase's Daily
Chase's Daily
© 2026 Chasedaily.cn 版权所有. 本网站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议, 转载请注明出处 京ICP备2026068377号-1

Debian 13 内核升级实录:修复 CVE-2026-99999(PwnEscape)虚拟机逃逸漏洞

摘要:2026 年 10 月公开的 CVE-2026-99999(代号 PwnEscape)是一个位于 宿主机 Linux 网络栈 的 guest-to-host 逃逸漏洞,对任何运行多租户 KVM 的环境都构成直接威胁。本文记录一台 Debian 13 节点从"确认受影响"到"升级内核并重启验收"的完整过程,包含全部命令与真实回显,并给出多节点推广、回滚预案与长期治理方案。

1. 漏洞背景

1.1 一句话概括

漏洞不在 KVM 里,而在宿主机 Linux 的 IPv4 校验和补全路径:客户机可以提交伪造的 virtio 校验和元数据,使内核在已经校验过 IPv4 头之后再向报文写入 2 字节,从而把 IPv4 首字节从 0x45(IHL=5,20 字节头)改成 0x4f(IHL=15,60 字节头)。随后输出分片(ip_do_fragment())按 60 字节复制"头部",把超出报文逻辑长度的 32 字节宿主内存当作 IP options 发了出去。

1.2 利用链

不可信输入(guest)                      宿主机网络栈
─────────────────────                  ─────────────────────────────
报文 + CHECKSUM_PARTIAL 元数据 ───────► 卸载元数据写入 skb
                                        │
                                        ▼
                                   链路层剥离 / L3 规范化
                                        │
                                        ▼
                                   IPv4 解析、重组、策略、路由
                                   (此时信任 IHL=5 / 20 字节)
                                        │
                                        ▼
                                   输出分片
                                        │
                                        ▼
                                   skb_checksum_help()
                                   (延迟写入覆盖了已被解析的头)
                                        │
                                        ▼
                                   ip_do_fragment() 读取晚到的 IHL
                                   头部现在声称 60 字节
                                        │
                                        ▼
                                   头部拷贝超出逻辑线性数据
                                        │
                                        ▼
                                   发出的 IP options 里含宿主内存

三个关键认知:

  1. skb->csum_start / csum_offset 不是描述性元数据,而是一次写入授权:写入位置 = csum_start + csum_offset。
  2. 校验发生在解析时,写入发生在分片时。两者之间头已经被信任过一次,属于语义上的 TOCTOU(时间差完全确定,不依赖线程竞争)。
  3. 32 字节泄露只是第一步。研究者用宿主内存观测 + 堆布局控制,在自有实验机上实现了受控的 64 字节内核写,并在四次冷启动中复现了"执行宿主 root helper 并回传标记"的完整链路。

1.3 影响面与时间线

项目内容
CVECVE-2026-99999
类型宿主内存泄露 → 内核写 → guest-to-host 逃逸
受影响范围使用 virtio-net 校验和卸载路径的 Linux KVM 宿主机(默认配置即在影响面内);TUN / AF_PACKET 场景同样触及
上游修复6785011f8b16,提交标题 ipv4: validate checksum_start before completing checksum
上游节奏2026-10-08 进入 net.git,2026-10-14 合入主线
公开披露2026-10-15(oss-security)
研究者预期"较弱配置的利用数周内出现,默认配置的利用一个月内出现"

修复本身是一个纵深防御性质的守卫(官方提交信息明确如此描述),更完整的入站侧校验仍在推进。也就是说:打完这个补丁不等于终点,后续还会有跟进的内核更新。

1.4 Debian 的修复状态

发行版版本状态
trixie(Debian 13)security6.12.113-1✅ 已修复(DSA-6568-1)
trixie(发布源)6.12.107-1❌ 受影响
bookworm(Debian 12)security6.1.187-1❌ 仍受影响,暂无修复
sid7.2.11-1✅ 已修复

结论:Debian 13 已有官方修复版;Debian 12 目前没有。 这一步决定了整改路线——Debian 13 节点一条 apt 命令即可修完,Debian 12 节点则只能先缩小暴露面。

1.5 为什么这类漏洞不能等

  • 我们是多租户 KVM 宿主,客户机本身就是"不可信 guest",与漏洞前提完全一致;
  • 逃逸成功后,同一宿主机上的所有客户机、以及宿主机上的所有凭据全部沦陷;
  • 上游定性为纵深防御,后续还有补丁 → 这意味着"等一个更完整的修复"是错误策略,应当立即跟进。

2. 确认自己是否受影响

root@debian:~# uname -r
6.12.73+deb13-amd64
当前内核判定
< 6.12.113受影响,需升级
>= 6.12.113已包含修复

本机为 6.12.73 → 受影响。


3. 修复路线选型

路线可行性结论
发行版安全源(trixie-security)已提供 6.12.113-1采用。一条命令、有签名、可回滚、后续可持续跟进
backports修复版已进安全源,无必要不采用
自行编译 / 手工打补丁破坏包管理与签名链,后续升级会打架不采用
内核热补丁(livepatch / kpatch / kGraft)Debian 无官方支持不采用,必须重启

4. 升级前的三个检查

4.1 确认 apt 源包含 trixie-security

Debian 13 使用 deb822 格式:

root@debian:~# cat /etc/apt/sources.list.d/*.sources
Types: deb
URIs: http://deb.debian.org/debian
Suites: trixie trixie-updates
Components: main contrib non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg

Types: deb
URIs: http://security.debian.org/debian-security
Suites: trixie-security
Components: main contrib non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg

修复版只存在于 trixie-security,源里没有它,后面无论怎么 apt 都拿不到补丁。

4.2 确认候选版本(核心判据)

root@debian:~# apt-get update
Hit:1 http://security.debian.org/debian-security trixie-security InRelease
Hit:2 http://deb.debian.org/debian trixie InRelease
Get:3 http://deb.debian.org/debian trixie-updates InRelease [47.3 kB]
Fetched 47.3 kB in 0s (235 kB/s)
Reading package lists... Done

root@debian:~# apt-cache policy linux-image-amd64
linux-image-amd64:
  Installed: 6.12.73-1
  Candidate: 6.12.113-1
  Version table:
     6.12.113-1 500
        500 http://security.debian.org/debian-security trixie-security/main amd64 Packages
     6.12.107-1 500
        500 http://deb.debian.org/debian trixie/main amd64 Packages
 *** 6.12.73-1 100
        100 /var/lib/dpkg/status

判据:Candidate 必须 ≥ 6.12.113-1。

顺带说明两个容易被忽略的点:

  • trixie-security 与主源优先级同为 500,apt 取版本号最高的那个,因此 6.12.113-1 会胜过 6.12.107-1;
  • 若 Candidate 仍是 73 或 107,说明镜像源未同步或安全源未生效——此时不要装,先对照 DSA-6568-1 排查,否则会"装了个新内核但其实没修"。

4.3 干跑,确认不会移除任何包

root@debian:~# apt-get --dry-run install linux-image-amd64
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  linux-image-6.12.113+deb13-amd64
Suggested packages:
  firmware-linux-free linux-doc-6.12 debian-kernel-handbook
The following NEW packages will be installed:
  linux-image-6.12.113+deb13-amd64
The following packages will be upgraded:
  linux-image-amd64
1 upgraded, 1 newly installed, 0 to remove and 80 not upgraded.
Inst linux-image-6.12.113+deb13-amd64 (6.12.113-1 Debian-Security:13/stable-security [amd64])
Inst linux-image-amd64 [6.12.73-1] (6.12.113-1 Debian-Security:13/stable-security [amd64])
Conf linux-image-6.12.113+deb13-amd64 (6.12.113-1 Debian-Security:13/stable-security [amd64])
Conf linux-image-amd64 (6.12.113-1 Debian-Security:13/stable-security [amd64])

三个要点:

  1. 0 to remove —— 没有任何删除动作,说明不会动到 libvirt / QEMU 等依赖;
  2. 来源标注为 Debian-Security:13/stable-security —— 确认装的是安全源版本,而不是发布源里的旧版;
  3. 80 not upgraded —— 这是正确的结果。本机还有 80 个包可升级,但那与本次修复无关;宿主机上的 libvirt / QEMU 升级需要单独评估窗口,不应顺手带过。

5. 执行升级

5.1 安装命令,以及两个"不要"

apt-get install -y linux-image-amd64

❌ 不要加 --only-upgrade:新内核是一个新包(linux-image-6.12.113+deb13-amd64),--only-upgrade 禁止安装新包,会直接因依赖不满足而失败。

❌ 不要用 apt full-upgrade:那会连同 libvirt、QEMU 一起升级。宿主机上这两个组件的变更必须单独做评估与回归,不能掩盖在一次内核升级里。

5.2 真实安装输出解读

root@debian:~# apt-get install -y linux-image-amd64
Need to get 108 MB of archives.
After this operation, 111 MB of additional disk space will be used.
Get:1 http://security.debian.org/debian-security trixie-security/main amd64 linux-image-6.12.113+deb13-amd64 amd64 6.12.113-1 [108 MB]
Get:2 http://security.debian.org/debian-security trixie-security/main amd64 linux-image-amd64 amd64 6.12.113-1 [1,480 B]
Fetched 108 MB in 2s (60.1 MB/s)
...
Setting up linux-image-6.12.113+deb13-amd64 (6.12.113-1) ...
I: /vmlinuz is now a symlink to boot/vmlinuz-6.12.113+deb13-amd64
I: /initrd.img is now a symlink to boot/initrd.img-6.12.113+deb13-amd64
/etc/kernel/postinst.d/initramfs-tools:
update-initramfs: Generating /boot/initrd.img-6.12.113+deb13-amd64
/etc/kernel/postinst.d/zz-update-grub:
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-6.12.113+deb13-amd64
Found initrd image: /boot/initrd.img-6.12.113+deb13-amd64
Found linux image: /boot/vmlinuz-6.12.73+deb13-amd64
Found initrd image: /boot/initrd.img-6.12.73+deb13-amd64
Warning: os-prober will not be executed to detect other bootable partitions.
Systems on them will not be added to the GRUB boot configuration.
Check GRUB_DISABLE_OS_PROBER documentation entry.
Adding boot menu entry for UEFI Firmware Settings ...
done
Setting up linux-image-amd64 (6.12.113-1) ...

四个关键信息:

  • initramfs 已重新生成,没有它就起不来;
  • GRUB 同时找到新内核与旧内核(113 与 73)→ 回滚路径存在,这是判断本次操作是否"可逆"的核心依据;
  • /vmlinuz、/initrd.img 软链已切到新内核;
  • os-prober 那条 warning 在单系统盘上是正常提示,可忽略。

5.3 重启前验证

root@debian:~# dpkg-query -W -f='${Version}\n' linux-image-amd64
6.12.113-1

root@debian:~# ls -1 /boot/vmlinuz-*
/boot/vmlinuz-6.12.113+deb13-amd64
/boot/vmlinuz-6.12.73+deb13-amd64

root@debian:~# df -h /boot
Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme0n1p2  944M  114M  765M  13% /boot

另外建议立刻把旧内核标记为手动安装,防止日后 apt autoremove 清理掉回滚路:

apt-mark manual linux-image-6.12.73+deb13-amd64

以及一条运维常识:/boot 独立分区只有 944M,一套内核(image + initrd)约 60M,装三四个没问题;但要定期 apt autoremove --purge,/boot 塞满会导致下一次内核安装直接失败。


6. 重启与验收

6.1 确认新内核已启动

root@debian:~# uname -r
6.12.113+deb13-amd64

登录横幅同样能确认:

Linux debian 6.12.113+deb13-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.113-1 (2026-10-15) x86_64

6.2 网络与 DNS 的持久化验证

内核升级必然伴随重启,重启暴露出来的问题往往不是内核,而是网络配置是否持久。先在重启前确认"谁在管网络":

root@debian:~# systemctl is-enabled networking systemd-networkd NetworkManager
enabled
disabled
not-found

root@debian:~# systemctl is-active networking systemd-networkd NetworkManager
active
inactive
inactive

root@debian:~# cat /etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback

auto ens1f0np0
iface ens1f0np0 inet static
        address 198.51.100.10/24
        gateway 198.51.100.1
root@debian:~# systemctl is-enabled cloud-init
not-found
组合含义重启风险
networking active + interfaces 里是 inet staticifupdown 静态配置无,原样恢复
interfaces 里是 inet dhcp地址由 DHCP 下发可能变 IP,需确认保留绑定
systemd-networkd / NetworkManager 接管看对应目录下的配置取决于配置
cloud-init 存在开机可能重写网络需要单独确认

本机结论:ifupdown + 静态地址 + 无 cloud-init → 重启后网络原样恢复。

一个容易被忽略的坑:DNS

interfaces 里只有 address 和 gateway,没有 dns-nameservers。若 /etc/resolv.conf 是由 resolvconf 在启动时根据 interfaces 重新生成的,重启后它会是空的——表现为 ping 1.1.1.1 通、ping deb.debian.org 不通、apt 直接报错。

重启前先查:

ls -l /etc/resolv.conf
cat /etc/resolv.conf
  • 普通文件且写着 nameserver → 不会被动,无需处理;
  • 软链(指向 /run/resolvconf/... 或 systemd-resolved 的 stub)→ 会被重生成,在 interfaces 里补一行:
    dns-nameservers 1.1.1.1 8.8.8.8

改完用 ifquery ens1f0np0 校验语法(不要用 systemctl restart networking 去应用,重启会自己生效)。

6.3 重启前后对照

重启前留档,重启后逐项对比——这是验证持久化最省事的办法:

ip -br a > /root/pre-reboot-net.txt
ip route >> /root/pre-reboot-net.txt
cat /etc/resolv.conf >> /root/pre-reboot-net.txt

重启后:

diff <(ip -br a; ip route) /root/pre-reboot-net.txt && echo "网络配置完全一致"
cat /etc/resolv.conf
uname -r
systemctl --failed
ping -c2 1.1.1.1 && ping -c2 deb.debian.org
dmesg --level=err,warn | tail -20

6.4 验收判定表

检查项通过标准
内核uname -r = 6.12.113+deb13-amd64
回滚路/boot 中旧内核仍在
网络diff 无输出,IP / 路由 / DNS 一致
系统systemctl --failed 为空
外网ICMP 与 DNS 解析都通
硬件dmesg 无新增 nvme / 网卡 error

7. 如何验证补丁"真的生效":两个错误做法与一个正确做法

这一节值得单独写,因为很容易得出错误结论。

❌ 错误做法一:在 Debian 内核 changelog 里 grep 提交主题

zcat /usr/share/doc/linux-image-*/changelog.Debian.gz | grep -i checksum_start   # 无输出

Debian 内核包的 changelog.Debian.gz 只记录发布层面的变更(如 "Rebase to 6.12.113"、DSA 编号),不记录上游逐条提交的主题。查不到不代表补丁没进。

❌ 错误做法二:在 System.map 里找 ip_check_csum_start

grep -c ip_check_csum_start /boot/System.map-6.12.113+deb13-amd64               # 0

该策略函数在上游是 static inline,会被内联到调用点,编译产物里没有对应符号。用 0 来判断"没修复"是彻底误判。

✅ 正确做法:用版本号对照发行版安全跟踪器

判据本次取值
Debian 官方标记的修复版本(trixie)6.12.113-1
本机已安装版本6.12.113-1
包来源Debian-Security:13/stable-security

三者一致即视为已修复。这条链路同时被官方公告(DSA-6568-1)与安全跟踪器背书,比任何二进制特征扫描都可靠。


8. 推广到其它节点

8.1 分批顺序

先在无任何业务负载的节点上验证(本次即如此),确认"新内核能在这批硬件上启动"之后,再推有业务的节点。理由是:内核升级真正的风险不是软件包,而是新内核在你这个硬件平台上能不能起来、网卡与 NVMe 是否正常——空机器是零成本的探雷器。

8.2 有虚拟机的宿主机:附加步骤

# 1) 留档现状
virsh list --all
virsh net-list --all
ip -br a; ip route
findmnt /homedata; swapon --show

# 2) 优雅关机所有虚拟机
for d in $(virsh list --name); do virsh shutdown "$d"; done
watch -n2 'virsh list --all'        # 等到全部 shut off 再继续

关于关机必要性的说明:

  • 磁盘缓存为 cache=none 时,客户机数据本身是落盘的,直接重启不会损坏镜像,但优雅关机仍然是标准动作——它保证客户机文件系统干净卸载;
  • 若使用 cache=unsafe(忽略客户机 flush),则必须优雅关机,直接重启或断电会导致客户机文件系统乃至 qcow2 元数据损坏。

重启后除 6.3 的清单,还要复核宿主机侧服务:

virsh net-list --all                # 路由型网络应为 active + autostart yes
sysctl -n net.ipv4.ip_forward       # 1
systemctl is-active libvirtd vf-nginx vf-php8-fpm supervisor
ss -lntp | grep 8892                # 面板通信端口
findmnt /homedata && swapon --show

8.3 网络配置经过手工改造的节点:分两次重启

如果某台节点的网络是手工改过的(例如私有 /31 传输段 + 公网 /24 三层路由 + libvirt 路由型网桥),且此前从未经历一次完整重启,那么建议:

步骤目的
第 1 次:不升内核,纯重启单独验证网络/存储/网桥的持久化是否成立
第 2 次:升内核后再重启此时若异常,可确定是内核而非配置导致

两次重启之间留出观察时间。把两个变量拆开,是把"起不来"从"不可诊断"变成"可诊断"的最便宜手段。

8.4 回滚的三种手段

场景手段
新内核起得来但有问题GRUB 里选旧内核启动,然后 apt-mark hold linux-image-amd64 钉住版本
新内核完全起不来带外管理(IPMI / KVM over IP)进入 GRUB → Advanced options → 选旧内核
想预设一次性默认项grub-reboot "<旧内核菜单标题>",只影响下一次启动

前提是带外管理可用。没有带外管理的单机执行内核升级,等于把机器交给运气。


9. 临时缓解:为什么基本没有

在补丁窗口期内,常见三个"聪明办法"都不成立:

候选方案结论原因
关闭 virtio 网卡的 TX 校验和卸载(-global virtio-net-pci.guest_csum=off)不可靠入站解析路径不校验特性是否协商,恶意客户机可以自行置位 NEEDS_CSUM,仍然走 CHECKSUM_PARTIAL
改用 e1000 / vmxnet3 等网卡模型无效这些模型同样具备校验和卸载能力,且性能更差
限制客户机 MTU、减少宿主分片仅降低概率客户机可自行构造超过宿主 MTU 的帧,绕过自身协议栈约束

唯一正解是升级内核。 窗口期内能做的只有缩小爆炸半径:

  • 面板通信端口(8892)只允许控制端 IP 访问,SSH 限制来源;
  • 宿主机保持最小化,除虚拟化管理套件外不安装其它服务;
  • 在补丁完成前,不向不可信租户开放新的多租户实例。

10. 长期:把内核升级做成 SOP

一个逃逸级漏洞必然有下一个。把本次流程固化下来,比记住某一次的命令更有价值。

10.1 只自动下载,不自动重启

apt-get install -y unattended-upgrades apt-listchanges
dpkg-reconfigure -plow unattended-upgrades

确认 /etc/apt/apt.conf.d/50unattended-upgrades 中:

Unattended-Upgrade::Automatic-Reboot "false";

宿主机必须人工把住重启窗口(要优雅关机所有虚拟机),自动重启是事故制造机。

10.2 订阅源

10.3 标准作业流程

步骤动作判据
1查安全跟踪器,确认修复版本得到形如 6.12.113-1 的目标版本
2apt-get update + apt-cache policy linux-image-amd64Candidate ≥ 修复版本
3apt-get --dry-run install linux-image-amd64无 Remv,来源为 security
4优雅关机所有虚拟机virsh list --all 全部 shut off
5apt-get install -y linux-image-amd64无报错,initramfs 与 grub 正常生成
6reboot—
7验收清单内核版本、systemctl --failed、网络、8892、存储、虚拟机自启

10.4 心态

本次修复被上游明确描述为纵深防御,完整的入站侧校验仍在推进。这意味着 6.12.113 修掉的是已知的这一条利用链,而不是这一类问题的全部。把内核升级当作常规动作,而不是一次性事件。


11. 经验清单

必须做

  • 升级前确认 Candidate ≥ 官方标记的修复版本,来源必须是 security 源;
  • 干跑确认 0 to remove,不用 full-upgrade 夹带其它组件升级;
  • 确认 /boot 里旧内核仍在(回滚路),并 apt-mark manual 防止被 autoremove 清掉;
  • 有带外管理再动内核升级;
  • 有虚拟机的宿主机,重启前优雅关机所有虚拟机;
  • 重启前留档网络状态,重启后 diff 比对;
  • 检查 interfaces 是否缺 dns-nameservers(重启后 DNS 丢失的经典原因)。

禁止做

  • 用 grep changelog 或 grep System.map 判断补丁是否生效;
  • 加 --only-upgrade 装内核(会因依赖不满足失败);
  • 在宿主机上 apt full-upgrade(libvirt/QEMU 变更需要单独窗口);
  • 无带外管理、有虚拟机在跑的情况下直接重启;
  • 把"打完这个补丁"当作该类问题的终点。

附录 A:命令速查

# 判断是否受影响
uname -r

# 确认源与候选版本
cat /etc/apt/sources.list.d/*.sources
apt-get update && apt-cache policy linux-image-amd64

# 干跑(判据:0 to remove,来源为 security)
apt-get --dry-run install linux-image-amd64

# 安装(不加 --only-upgrade,不用 full-upgrade)
apt-get install -y linux-image-amd64

# 重启前确认
dpkg-query -W -f='${Version}\n' linux-image-amd64
ls -1 /boot/vmlinuz-*
df -h /boot
apt-mark manual linux-image-6.12.73+deb13-amd64

# 重启前留档
ip -br a > /root/pre-reboot-net.txt; ip route >> /root/pre-reboot-net.txt

# 重启后验收
uname -r
diff <(ip -br a; ip route) /root/pre-reboot-net.txt && echo "网络配置完全一致"
systemctl --failed
ping -c2 1.1.1.1 && ping -c2 deb.debian.org
dmesg --level=err,warn | tail -20

附录 B:参考资料

上一篇 VirtFusion 被控节点部署实录:私有 /31 传输段 + 公网 /24 三层路由环境下的桥接与存储规划 下一篇 答不上来的时候

暂无评论

正在验证… Ctrl + Enter 发送

还没有评论,来说点什么吧

© 2026 Chasedaily.cn 版权所有. 本网站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议, 转载请注明出处
京ICP备2026068377号-1