gVisor - CPUID
CPUID (CPU Identification) is a specific processor instruction for the x86 architecture. It allows software to query the processor to find out exactly what kind of CPU is being used and what features it supports.
In the context of gVisor, CPUID is a critical component for both security isolation and application compatibility.
How CPUID works
When a program executes the CPUID instruction:
- The program puts a "function code" into the
EAXregister. - The CPU processes the request.
- The CPU fills the registers (
EAX,EBX,ECX,EDX) with information like:- Vendor ID (e.g., "GenuineIntel" or "AuthenticAMD").
- Model and Family (e.g., Core i7, 12th Gen).
- Feature Flags (e.g., "Does this CPU support AES encryption? Does it support AVX-512?").
CPUID in gVisor: "The Hardware Lie"
In a standard container (runc), when an app runs CPUID, it talks directly to the host hardware. It sees exactly what the host CPU is.
In gVisor, the Sentry intercepts the CPUID instruction. Instead of letting the application see the raw host hardware, gVisor returns a filtered or "trapped" version of the CPU info.
Why gVisor filters CPUID
- Security (Anti-Fingerprinting): By hiding the exact model and stepping of the host CPU, gVisor makes it harder for an attacker to know which specific hardware vulnerabilities (like Spectre or Meltdown) the host might be susceptible to.
- Compatibility/Migration: If you move a running container from an Intel machine to an AMD machine (Checkpoint/Restore), the application might crash if it thinks it still has Intel-specific features. gVisor provides a "common denominator" CPU view.
- Feature Masking: gVisor might support a feature (like AVX), but if the Sentry hasn't fully implemented the safe save/restore of those registers yet, it will tell the application: "I don't support AVX," even if the physical hardware does.
How to see CPUID info inside gVisor
You can see what gVisor is "telling" your application by running standard Linux tools inside the sandbox:
# Run inside a gVisor container
lscpu
# OR
cat /proc/cpuinfo
Note: You will often notice that the "Model name" or "Flags" list is shorter than what you see on your actual host machine.
Configuring CPUID in runsc
gVisor allows you to customize the CPU features exposed to the container. This is done via the --cpuid-config flag or by using specific built-in profiles.
Example: Changing the CPU Vendor
You can actually make gVisor lie and say the CPU was made by a fictional company.
Note: This usually requires a custom configuration file passed to runsc.
Common Flag: Software vs. Hardware
- KVM Platform: Uses hardware acceleration to handle CPUID. It is faster but still allows the Sentry to mask out specific bits.
- Systrap/Ptrace Platform: The Sentry must manually catch the instruction and emulate the response, which is slower.
Why should you care?
Most users don't need to touch CPUID settings, but it becomes important in two cases:
- Performance: If your app (like a video transcoder) uses AVX-512 or AES-NI and gVisor has masked those flags out, your app will fall back to a much slower software-based method.
- Crashes: Some highly optimized math libraries (like OpenBLAS) check CPUID at startup. If gVisor returns a combination of flags that the library doesn't expect, the library might crash with an "Illegal Instruction" error.
Summary
CPUID is the CPU's "ID card." gVisor acts like a fake ID generator—it intercepts requests for that ID card and hands back a modified version that is safer and more consistent for the application to use.