VMMCALL intercept (AMD hypercall trap)¶
AMD-V'yi guest
VMMCALLinstruction'ını intercept edecek şekilde yapılandırmak (INTERCEPT_VMMCALL) ki her guest hypercall'ı exit code VMEXIT_VMMCALL ile host'a trap olsun — AMD hypercall ABI primitive'i ve (yanlış) kullanıldığında guest-reachable bir VMM entry point / backdoor channel'ı.
Mechanism¶
Note
VMMCALL, AMD'nin adanmış guest→host çağrı instruction'ıdır. Tek başına yalnızca
host onu intercept ederse bir #VMEXIT tetikler: host, VMCB control area'sının
intercept vector'ında INTERCEPT_VMMCALL bit'ini set eder, ardından bir guest
VMMCALL'ı exit_code == VMEXIT_VMMCALL ile exit eder ve host'un guest register'larını
hypercall argümanları olarak okuyup isteği servis etmesine izin verir. VMMCALL
intercept edilmezse, onu çalıştırmak guest'te #UD doğurur (AMD APM'e göre) — implicit
bir hypercall yoktur. Invariant: host'un VMMCALL handler'ı, guest-controlled register
argümanlarının attacker-reachable bir parser'ıdır, yani onları tıpkı herhangi bir
syscall handler'ı gibi doğrulamalıdır. Bug class: güçlü bir VMMCALL expose eden
(örn. host memory'sini okuyan/yazan veya unchecked bir index'e göre dispatch eden bir
debug/"backdoor" hypercall'ı) ya da nested SVM'de exit'i yanlış route eden bir
hypervisor, bir guest→host attack surface'ı yaratır; yakın zamandaki KVM nested-SVM
çalışması, L1'in intercept etmediği bir L2 VMMCALL'ını L0'ın nasıl route ettiğini
sertleştirdi.
Intel'in VMCALL exit'inin AMD karşılığı; VMCB manipulation aracılığıyla yapılandırılır. VMCALL inline hook'taki inline-hook abuse'ü ile karşılaştır.
Walkthrough¶
Kavramsal host + guest tarafları (AMD SVM manual'ı ve KVM hypercall analizinden):
Host intercept'i etkinleştirir (VMCB):
vmcb->control.intercept |= (1ULL << INTERCEPT_VMMCALL);
vmcb->control.clean &= ~CLEAN_INTERCEPTS; /* see VMCB clean bits */
Guest bir hypercall yapar:
mov rax, HCALL_NR ; hypercall number (ABI-defined)
mov rbx, arg0
vmmcall ; -> #VMEXIT, exit_code = VMEXIT_VMMCALL
Host VMEXIT handler'ı:
case VMEXIT_VMMCALL:
nr = vmcb->save.rax; /* attacker-controlled */
if (nr >= HCALL_MAX) { inject_ud(); break; } /* must validate */
dispatch[nr](guest_regs); /* validate every arg inside */
vmcb->save.rip += 3; /* skip the 3-byte VMMCALL */
Beklenen: geçerli bir hypercall servis edilir ve guest VMMCALL'dan sonra devam eder; out-of-range/unintercepted bir durum, sessiz host eylemi yerine #UD doğurur.
Warning
Kavramsal. Risk tasarım seviyesindedir: host memory erişimi sağlayan veya unchecked index'lere göre dispatch eden guest-reachable VMMCALL'lar gönderme.
Detection¶
- Host: VMEXIT_VMMCALL'ı hypercall numarasıyla logla; tanımsız/kötüye kullanan numaralar ya da host range'lerine işaret eden argümanlar için uyar.
- Nested SVM: L1'in intercept etmediği L2 VMMCALL exit'lerinin yanlış ele alındığını tespit et.
Mitigation¶
- Hypercall numarasını ve her argümanı doğrula; bilinmeyen çağrılar için varsayılan olarak #UD inject et (architectural no-intercept davranışıyla eşleşerek).
- Production build'lerinde debug/backdoor hypercall'ları expose etme.
- VMMCALL clean bit'ini sync tut (bkz. VMCB clean bits); nested SVM'de L2 VMMCALL'ları düzeltilmiş KVM semantiğine göre route et.