Documentation
¶
Overview ¶
Package nestedvirt detects KVM guests that have used nested virtualization.
The package is intentionally centered on host-local evidence. It reads KVM nested_run counters from debugfs through github.com/vexxhost/debugfs, then correlates non-zero counters with process metadata from /proc through github.com/prometheus/procfs. When the process looks like QEMU, the scanner extracts common libvirt/QEMU identity fields such as the guest name and UUID, and discovers likely QMP monitor sockets by joining the process fd table with /proc/net/unix. It also connects to libvirt through qemu:///system by default using the pure-Go libvirt RPC protocol and enriches findings with domain identity and Nova metadata when available.
A scan reports observed nested virtualization use. It does not prove that a guest permanently requires nested virtualization, but a non-zero counter is a strong signal that disabling nested virtualization may break that workload.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Finding ¶
type Finding struct {
Process Process `json:"process"`
VM *VMIdentity `json:"vm,omitempty"`
MonitorSockets []MonitorSocket `json:"monitor_sockets,omitempty"`
LibvirtDomain *LibvirtDomain `json:"libvirt_domain,omitempty"`
NestedRunCount uint64 `json:"nested_run_count"`
NestedRunCounters []NestedRunCounter `json:"nested_run_counters"`
Requirement Requirement `json:"requirement"`
Errors []FindingError `json:"errors,omitempty"`
}
Finding describes one process whose KVM VM has a non-zero nested_run counter.
type FindingError ¶
type FindingError struct {
PID int `json:"pid"`
Operation string `json:"operation"`
Error string `json:"error"`
}
FindingError records process-inspection errors that did not prevent the scan from reporting the nested_run evidence.
type LibvirtDomain ¶
type LibvirtDomain struct {
Name string `json:"name,omitempty"`
UUID string `json:"uuid,omitempty"`
NovaMetadata *NovaMetadata `json:"nova_metadata,omitempty"`
}
LibvirtDomain contains identity and metadata read from libvirt for a QEMU domain.
type MonitorSocket ¶
type MonitorSocket struct {
FD int `json:"fd"`
Inode uint64 `json:"inode"`
Path string `json:"path"`
Source string `json:"source"`
}
MonitorSocket describes a Unix socket that looks like a QEMU monitor or QMP endpoint for the process.
type NestedRunCounter ¶
NestedRunCounter identifies one debugfs nested_run counter that contributed to a finding.
type NovaFlavor ¶
type NovaFlavor struct {
Name string `json:"name,omitempty"`
MemoryMiB string `json:"memory_mib,omitempty"`
DiskGiB string `json:"disk_gib,omitempty"`
SwapMiB string `json:"swap_mib,omitempty"`
EphemeralGiB string `json:"ephemeral_gib,omitempty"`
VCPUs string `json:"vcpus,omitempty"`
}
NovaFlavor describes flavor fields Nova stores in libvirt metadata.
type NovaIdentity ¶
type NovaIdentity struct {
UUID string `json:"uuid,omitempty"`
Name string `json:"name,omitempty"`
}
NovaIdentity contains a Nova user or project display value and UUID.
type NovaMetadata ¶
type NovaMetadata struct {
Namespace string `json:"namespace,omitempty"`
Name string `json:"name,omitempty"`
Hostname string `json:"hostname,omitempty"`
CreationTime string `json:"creation_time,omitempty"`
PackageVersion string `json:"package_version,omitempty"`
Flavor *NovaFlavor `json:"flavor,omitempty"`
Owner *NovaOwner `json:"owner,omitempty"`
Root *NovaRoot `json:"root,omitempty"`
}
NovaMetadata contains common OpenStack Nova metadata from a libvirt domain.
type NovaOwner ¶
type NovaOwner struct {
User NovaIdentity `json:"user,omitempty"`
Project NovaIdentity `json:"project,omitempty"`
}
NovaOwner describes the user and project that own the server.
type Option ¶
type Option func(*scannerConfig) error
Option configures a Scanner.
func WithDebugFS ¶
WithDebugFS configures the debugfs reader directly.
func WithDebugFSMount ¶
WithDebugFSMount configures the debugfs mount point.
func WithLibvirtURI ¶
WithLibvirtURI configures the libvirt connection URI.
func WithProcFS ¶
WithProcFS configures the procfs reader directly.
func WithProcFSMount ¶
WithProcFSMount configures the procfs mount point.
type Process ¶
type Process struct {
PID int `json:"pid"`
Command string `json:"command,omitempty"`
Executable string `json:"executable,omitempty"`
Kind ProcessKind `json:"kind"`
}
Process describes the userspace process attached to a KVM VM.
type ProcessKind ¶
type ProcessKind string
ProcessKind classifies the userspace process attached to a KVM VM.
const ( // ProcessKindUnknown means the scanner could not read enough process // metadata to classify the process. ProcessKindUnknown ProcessKind = "unknown" // ProcessKindQEMU means the process looks like QEMU or qemu-kvm. ProcessKindQEMU ProcessKind = "qemu" // ProcessKindOther means the process was readable but did not look like // QEMU. ProcessKindOther ProcessKind = "other" )
type Report ¶
type Report struct {
ScannedAt time.Time `json:"scanned_at"`
Summary Summary `json:"summary"`
Findings []Finding `json:"findings"`
}
Report is the result of a host scan.
func (Report) NestedVirtObserved ¶
NestedVirtObserved reports whether any process has a non-zero nested_run counter.
type Requirement ¶
type Requirement string
Requirement describes whether a workload should be treated as requiring nested virtualization.
const ( // RequirementUnknown is used because a nested_run counter only proves prior // use, not a durable contractual requirement. RequirementUnknown Requirement = "unknown" )
type Scanner ¶
type Scanner struct {
// contains filtered or unexported fields
}
Scanner correlates KVM debugfs counters with process metadata.
func NewScanner ¶
NewScanner creates a Scanner. By default it reads /sys/kernel/debug and /proc.
type Summary ¶
type Summary struct {
NestedRunCounters int `json:"nested_run_counters"`
ObservedProcesses int `json:"observed_processes"`
QEMUProcesses int `json:"qemu_processes"`
UnknownProcesses int `json:"unknown_processes"`
MonitorSockets int `json:"monitor_sockets"`
LibvirtDomains int `json:"libvirt_domains"`
LibvirtNovaMetadata int `json:"libvirt_nova_metadata"`
NestedVirtObserved bool `json:"nested_virt_observed"`
}
Summary contains aggregate scan counts.
type VMIdentity ¶
type VMIdentity struct {
Name string `json:"name,omitempty"`
UUID string `json:"uuid,omitempty"`
Sources []string `json:"sources,omitempty"`
}
VMIdentity contains VM identity discovered from a QEMU command line.