
KVM/x86 shadow-MMU の use-after-free(Zapscape、CVE-2026-64561)に対する汎用カーネルライブパッチ
English | 简体中文
CentOS Stream 8 / RHEL 8(4.18.0 全シリーズカーネル)の KVM ホストにおいて CVE-2026-64561(Zapscape) 脆弱性を修正するカーネルライブパッチ:
パッチを適用しないリスク:テナント仮想マシン(guest)が自身の操作のみでホストへ エスケープし、ホストカーネルの root 権限でコードを実行できる——物理マシン全体とその上の すべての仮想マシンが突破される。
本プロジェクトのパッチ:Linux アップストリームの公式修正(2abd5287f083)を
ベースにバックポートしたもので、カーネル livepatch 機構によりオンラインで有効化される:
✅ ホストを再起動しない ✅ 仮想マシンを再起動しない ✅ 仮想化機能を一切無効化しない ✅ 全工程を通じて無停止
Zapscape のトリガー条件はプラットフォームごとに異なる:AMD は追加のハードウェア要件が一切ない(SVM/NPT をサポートする任意の CPU でトリガー可能);Intel は 5 レベル EPT(EPT page-walk length 5、PWL5)をサポートし、かつホストがそれを L1 に公開している必要があり、そうでなければ root/child エイリアスを構築できず、この攻撃経路はトリガーできない。
| プラットフォーム | CPU シリーズ | トリガー可能(パッチ適用が必要) |
|---|---|---|
| Intel | Xeon Scalable 第 1 世代 — Skylake-SP(4100/5100/6100/8100) | ✗ いいえ |
| Intel | Xeon Scalable 第 2 世代 — Cascade Lake(4200/5200/6200/8200) | ✗ いいえ(本リポジトリで実測した 8259CL を含む) |
| Intel | Xeon Scalable 第 3 世代 — Ice Lake-SP(4300/5300/6300/8300) | ✓ はい |
| Intel | Xeon Scalable 第 4 世代 — Sapphire Rapids(8400) | ✓ はい |
| Intel | Xeon Scalable 第 5 世代 — Emerald Rapids(8500) | ✓ はい |
| Intel | その他(Xeon E、Cooper Lake 83xxH などのエッジモデル) | 実測による |
| AMD | EPYC 第 1–3 世代(Naples 7001 / Rome 7002 / Milan 7003) | ✓ はい(LA57 がなくても不要) |
| AMD | EPYC 第 4 世代(Genoa/Bergamo/Siena 9004/8004) | ✓ はい |
根拠:5-level paging / 5-level EPT は Intel が Ice Lake マイクロアーキテクチャで初めて実装した(Wikipedia: Intel 5-level paging;Intel ホワイトペーパー「5-Level Paging and 5-Level EPT」、文書番号 671442);本リポジトリでは Xeon Platinum 8259CL(Cascade Lake)上で IA32_VMX_EPT_VPID_CAP (MSR 0x48C) の bit 7(PWL5)= 0 を実測し、/proc/cpuinfo に la57 は存在しない——Cascade Lake 以前には 5 レベル EPT がないことを裏付けている。AMD の NPT は常に 4 レベルのハードウェア walk であり、Zapscape は 5 レベルの機能を必要としないため、AMD は全世代でトリガー可能である。
⚠️ 世代表はあくまで参考であり、実測を優先する(クラウドプロバイダー/ファームウェアが機能を無効化している場合がある)。1 つのコマンドで、お使いの Intel ホストにパッチが必要かどうかを確認できる:
# 方法一(简单):检查 LA57(5-level paging)
grep -m1 flags /proc/cpuinfo | grep -o la57 && echo "有 LA57 → 需打补丁" || echo "无 LA57 → 大概率无需"
# 方法二(直接,Intel 专用):读取 EPT 能力 MSR 0x48C 的 bit 7(PWL5)
dnf install -y msr-tools && modprobe msr
V=$(rdmsr -p0 0x48c); echo "EPT PWL5 支持: $(( (0x$V >> 7) & 1 ))" # 1=支持(需打补丁) 0=不支持
⚠️「トリガー不可」≠「絶対安全」:これはZapscapeのIntel攻撃経路が成立しないことのみを意味します。KVM shadow MMUには依然として他のリスクが存在する可能性があるため、引き続き公式のセキュリティアップデートにご注意ください。
ホストマシンが他の CVE 対応のために新しいカーネルを必要とし、ELRepo から kernel-ml
(mainline カーネル)をインストールした場合、Zapscape の修正状態はバージョンによって異なります:
| kernel-ml バージョン | Zapscape の状態 | 対応 |
|---|---|---|
| 7.1.3 / 7.1.4 | ❌ 未修正(ソースコードで検証済み) | 7.1.7 にアップグレードするか、本リポジトリの kernel-ml livepatch(実測済み)を使用 |
| 7.1.5 / 7.1.6 | ✅ 修正済み(上流 2abd5287f083 がマージ済み) | 対応不要 |
| 7.1.7 | ✅ 修正済み(ソースコードで検証済み) | 対応不要 |
CONFIG_LIVEPATCH=y + CONFIG_KLP_BUILD=y + objtool klp サブコマンド)、
kpatch は不要です。本リポジトリではカーネルネイティブの objtool klp diff + post-link フローを用い、
7.1.7 で修正済みの direct_page_fault / paging64_page_fault /
paging32_page_fault / ept_page_fault を置換本体として、7.1.3 向けの
livepatch モジュールを生成します(livepatch/kernel-ml/、詳細は
livepatch/kernel-ml/README.md を参照)。
7.1.3(自前ビルド、ELRepo 7.1.x のソースと一致)上で実測済み:
kpatch/objtool が生成したモジュールは正常にロードされ、/sys/kernel/livepatch には
4 つの関数すべてが置換済み(enabled=1)、transition 完了と表示され、稼働中の仮想マシンは一切影響を受けません。注記:7.1.x では kpatch 時代の旧形式
klp_relocが削除され、.klp.rela.*セグメント(klp_resolve_symbolsで解決)に変更されたため、4.18 用の kpatch 0.9.x ツールチェーンは 7.1.x では使用できません。本リポジトリの kernel-ml 向け手法は完全にカーネルネイティブの KLP ツールチェーンに基づいています。
ELRepo 公式リポジトリ(elrepo.org)は中国国内からの接続性が悪いため(実測約 15 kB/s)、 国内ミラー(実測 4 MB/s 以上)に切り替えてください:
# 安装 elrepo-release(一次)
dnf install -y https://www.elrepo.org/elrepo-release-8.el8.elrepo.noarch.rpm
# 把 elrepo-kernel 源切换到清华 TUNA 镜像(中科大 USTC 同样可用:
# https://mirrors.ustc.edu.cn/elrepo/kernel/el8/$basearch/)
awk '
/^\[elrepo-kernel\]/ {ink=1}
/^\[/ && !/^\[elrepo-kernel\]/ {ink=0}
ink && /^baseurl=/ { print "baseurl=https://mirrors.tuna.tsinghua.edu.cn/elrepo/kernel/el8/$basearch/"; next }
ink && /^[[:space:]]/ { next }
ink && /^mirrorlist=/ { print "#" $0; next }
{ print }
' /etc/yum.repos.d/elrepo.repo > /etc/yum.repos.d/elrepo.repo.new && \
mv /etc/yum.repos.d/elrepo.repo.new /etc/yum.repos.d/elrepo.repo
# 安装最新 mainline 内核(含 kernel-ml-devel,kpatch 构建也需要它)
dnf --enablerepo=elrepo-kernel install -y kernel-ml kernel-ml-devel
# 确认新内核成为默认启动项
grubby --default-kernel
# 输出 /boot/vmlinuz-7.1.7-1.el8.elrepo.x86_64 即为成功
⚠️ カーネルのアップグレードは再起動しないと反映されません。再起動すると 4.18 カーネル上で既にロードされている livepatch が 無効になります(新しいカーネルに修正が組み込まれている場合は再ロード不要です)。再起動前に仮想マシンの復旧メカニズムを確認してください (魔方雲パネルは管理下の VM を自動的に起動します)。
| 項目 | 要件 |
|---|---|
| OS | CentOS Stream 8 / RHEL 8(8.0 ~ 8.10 の全ブランチを含む) |
| 仮想化プラットフォーム | 智簡魔方 魔方雲 KVM強化版(idcsmart Cloud KVM)——実測済み |
| カーネル | 4.18.0-* の任意のサブバージョン(4.18.0-80 ~ 4.18.0-553 の全コード形態をカバー済み) |
| 権限 | root |
| 依存関係 | gcc、make、git、patch、elfutils、openssl-devel、bc、bison、flex、dwarves、kpatch、kernel-devel(実行中カーネルと同一バージョン)、カーネルソース RPM |
| 時間 | 初回ビルドは約 20~40 分(CPU コア数に依存) |
カーネルは livepatch をサポートしている必要があります(
CONFIG_LIVEPATCH=y、RHEL 8 / Stream 8 ではデフォルトで有効)。 デプロイのステップ 0 で最初に確認します。
grep CONFIG_LIVEPATCH /boot/config-$(uname -r)
CONFIG_LIVEPATCH=y を出力する必要があります。そうでない場合、そのカーネルはライブパッチを適用できません。
# 中国大陆网络环境请用 ghproxy 加速镜像(直连 GitHub 可能失败):
# git clone https://ghproxy.net/github.com/Aoripus-LTD/Zapscape-Fix.git
git clone https://github.com/Aoripus-LTD/Zapscape-Fix.git
cd Zapscape-Fix/livepatch
dnf install -y gcc make git patch elfutils elfutils-devel \
elfutils-libelf-devel openssl-devel bc bison flex dwarves \
yum-utils dnf-plugins-core kpatch kpatch-dnf
dnf install -y kernel-devel-$(uname -r)
CentOS Stream 8 は 2024-05-31 にサポート終了(EOL)となったため、デフォルトのソフトウェアリポジトリは無効になっており、
dnf download --source kernel はほとんどのマシンで失敗します。以下のいずれかの方法を選んでください。
dnf ファミリー全体が使えるようになる)阿里雲ミラーを例に挙げます(テスト環境で実測済み、利用可能):
# 把 Stream 8 的源从已失效的 mirrorlist 切换到 vault 快照
sed -i 's|^mirrorlist=|#mirrorlist=|; s|^#baseurl=http://mirror.centos.org|baseurl=http://mirrors.aliyun.com/centos-vault|' \
/etc/yum.repos.d/CentOS-Stream-*.repo
dnf clean all && dnf makecache
# 然后正常下载内核源码(会自动定位到正确文件)
dnf download --source kernel
清華ミラーも同様に利用可能です。上記の
mirrors.aliyun.com/centos-vaultをmirrors.tuna.tsinghua.edu.cn/centos-vaultに置き換えてください。
# URL 规则:<镜像>/centos-vault/8-stream/BaseOS/Source/SPackages/Packages/kernel-<内核版本>.src.rpm
# 内核版本 = uname -r 去掉结尾的 .x86_64,例如:
curl -O http://mirrors.aliyun.com/centos-vault/8-stream/BaseOS/Source/SPackages/Packages/kernel-4.18.0-553.6.1.el8.src.rpm
# 也可以自动拼出你自己的内核版本:
VER=$(uname -r | sed 's/\.x86_64$//')
curl -O "http://mirrors.aliyun.com/centos-vault/8-stream/BaseOS/Source/SPackages/Packages/kernel-${VER}.src.rpm"
rpm2cpio kernel-*.src.rpm | cpio -idmv 'linux*.tar.xz'
tar xf linux-*.tar.xz
SRC=$(ls -d /root/linux-* | head -1)
echo "内核源码目录: $SRC"