Skip to content

feat(fire_vmm): mask VMX and SVM from guests via /cpu-config - #91

Open
markovejnovic wants to merge 1 commit into
mainfrom
feat/mask-guest-nested-virt
Open

markovejnovic wants to merge 1 commit into
mainfrom
feat/mask-guest-nested-virt

Conversation

@markovejnovic

Copy link
Copy Markdown
Contributor

Part of #90. Firecracker 1.16.0 passes VMX and SVM through unmasked, so on a host with the default nested=1 every guest can run a nested hypervisor, which is the precondition for CVE-2026-53359. Every x86_64 boot now PUTs a /cpu-config clearing CPUID.01H:ECX[5] and CPUID.80000001H:ECX[2]; aarch64 sends nothing.

  • GuestCpu.config/1 builds the template, BootSpec.resolve/3 picks it by the VM's arch, and configure_devices PUTs it right after machine-config.
  • KVM treats CR4.VMXE as reserved and rejects EFER.SVME when the guest's CPUID lacks the bit (mainline arch/x86/kvm/regs.h, arch/x86/kvm/msrs.c), so the mask holds whatever the host's nested param says.
  • guest_cpu_properties_test.exs applies the modifiers the way Firecracker documents its bitmap and checks VMX/SVM clear with every other host bit kept. Confirmed it fails for an LSB-first bitmap, a wrong bit, and a wrong subleaf.
  • test/e2e/guest_cpu_test.exs asserts a booted guest's /proc/cpuinfo flags carry no vmx/svm. It only has teeth if the runner's KVM has nested on; I haven't confirmed that for GitHub's runners.

Verified on macOS: format --check-formatted, credo --strict, compile --warnings-as-errors (bar the stamp-generated SuidHelper.Expected), and mix test test/hyper/node/fire_vmm (69 passed). Dialyzer and the e2e suite need the Linux build, so those are CI's.

Written by Claude Code; review it as AI-authored.

Firecracker passes VMX and SVM through from KVM_GET_SUPPORTED_CPUID
unmasked, so on a host with the default kvm_intel/kvm_amd nested=1 every
guest could run its own hypervisor on top of the host's nested-paging
code (CVE-2026-53359).

Every x86_64 boot now PUTs a /cpu-config that clears CPUID.01H:ECX[5] and
CPUID.80000001H:ECX[2]. KVM treats CR4.VMXE as reserved and rejects
EFER.SVME when the guest's CPUID lacks the bit, so the mask holds
regardless of the host's nested parameter. aarch64 sends nothing.
@codecov

codecov Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 81.81818% with 2 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
lib/hyper/node/fire_vmm/guest_cpu.ex 75.00% 1 Missing ⚠️
lib/hyper/node/fire_vmm/state.ex 85.71% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@github-actions

Copy link
Copy Markdown

Test Results

  3 files   -   1  204 suites   - 23   2m 18s ⏱️ - 1m 5s
486 tests  - 189  486 ✅  - 188    0 💤 ±0  0 ❌  - 1 
964 runs   - 187  486 ✅  - 188  478 💤 +2  0 ❌  - 1 

Results for commit 0c25f09. ± Comparison against base commit 3ac24e1.

This pull request removes 191 and adds 2 tests. Note that renamed tests count towards both.
hyper-suidhelper::config_network ‑ absent_network_table_means_disabled
hyper-suidhelper::config_network ‑ partial_network_table_without_uplink_disables_not_bricks
hyper-suidhelper::config_network ‑ present_table_with_only_uplink_defaults_clone_pool
hyper-suidhelper::config_seam ‑ override_path_is_consulted_through_the_real_lexical_gate
hyper-suidhelper::config_uid_gid_range ‑ absent_range_yields_default
hyper-suidhelper::config_uid_gid_range ‑ min_exceeds_max_always_rejected
hyper-suidhelper::config_uid_gid_range ‑ valid_range_accepted
hyper-suidhelper::config_uid_gid_range ‑ valid_range_round_trips_via_toml
hyper-suidhelper::config_uid_gid_range ‑ zero_min_always_rejected
hyper-suidhelper::e2e_argv ‑ blockdev_getsz_argv_and_parse_as_root
…
Elixir.Hyper.E2e.GuestCpuTest ‑ test a booted guest's CPU flags carry neither vmx nor svm
Elixir.Hyper.Node.FireVMM.GuestCpuPropertiesTest ‑ property VMX and SVM are cleared and every other host bit survives

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant