Skip to content

VMMCALL intercept (AMD hypercall trap)

AMD-V'yi guest VMMCALL instruction'ı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 VMMCALLexit_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.

References