
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)을 기반으로
backport되었으며, 커널 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 전 세대에서 트리거 가능합니다.
⚠️ 세대 표는 참고용이며, 실측 기준입니다(클라우드 사업자/펌웨어가 기능을 비활성화했을 수 있음). 다음 명령 하나로 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을 자동으로 기동합니다).
| 항목 | 요구 사항 |
|---|---|
| 운영 체제 | 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"
./build-livepatch.sh -s "$SRC" -j "$(nproc)"