Compare commits

...

7 Commits

Author SHA1 Message Date
Stéphane Lesimple 737cfe4a5f arm64: add SSBS detection 2026-06-06 17:01:46 +02:00
Stéphane Lesimple 0b022ee253 fix: zenbleed (CVE-2023-20593) handle the VM guest case (#488)
Zenbleed (CVE-2023-20593) is mitigated either by up-to-date CPU microcode
or by the host kernel setting FP_BACKUP_FIX (DE_CFG MSR 0xc0011029 bit 9).
Both are applied at the host level. Inside a Xen dom0/domU (or any VM
guest) the script can't read that MSR and can't trust the microcode
version the hypervisor presents, so it wrongly concluded "kernel too old
+ microcode not fixed" and reported VULN even though the host had applied
the microcode fix (passing on bare metal).

In live mode, when the verdict would be VULN and we're running as a guest,
report UNK instead, explaining the mitigation is host-level and not
observable from inside the guest. Bare metal is unchanged (still VULN),
offline analysis is unchanged, and a guest with positively-confirmed
fixed microcode still reports OK.
2026-06-06 16:13:52 +02:00
Stéphane Lesimple 1e33f40f0a mds/mmio/taa: don't claim "disable SMT" inside a VM guest (#343)
Inside a Xen PVH domU (and any guest where the kernel sets
X86_FEATURE_HYPERVISOR), the kernel appends "; SMT Host state unknown"
to the MDS/MMIO sysfs vuln string: the host controls SMT scheduling and
the guest genuinely can't see it. The "SMT is either mitigated or
disabled" check only matched 'SMT (disabled|mitigated)', so this read as
"not mitigated" and --paranoid flipped the verdict to a misleading
VULN "you must disable SMT (Hyper-Threading)".

Make *_smt_mitigated a tri-state: 1 (disabled/mitigated), 0 (vulnerable),
and 2 (host state unknown). In paranoid mode, when the in-guest
mitigation is active but SMT host state is unknown, report UNK with an
explanation that cross-thread protection depends on the hypervisor host's
SMT/core-scheduling config, instead of VULN. PV DomUs (kernel reports
"SMT vulnerable", no HYPERVISOR bit) are unchanged and still flagged.
2026-06-06 16:13:52 +02:00
Stéphane Lesimple 1211c21261 xen: more reliable Xen/guest detection + container awareness (#173)
Better detect Xen guest type + add container detection

CVE-2017-5754: when we see Xen but we're inside a container,
/proc/xen/capabilities isn't exposed and dmesg is the host's,
so dom0 vs PV DomU can't be told apart. Don't report VULN in
that case, but UNKNOWN instead, and ask to rerun the script on the host.
2026-06-06 16:13:52 +02:00
Stéphane Lesimple d8abfbe20a doc: add CVE-2026-46174 (AMD Zen 2 Op Cache Improper Resource Isolation) to the unsupported list 2026-06-06 15:07:18 +02:00
Stéphane Lesimple 45fe976ca9 doc: add unsupported CVE to list (CVE-2021-26314 / CVE-2021-26313 / CVE-2025-52533)
CVE-2021-26314 / CVE-2021-26313 (Floating-Point Value Injection (FPVI) and Speculative Code Store Bypass (SCSB))
CVE-2025-52533 (AMD On-Chip Debug Interface Improper Access Control)
2026-06-06 12:53:22 +02:00
Stéphane Lesimple 44ba3790d9 fix: arm64: collapse per-core CPU info lists to a single line
Store the per-core implementer/part/arch/variant/revision lists
space-separated (no embedded newlines, which also cleans up JSON and
prometheus output) and dedup them for the human-readable display, so
homogeneous systems show e.g. "0x41" instead of repeating it per core.
2026-06-02 19:15:05 +02:00
9 changed files with 223 additions and 45 deletions
+34
View File
@@ -188,6 +188,18 @@ Observable timing discrepancy in some Intel processors allows an authenticated u
**Why out of scope:** Like CVE-2020-24511, this is a microcode-only fix with no Linux kernel sysfs entry, no CPUID bit, no MSR, and no kernel configuration option. Detection would require a per-CPU-stepping microcode version lookup table. The vulnerability has low severity (CVSS 2.8) and practical exploitation is limited. Intel dropped microcode support for Sandy Bridge and Ivy Bridge, leaving those generations permanently vulnerable. **Why out of scope:** Like CVE-2020-24511, this is a microcode-only fix with no Linux kernel sysfs entry, no CPUID bit, no MSR, and no kernel configuration option. Detection would require a per-CPU-stepping microcode version lookup table. The vulnerability has low severity (CVSS 2.8) and practical exploitation is limited. Intel dropped microcode support for Sandy Bridge and Ivy Bridge, leaving those generations permanently vulnerable.
## CVE-2021-26314 / CVE-2021-26313 — Floating-Point Value Injection (FPVI) and Speculative Code Store Bypass (SCSB)
- **Bulletin:** [AMD-SB-1003](https://www.amd.com/en/resources/product-security/bulletin/amd-sb-1003.html) (FPVI and SCSB); [AMD-SB-7050](https://www.amd.com/en/resources/product-security/bulletin/amd-sb-7050.html) (FPVI variant, informational)
- **Intel advisory:** [Floating Point Value Injection](https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/floating-point-value-injection.html)
- **Research paper:** [Rage Against the Machine Clear (FPVI/SCSB) — VUSec, USENIX Security '21](https://www.vusec.net/projects/fpvi-scsb/)
- **Affected CPUs:** All supported AMD CPU products; Intel CPUs (FPVI)
- **CVSS:** 5.5 (Medium) for both
FPVI (CVE-2021-26314) lets an attacker inject arbitrary floating-point values into the transient execution window opened by a floating-point machine clear, so that dependent operations transiently compute on attacker-influenced values that can then be inferred through a microarchitectural covert channel. SCSB (CVE-2021-26313) is the companion vulnerability where overwritten instructions may still be executed speculatively. AMD-SB-7050 documents an FPVI variant (from the "TREVEX" detection-framework paper) that can be triggered without denormal inputs; AMD considers it to fall within the existing scope of CVE-2021-26314 and assigned it no new CVE, classifying it as informational only.
**Why out of scope:** The mitigation responsibility falls on individual software, not on the kernel or microcode. Both AMD and Intel recommend that software vendors analyze their code for vulnerable speculative floating-point sequences and insert an `LFENCE` to serialize execution. No microcode update, no CPUID flag, no MSR, and no kernel configuration option was issued, and there is no `/sys/devices/system/cpu/vulnerabilities/` entry for FPVI or SCSB — the kernel never added one, because the fix is not a kernel-level control. This is the same situation as [SLAM (CVE-2020-12965)](#cve-2020-12965--transient-execution-of-non-canonical-accesses-slam) and "Take A Way": the vendor's guidance is "software inserts LFENCE in its own code," leaving nothing for this tool to check. The AMD-SB-7050 variant adds nothing detectable, as it is informational and reuses the existing (software-only) FPVI guidance.
## CVE-2021-26318 — AMD Prefetch Attacks through Power and Time ## CVE-2021-26318 — AMD Prefetch Attacks through Power and Time
- **Issue:** [#412](https://github.com/speed47/spectre-meltdown-checker/issues/412) - **Issue:** [#412](https://github.com/speed47/spectre-meltdown-checker/issues/412)
@@ -308,6 +320,28 @@ Exploits a synchronization failure in the AMD stack engine via an undocumented M
**Why out of scope:** Not a transient/speculative execution side channel. This is an architectural attack on AMD SEV-SNP confidential computing that requires hypervisor access, which is outside the threat model of this tool. **Why out of scope:** Not a transient/speculative execution side channel. This is an architectural attack on AMD SEV-SNP confidential computing that requires hypervisor access, which is outside the threat model of this tool.
## CVE-2025-52533 — AMD On-Chip Debug Interface Improper Access Control
- **Advisory:** [NVD CVE-2025-52533](https://nvd.nist.gov/vuln/detail/CVE-2025-52533)
- **Affected CPUs:** AMD (various; on-chip debug/test interface)
- **CVSS:** 8.7 (High)
- **CWE:** [CWE-1191 (On-Chip Debug and Test Interface With Improper Access Control)](https://cwe.mitre.org/data/definitions/1191.html)
Improper access control in an on-chip debug interface could allow a privileged attacker to enable a debug interface and potentially compromise data confidentiality or integrity.
**Why out of scope:** Not a transient or speculative execution vulnerability — this is an access-control flaw in a hardware debug/test interface (CWE-1191), with no side-channel or speculative execution component, and it requires a privileged attacker. There is no Linux kernel sysfs entry, no CPUID flag, and no kernel-side mitigation: the fix is delivered as platform/PSP firmware and proven via remote attestation against AMD's Key Distribution Service (KDS), with several SKUs marked "no fix planned." None of this is detectable by this tool, which inspects OS-loadable microcode revisions, CPUID/MSR bits, kernel capabilities, and sysfs.
## CVE-2026-46174 — AMD Zen 2 Op Cache Improper Resource Isolation
- **Bulletin:** [AMD-SB-7052](https://www.amd.com/en/resources/product-security/bulletin/amd-sb-7052.html) (CPU OP Cache Corruption)
- **Kernel fix:** [commit 1e23b30a80b1](https://github.com/torvalds/linux/commit/1e23b30a80b14e5764657401ee2cca030525ae8e) — `x86/CPU/AMD: Prevent improper isolation of shared resources in Zen2's op cache`
- **Affected CPUs:** AMD Zen 2
- **CVSS:** 8.8 (High)
Resources in the Zen 2 micro-op (op) cache can be improperly shared, causing instruction corruption that may be leveraged to execute instructions at a higher privilege level (userspace-to-kernel escalation). The Linux fix sets a bug-fix bit (bit 33) in the AMD `BP_CFG` model-specific register (`0xc001102e`) via `msr_set_bit()` in `init_amd_zen2()`, and only on bare metal (skipped when `X86_FEATURE_HYPERVISOR` is set, as the mitigation is the host's responsibility for guests).
**Why out of scope:** Not a transient or speculative execution vulnerability — this is an op-cache resource-isolation bug that causes *instruction corruption* (an integrity/correctness erratum), with no side-channel or speculative data-leak component, which places it outside the vulnerability class this tool detects. It is also undetectable by this tool's standard framework: the kernel deliberately adds no `/sys/devices/system/cpu/vulnerabilities/` entry, no `X86_BUG_*` flag (so nothing in `/proc/cpuinfo`), no dmesg message, and no kernel command-line parameter. The mitigation is an unconditional inline MSR bit-set with no greppable named symbol, so it leaves no handle for no-runtime (kernel image / `System.map`) detection. The only possible check would be a live read of `BP_CFG` bit 33, which requires root and the `msr` module, works on bare metal only (guests report `N/A`), and would be a bespoke one-off outside the established CVE-detection model — the same situation as the [JCC Erratum](#no-cve--jump-conditional-code-jcc-erratum) below, but for AMD.
## No CVE — Jump Conditional Code (JCC) Erratum ## No CVE — Jump Conditional Code (JCC) Erratum
- **Issue:** [#329](https://github.com/speed47/spectre-meltdown-checker/issues/329) - **Issue:** [#329](https://github.com/speed47/spectre-meltdown-checker/issues/329)
+12 -5
View File
@@ -29,11 +29,18 @@ parse_cpu_details() {
# cpu_variant_list and cpu_revision_list are consumed by ARM64 errata affection checks # cpu_variant_list and cpu_revision_list are consumed by ARM64 errata affection checks
# that need to match a specific revision range. # that need to match a specific revision range.
if grep -q 'CPU implementer' "$g_procfs/cpuinfo"; then if grep -q 'CPU implementer' "$g_procfs/cpuinfo"; then
cpu_impl_list=$(awk '/CPU implementer/ {print $4}' "$g_procfs/cpuinfo") # keep these single-line (space-separated) so consumers and outputs (JSON, prometheus)
cpu_part_list=$(awk '/CPU part/ {print $4}' "$g_procfs/cpuinfo") # don't end up with embedded newlines; per-core order is preserved for the errata checks
cpu_arch_list=$(awk '/CPU architecture/ {print $3}' "$g_procfs/cpuinfo") cpu_impl_list=$(awk '/CPU implementer/ {print $4}' "$g_procfs/cpuinfo" | tr '\n' ' ')
cpu_variant_list=$(awk '/CPU variant/ {print $4}' "$g_procfs/cpuinfo") cpu_impl_list=${cpu_impl_list% }
cpu_revision_list=$(awk '/CPU revision/ {print $4}' "$g_procfs/cpuinfo") cpu_part_list=$(awk '/CPU part/ {print $4}' "$g_procfs/cpuinfo" | tr '\n' ' ')
cpu_part_list=${cpu_part_list% }
cpu_arch_list=$(awk '/CPU architecture/ {print $3}' "$g_procfs/cpuinfo" | tr '\n' ' ')
cpu_arch_list=${cpu_arch_list% }
cpu_variant_list=$(awk '/CPU variant/ {print $4}' "$g_procfs/cpuinfo" | tr '\n' ' ')
cpu_variant_list=${cpu_variant_list% }
cpu_revision_list=$(awk '/CPU revision/ {print $4}' "$g_procfs/cpuinfo" | tr '\n' ' ')
cpu_revision_list=${cpu_revision_list% }
fi fi
# Map first-seen implementer to cpu_vendor; note that heterogeneous systems # Map first-seen implementer to cpu_vendor; note that heterogeneous systems
# (e.g. DynamIQ with ARM+Kryo cores) would all map to one vendor here, but # (e.g. DynamIQ with ARM+Kryo cores) would all map to one vendor here, but
+94 -25
View File
@@ -1,25 +1,41 @@
# vim: set ts=4 sw=4 sts=4 et: # vim: set ts=4 sw=4 sts=4 et:
# Check whether the system is running as a Xen paravirtualized guest
# Returns: 0 if Xen PV, 1 otherwise # Probe Xen presence and guest type using the most reliable sources available.
is_xen() { # Prefer /sys/hypervisor when avalable, fallback to dmesg otherwise.
local ret # Caches results in g_xen (1/0) and g_xen_guest_type (PV|PVH|HVM|'').
if [ ! -d "$g_procfs/xen" ]; then _detect_xen() {
return 1 [ "${g_xen_cached:-0}" = 1 ] && return
g_xen=0
g_xen_guest_type=''
g_xen_cached=1
# Most reliable: /sys/hypervisor/type is 'xen' on any Xen domain (dom0
# included), and /sys/hypervisor/guest_type reports PV, PVH or HVM.
if [ -r /sys/hypervisor/type ] && [ "$(cat /sys/hypervisor/type 2>/dev/null)" = xen ]; then
g_xen=1
if [ -r /sys/hypervisor/guest_type ]; then
g_xen_guest_type=$(cat /sys/hypervisor/guest_type 2>/dev/null)
fi
return
fi fi
# XXX do we have a better way that relying on dmesg? # Fallback for kernels without /sys/hypervisor: /proc/xen plus a dmesg probe.
dmesg_grep 'Booting paravirtualized kernel on Xen$' if [ -d "$g_procfs/xen" ]; then
ret=$? dmesg_grep 'Booting paravirtualized kernel on Xen$'
if [ "$ret" -eq 2 ]; then case $? in
pr_warn "dmesg truncated, Xen detection will be unreliable. Please reboot and relaunch this script" 0) g_xen=1 ;;
return 1 2) pr_warn "dmesg truncated, Xen detection will be unreliable. Please reboot and relaunch this script" ;;
elif [ "$ret" -eq 0 ]; then esac
return 0
else
return 1
fi fi
} }
# Check whether the system is running on Xen (any domain type, dom0 included).
# Returns: 0 if Xen, 1 otherwise
is_xen() {
_detect_xen
[ "$g_xen" = 1 ]
}
# Check whether the system is a Xen Dom0 (privileged domain) # Check whether the system is a Xen Dom0 (privileged domain)
# Returns: 0 if Dom0, 1 otherwise # Returns: 0 if Dom0, 1 otherwise
is_xen_dom0() { is_xen_dom0() {
@@ -34,31 +50,77 @@ is_xen_dom0() {
fi fi
} }
# Check whether the system is a Xen DomU (unprivileged PV guest) # Check whether the system is running as a Xen PV DomU (the only Xen guest type
# Returns: 0 if DomU, 1 otherwise # affected by Meltdown, which needs Xen-level mitigation).
# Returns: 0 if PV DomU, 1 otherwise
is_xen_domU() { is_xen_domU() {
local ret local ret
if ! is_xen; then if ! is_xen; then
return 1 return 1
fi fi
# PVHVM guests also print 'Booting paravirtualized kernel', so we need this check. if is_xen_dom0; then
return 1
fi
# When the reliable guest type is known, only PV domains (which aren't
# dom0, checked above) are the PV DomU case. PVH and HVM guests are not.
if [ -n "$g_xen_guest_type" ]; then
[ "$g_xen_guest_type" = PV ] && return 0
return 1
fi
# Fallback (no /sys/hypervisor/guest_type): PVHVM guests also print the
# 'Booting paravirtualized kernel' line, so exclude them via dmesg.
dmesg_grep 'Xen HVM callback vector for event delivery is enabled$' dmesg_grep 'Xen HVM callback vector for event delivery is enabled$'
ret=$? ret=$?
if [ "$ret" -eq 0 ]; then if [ "$ret" -eq 0 ]; then
return 1 return 1
fi fi
if ! is_xen_dom0; then return 0
return 0
else
return 1
fi
} }
# Check whether the system is running as a guest inside a virtual machine. # Check whether we're running inside an OS-level container (LXC, Docker,
# systemd-nspawn, etc.). Containers share the host kernel, so host/hypervisor
# introspection (e.g. telling a Xen dom0 from a domU) is unreliable from inside
# one: /proc/xen is exposed but empty, dmesg is the host's, etc. (issue #173)
# Returns: 0 if in a container, 1 otherwise
# Sets: g_is_container (1/0), g_container_reason
is_running_in_container() {
local ctype
if [ "${g_is_container_cached:-0}" != 1 ]; then
g_is_container=0
g_container_reason=''
# systemd and most runtimes export 'container=' to PID 1's environment
if [ -r "$g_procfs/1/environ" ]; then
ctype=$(tr '\0' '\n' <"$g_procfs/1/environ" 2>/dev/null | sed -n 's/^container=//p' | head -n1)
if [ -n "$ctype" ]; then
g_is_container=1
g_container_reason="container=$ctype in $g_procfs/1/environ"
fi
fi
# Docker (and some others) drop a marker file at the filesystem root
if [ "$g_is_container" = 0 ] && [ -e /.dockerenv ]; then
g_is_container=1
g_container_reason="/.dockerenv present"
fi
# cgroup membership often reveals the runtime (lxc, docker, kubepods, ...)
if [ "$g_is_container" = 0 ] && [ -r "$g_procfs/1/cgroup" ]; then
if grep -qE '(^|[:/])(lxc|docker|kubepods|libpod|containerd|machine\.slice)([/.]|$)' "$g_procfs/1/cgroup" 2>/dev/null; then
g_is_container=1
g_container_reason="container runtime found in $g_procfs/1/cgroup"
fi
fi
g_is_container_cached=1
fi
[ "$g_is_container" = 1 ]
}
# Check whether the system is running as a guest inside a VM.
# Uses the 'hypervisor' CPUID feature flag exposed in /proc/cpuinfo by KVM, # Uses the 'hypervisor' CPUID feature flag exposed in /proc/cpuinfo by KVM,
# VMware, Hyper-V, VirtualBox, and most other type-1 and type-2 hypervisors. # VMware, Hyper-V, VirtualBox, and most other type-1 and type-2 hypervisors.
# Xen PV/PVH DomUs don't set that flag, so they're detected separately.
# Returns: 0 if running as a VM guest, 1 otherwise # Returns: 0 if running as a VM guest, 1 otherwise
# Sets: g_is_guest_vm (1=guest, 0=not a guest), g_is_guest_vm_reason # Sets: g_is_guest_vm (1=guest, 0=not a guest), g_is_guest_vm_reason
is_running_as_guest() { is_running_as_guest() {
@@ -69,6 +131,13 @@ is_running_as_guest() {
g_is_guest_vm=1 g_is_guest_vm=1
g_is_guest_vm_reason="'hypervisor' flag in $g_procfs/cpuinfo" g_is_guest_vm_reason="'hypervisor' flag in $g_procfs/cpuinfo"
fi fi
# Xen PV/PVH DomUs don't expose the 'hypervisor' CPUID flag. Don't
# classify a container on a Xen host as a guest here: we can't tell
# dom0 from domU from inside a container (handled separately).
if [ "$g_is_guest_vm" = 0 ] && is_xen && ! is_xen_dom0 && ! is_running_in_container; then
g_is_guest_vm=1
g_is_guest_vm_reason="Xen ${g_xen_guest_type:-PV} DomU"
fi
g_is_guest_vm_cached=1 g_is_guest_vm_cached=1
fi fi
[ "$g_is_guest_vm" = 1 ] [ "$g_is_guest_vm" = 1 ]
+25 -3
View File
@@ -384,6 +384,12 @@ check_kernel_info() {
fi fi
} }
# Collapse a whitespace-separated list to its unique values, preserving first-seen order.
# Used to prettify the per-core ARM lists for display (e.g. "0x41 0x41 0x41 0x41" -> "0x41").
_uniq_list() {
echo "$1" | awk '{ for (i = 1; i <= NF; i++) if (!seen[$i]++) printf "%s%s", (n++ ? " " : ""), $i }'
}
# Display hardware-level CPU mitigation support (microcode features, ARCH_CAPABILITIES, etc.) # Display hardware-level CPU mitigation support (microcode features, ARCH_CAPABILITIES, etc.)
check_cpu() { check_cpu() {
local capabilities ret spec_ctrl_msr codename ucode_str local capabilities ret spec_ctrl_msr codename ucode_str
@@ -393,13 +399,13 @@ check_cpu() {
pr_info " * Vendor: $cpu_vendor" pr_info " * Vendor: $cpu_vendor"
pr_info " * Model name: $cpu_friendly_name" pr_info " * Model name: $cpu_friendly_name"
if [ -n "${cpu_impl_list:-}" ]; then if [ -n "${cpu_impl_list:-}" ]; then
pr_info " * Implementer(s): $cpu_impl_list" pr_info " * Implementer(s): $(_uniq_list "$cpu_impl_list")"
fi fi
if [ -n "${cpu_part_list:-}" ]; then if [ -n "${cpu_part_list:-}" ]; then
pr_info " * Part(s): $cpu_part_list" pr_info " * Part(s): $(_uniq_list "$cpu_part_list")"
fi fi
if [ -n "${cpu_arch_list:-}" ]; then if [ -n "${cpu_arch_list:-}" ]; then
pr_info " * Architecture(s): $cpu_arch_list" pr_info " * Architecture(s): $(_uniq_list "$cpu_arch_list")"
fi fi
if has_runtime; then if has_runtime; then
pr_info_nol " * Running as VM guest: " pr_info_nol " * Running as VM guest: "
@@ -409,6 +415,22 @@ check_cpu() {
pstatus green NO pstatus green NO
fi fi
fi fi
# ARM exposes no userspace-readable CPUID/MSR to query SSBD support directly.
# The ARMv8.5 SSBS ("Speculative Store Bypass Safe") hardware bit, when present,
# surfaces as the 'ssbs' hwcap in /proc/cpuinfo. We use it *only* as a positive
# confirmation of SSB mitigation capability (Variant 4 / CVE-2018-3639): its
# absence proves nothing, because the kernel deliberately hides the hwcap on some
# cores (e.g. the erratum-3194386 SSBS self-sync workaround), so we must never
# infer immunity from a missing 'ssbs'.
if has_runtime; then
pr_info_nol " * CPU indicates SSBS (Speculative Store Bypass Safe) capability: "
if grep '^Features' "$g_procfs/cpuinfo" | grep -qw ssbs; then
cap_ssbd='ARM SSBS (cpuinfo)'
pstatus green YES "$cap_ssbd"
else
pstatus blue UNKNOWN "not exposed (the kernel may hide it; cannot conclude)"
fi
fi
return return
fi fi
+9
View File
@@ -174,6 +174,12 @@ check_mds_linux() {
if echo "$ret_sys_interface_check_fullmsg" | grep -Eq 'SMT (disabled|mitigated)'; then if echo "$ret_sys_interface_check_fullmsg" | grep -Eq 'SMT (disabled|mitigated)'; then
mds_smt_mitigated=1 mds_smt_mitigated=1
pstatus green YES pstatus green YES
elif echo "$ret_sys_interface_check_fullmsg" | grep -q 'SMT Host state unknown'; then
# The kernel appends "SMT Host state unknown" when running under
# a hypervisor (X86_FEATURE_HYPERVISOR): the host controls SMT
# scheduling, so it can't be determined from inside the guest (#343).
mds_smt_mitigated=2
pstatus yellow UNKNOWN "running in a VM guest, the hypervisor host controls SMT"
else else
mds_smt_mitigated=0 mds_smt_mitigated=0
pstatus yellow NO pstatus yellow NO
@@ -200,6 +206,9 @@ check_mds_linux() {
if [ "$opt_paranoid" != 1 ] || [ "$mds_smt_mitigated" = 1 ]; then if [ "$opt_paranoid" != 1 ] || [ "$mds_smt_mitigated" = 1 ]; then
mystatus=OK mystatus=OK
mymsg="Your microcode and kernel are both up to date for this mitigation, and mitigation is enabled" mymsg="Your microcode and kernel are both up to date for this mitigation, and mitigation is enabled"
elif [ "$mds_smt_mitigated" = 2 ]; then
mystatus=UNK
mymsg="Your microcode and kernel are both up to date for this mitigation and it's enabled, but SMT (Hyper-Threading) cross-thread protection can't be verified from inside a VM guest: it depends on the hypervisor host's SMT/core-scheduling configuration"
else else
mystatus=VULN mystatus=VULN
mymsg="Your microcode and kernel are both up to date for this mitigation, but you must disable SMT (Hyper-Threading) for a complete mitigation" mymsg="Your microcode and kernel are both up to date for this mitigation, but you must disable SMT (Hyper-Threading) for a complete mitigation"
+9
View File
@@ -216,6 +216,12 @@ check_mmio_linux() {
if echo "$ret_sys_interface_check_fullmsg" | grep -Eq 'SMT (disabled|mitigated)'; then if echo "$ret_sys_interface_check_fullmsg" | grep -Eq 'SMT (disabled|mitigated)'; then
mmio_smt_mitigated=1 mmio_smt_mitigated=1
pstatus green YES pstatus green YES
elif echo "$ret_sys_interface_check_fullmsg" | grep -q 'SMT Host state unknown'; then
# The kernel appends "SMT Host state unknown" when running under
# a hypervisor (X86_FEATURE_HYPERVISOR): the host controls SMT
# scheduling, so it can't be determined from inside the guest (#343).
mmio_smt_mitigated=2
pstatus yellow UNKNOWN "running in a VM guest, the hypervisor host controls SMT"
else else
mmio_smt_mitigated=0 mmio_smt_mitigated=0
pstatus yellow NO pstatus yellow NO
@@ -253,6 +259,9 @@ check_mmio_linux() {
if [ "$opt_paranoid" != 1 ] || [ "$mmio_smt_mitigated" = 1 ]; then if [ "$opt_paranoid" != 1 ] || [ "$mmio_smt_mitigated" = 1 ]; then
mystatus=OK mystatus=OK
mymsg="Your microcode and kernel are both up to date for this mitigation, and mitigation is enabled" mymsg="Your microcode and kernel are both up to date for this mitigation, and mitigation is enabled"
elif [ "$mmio_smt_mitigated" = 2 ]; then
mystatus=UNK
mymsg="Your microcode and kernel are both up to date for this mitigation and it's enabled, but SMT (Hyper-Threading) cross-thread protection can't be verified from inside a VM guest: it depends on the hypervisor host's SMT/core-scheduling configuration"
else else
mystatus=VULN mystatus=VULN
mymsg="Your microcode and kernel are both up to date for this mitigation, but you must disable SMT (Hyper-Threading) for a complete mitigation" mymsg="Your microcode and kernel are both up to date for this mitigation, but you must disable SMT (Hyper-Threading) for a complete mitigation"
+18 -5
View File
@@ -45,7 +45,7 @@ check_CVE_2017_5754() {
} }
check_CVE_2017_5754_linux() { check_CVE_2017_5754_linux() {
local status sys_interface_available msg kpti_support kpti_can_tell kpti_enabled dmesg_grep pti_xen_pv_domU xen_pv_domo xen_pv_domu explain_text local status sys_interface_available msg kpti_support kpti_can_tell kpti_enabled dmesg_grep pti_xen_pv_domU xen_pv_domo xen_pv_domu xen_unknown_container explain_text
status=UNK status=UNK
sys_interface_available=0 sys_interface_available=0
msg='' msg=''
@@ -167,14 +167,24 @@ check_CVE_2017_5754_linux() {
# Test if the current host is a Xen PV Dom0 / DomU # Test if the current host is a Xen PV Dom0 / DomU
xen_pv_domo=0 xen_pv_domo=0
xen_pv_domu=0 xen_pv_domu=0
is_xen_dom0 && xen_pv_domo=1 xen_unknown_container=0
is_xen_domU && xen_pv_domu=1 if is_xen && ! is_xen_dom0 && is_running_in_container; then
# We can see Xen, but we're inside a container so /proc/xen/capabilities
# isn't exposed and dmesg is the host's: we can't tell a safe Dom0 from
# a vulnerable PV DomU from in here (issue #173).
xen_unknown_container=1
else
is_xen_dom0 && xen_pv_domo=1
is_xen_domU && xen_pv_domu=1
fi
if [ "$g_mode" = live ]; then if [ "$g_mode" = live ]; then
# checking whether we're running under Xen PV 64 bits. If yes, we are affected by affected_variant3 # checking whether we're running under Xen PV 64 bits. If yes, we are affected by affected_variant3
# (unless we are a Dom0) # (unless we are a Dom0)
pr_info_nol "* Running as a Xen PV DomU: " pr_info_nol "* Running as a Xen PV DomU: "
if [ "$xen_pv_domu" = 1 ]; then if [ "$xen_unknown_container" = 1 ]; then
pstatus yellow UNKNOWN "running in a container, can't query Xen from here"
elif [ "$xen_pv_domu" = 1 ]; then
pstatus yellow YES pstatus yellow YES
else else
pstatus blue NO pstatus blue NO
@@ -187,7 +197,10 @@ check_CVE_2017_5754_linux() {
elif [ -z "$msg" ]; then elif [ -z "$msg" ]; then
# if msg is empty, sysfs check didn't fill it, rely on our own test # if msg is empty, sysfs check didn't fill it, rely on our own test
if [ "$g_mode" = live ]; then if [ "$g_mode" = live ]; then
if [ "$kpti_enabled" = 1 ]; then if [ "$xen_unknown_container" = 1 ]; then
pvulnstatus "$cve" UNK "running inside a container on a Xen host, can't determine if the underlying domain is a vulnerable PV DomU"
explain "This system looks like a container ($g_container_reason) running on a Xen host. Whether the underlying domain is a safe Dom0 or a vulnerable PV DomU can't be reliably determined from inside a container (/proc/xen is exposed but empty, and dmesg belongs to the host). Please re-run this script directly on the host, outside the container, to get an accurate result."
elif [ "$kpti_enabled" = 1 ]; then
pvulnstatus "$cve" OK "PTI mitigates the vulnerability" pvulnstatus "$cve" OK "PTI mitigates the vulnerability"
elif [ "$xen_pv_domo" = 1 ]; then elif [ "$xen_pv_domo" = 1 ]; then
pvulnstatus "$cve" OK "Xen Dom0s are safe and do not require PTI" pvulnstatus "$cve" OK "Xen Dom0s are safe and do not require PTI"
+5
View File
@@ -86,6 +86,11 @@ check_CVE_2019_11135_linux() {
pvulnstatus "$cve" VULN "TSX must be disabled for full mitigation" pvulnstatus "$cve" VULN "TSX must be disabled for full mitigation"
elif echo "$ret_sys_interface_check_fullmsg" | grep -qF 'SMT vulnerable'; then elif echo "$ret_sys_interface_check_fullmsg" | grep -qF 'SMT vulnerable'; then
pvulnstatus "$cve" VULN "SMT (HyperThreading) must be disabled for full mitigation" pvulnstatus "$cve" VULN "SMT (HyperThreading) must be disabled for full mitigation"
elif echo "$ret_sys_interface_check_fullmsg" | grep -qF 'SMT Host state unknown'; then
# The kernel appends "SMT Host state unknown" when running under a
# hypervisor (X86_FEATURE_HYPERVISOR): the host controls SMT
# scheduling, so it can't be determined from inside the guest (#343).
pvulnstatus "$cve" UNK "TAA is mitigated and TSX is disabled, but SMT (Hyper-Threading) cross-thread protection can't be verified from inside a VM guest: it depends on the hypervisor host's SMT/core-scheduling configuration"
else else
pvulnstatus "$cve" "$status" "$msg" pvulnstatus "$cve" "$status" "$msg"
fi fi
+17 -7
View File
@@ -103,13 +103,23 @@ check_CVE_2023_20593_linux() {
fi fi
fi fi
if [ "$zenbleed_print_vuln" = 1 ]; then if [ "$zenbleed_print_vuln" = 1 ]; then
pvulnstatus "$cve" VULN "Your kernel is too old to mitigate Zenbleed and your CPU microcode doesn't mitigate it either" if [ "$g_mode" = live ] && is_running_as_guest; then
explain "Your CPU vendor may have a new microcode for your CPU model that mitigates this issue (refer to the hardware section above).\n " \ # Both Zenbleed mitigations are applied at the host level: an
"Otherwise, the Linux kernel is able to mitigate this issue regardless of the microcode version you have, but in this case\n " \ # up-to-date microcode, or the host kernel setting FP_BACKUP_FIX
"your kernel is too old to support this, your Linux distribution vendor might have a more recent version you should upgrade to.\n " \ # in DE_CFG. From inside a guest we can't read that MSR and can't
"Note that either having an up to date microcode OR an up to date kernel is enough to mitigate this issue.\n " \ # trust the microcode version the hypervisor presents, so we can't
"To manually mitigate the issue right now, you may use the following command: \`wrmsr -a 0xc0011029 \$((\$(rdmsr -c 0xc0011029) | (1<<9)))\`,\n " \ # confirm or deny the mitigation -- don't cry VULN (#488).
"however note that this manual mitigation will only be active until the next reboot." pvulnstatus "$cve" UNK "Zenbleed mitigation can't be verified from inside a VM guest ($g_is_guest_vm_reason): it may be applied by the hypervisor host, but that isn't observable from here"
explain "Zenbleed is mitigated either by an up-to-date CPU microcode or by the host kernel setting the FP_BACKUP_FIX bit (DE_CFG MSR 0xc0011029 bit 9). Both are host-level: a guest can neither read that MSR nor trust the microcode version the hypervisor presents (see the VM note in the hardware section above). Re-run this script on the hypervisor host to get an accurate result."
else
pvulnstatus "$cve" VULN "Your kernel is too old to mitigate Zenbleed and your CPU microcode doesn't mitigate it either"
explain "Your CPU vendor may have a new microcode for your CPU model that mitigates this issue (refer to the hardware section above).\n " \
"Otherwise, the Linux kernel is able to mitigate this issue regardless of the microcode version you have, but in this case\n " \
"your kernel is too old to support this, your Linux distribution vendor might have a more recent version you should upgrade to.\n " \
"Note that either having an up to date microcode OR an up to date kernel is enough to mitigate this issue.\n " \
"To manually mitigate the issue right now, you may use the following command: \`wrmsr -a 0xc0011029 \$((\$(rdmsr -c 0xc0011029) | (1<<9)))\`,\n " \
"however note that this manual mitigation will only be active until the next reboot."
fi
fi fi
unset zenbleed_print_vuln unset zenbleed_print_vuln
else else