Compare commits

..

1 Commits

Author SHA1 Message Date
Stéphane Lesimple 3e2b6cc734 Merge pull request #566 from speed47/test
Prepare release v26.33.0420xxx
2026-04-20 11:02:38 +00:00
24 changed files with 164 additions and 1229 deletions
+1 -1
View File
@@ -186,7 +186,7 @@ if [ $ret = $READ_CPUID_RET_OK ]; then
cap_ssbd='Intel SSBD' cap_ssbd='Intel SSBD'
elif [ $ret = $READ_CPUID_RET_ERR ] && [ "$g_mode" = live ]; then elif [ $ret = $READ_CPUID_RET_ERR ] && [ "$g_mode" = live ]; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
if cpuinfo_has_flag ssbd; then if grep ^flags "$g_procfs/cpuinfo" | grep -qw ssbd; then
cap_ssbd='Intel SSBD (cpuinfo)' cap_ssbd='Intel SSBD (cpuinfo)'
ret=$READ_CPUID_RET_OK ret=$READ_CPUID_RET_OK
fi fi
+11 -19
View File
@@ -40,14 +40,6 @@ CVE | Name | Aliases
[CVE-2024-45332](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-45332) | Branch Privilege Injection | BPI [CVE-2024-45332](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-45332) | Branch Privilege Injection | BPI
[CVE-2025-54505](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2025-54505) | AMD Zen1 Floating-Point Divider Stale Data Leak | FPDSS [CVE-2025-54505](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2025-54505) | AMD Zen1 Floating-Point Divider Stale Data Leak | FPDSS
The following entries are ARM64 silicon errata that the kernel actively works around. They have no assigned CVE; they are tracked only by ARM's erratum numbers. Select them with `--errata <number>` or the associated `--variant` mnemonic.
ID | Name | Affected cores
-- | ---- | --------------
CVE-0001-0001 | Speculative AT TLB corruption (errata 1165522, 1319367, 1319537, 1530923) | Cortex-A55/A57/A72/A76
CVE-0001-0002 | Speculative unprivileged load (errata 2966298, 3117295) | Cortex-A510/A520
CVE-0001-0003 | MSR SSBS not self-synchronizing (erratum 3194386 + siblings) | Cortex-A76/A77/A78/A78C/A710/A715/A720/A720AE/A725, X1/X1C/X2/X3/X4/X925, Neoverse-N1/N2/N3/V1/V2/V3/V3AE
## Am I at risk? ## Am I at risk?
Depending on your situation, the table below answers whether an attacker in a given position can extract data from a given target. Depending on your situation, the table below answers whether an attacker in a given position can extract data from a given target.
@@ -280,23 +272,23 @@ In **Hardware-only** mode, the script only reports CPU information and per-CVE h
- Get the latest version of the script using `curl` *or* `wget` - Get the latest version of the script using `curl` *or* `wget`
```bash ```bash
curl -L https://meltdown.ovh -o spectre-meltdown-checker.sh curl -L https://meltdown.ovh -o spectre-meltdown-checker.sh
wget https://meltdown.ovh -O spectre-meltdown-checker.sh wget https://meltdown.ovh -O spectre-meltdown-checker.sh
``` ```
- Inspect the script. You never blindly run scripts you downloaded from the Internet, do you? - Inspect the script. You never blindly run scripts you downloaded from the Internet, do you?
```bash ```bash
vim spectre-meltdown-checker.sh vim spectre-meltdown-checker.sh
``` ```
- When you're ready, run the script as root - When you're ready, run the script as root
```bash ```bash
chmod +x spectre-meltdown-checker.sh chmod +x spectre-meltdown-checker.sh
sudo ./spectre-meltdown-checker.sh sudo ./spectre-meltdown-checker.sh
``` ```
### Using a docker container ### Using a docker container
-44
View File
@@ -188,18 +188,6 @@ 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)
@@ -319,35 +307,3 @@ A weakness in AMD's microcode signature verification (AES-CMAC hash) allows load
Exploits a synchronization failure in the AMD stack engine via an undocumented MSR bit, targeting AMD SEV-SNP confidential VMs. Requires hypervisor-level (ring 0) access. Exploits a synchronization failure in the AMD stack engine via an undocumented MSR bit, targeting AMD SEV-SNP confidential VMs. Requires hypervisor-level (ring 0) access.
**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
- **Issue:** [#329](https://github.com/speed47/spectre-meltdown-checker/issues/329)
- **Intel whitepaper:** [Mitigations for Jump Conditional Code Erratum](https://www.intel.com/content/dam/support/us/en/documents/processors/mitigations-jump-conditional-code-erratum.pdf)
- **Affected CPUs:** Intel 6th through 10th generation Core and Xeon processors (Skylake through Cascade Lake)
A microarchitectural correctness erratum where a conditional jump instruction that straddles or ends at a 64-byte instruction fetch boundary can corrupt the branch predictor state, potentially causing incorrect execution. Intel addressed this in a November 2019 microcode update. Compilers and assemblers (GCC, LLVM, binutils) also introduced alignment options (`-mbranch-alignment`, `-x86-branches-within-32B-boundaries`) to pad jump instructions away from boundary conditions, preserving performance on CPUs with updated microcode.
**Why out of scope:** The JCC erratum is a microarchitectural correctness bug, not a transient or speculative execution side-channel vulnerability. No CVE was ever assigned. Red Hat noted that privilege escalation "has not been ruled out" but made no definitive security finding, and no exploit has been demonstrated. There is no Linux sysfs entry, no CPUID bit, and no MSR flag exposing the mitigation status. The microcode fix introduces no detectable hardware indicator, so checking for it would require maintaining a per-CPU-stepping minimum microcode version table (the design principle 3 exception) — costly to maintain without a CVE anchor or confirmed exploitability to justify the ongoing work. The kernel compiler mitigation is a build-time-only change (instruction alignment) with no observable runtime state.
-245
View File
@@ -1,245 +0,0 @@
#!/bin/sh
# vim: set ts=4 sw=4 sts=4 et:
# Regenerate src/db/200_mcedb.sh, the builtin microcode firmware database.
#
# This is a standalone port of the --update-builtin-fwdb logic from
# spectre-meltdown-checker.sh. It builds the database from three sources:
# 1. platomav's MCExtractor MCE.db (Intel + AMD microcode versions)
# 2. Intel's official Linux Processor Microcode Data Files (takes precedence)
# 3. linux-firmware's amd-ucode README (AMD patch levels)
#
# The header of src/db/200_mcedb.sh (everything before the "# %%% MCEDB" line)
# is preserved as-is; only the version line and the data lines are regenerated.
#
# Requires: sqlite3, unzip, md5sum, and wget or curl.
# Intel firmwares are listed with iucode-tool when available; otherwise a pure-shell
# parser (needing only `od`) is used, so the script also works on arm64 where
# iucode-tool has no package.
#
# Usage: scripts/update_mcedb.sh
set -eu
SCRIPTDIR="$(cd "$(dirname "$0")" && pwd)"
REPODIR="$(dirname "$SCRIPTDIR")"
OUTFILE="$REPODIR/src/db/200_mcedb.sh"
MCEDB_URL='https://github.com/platomav/MCExtractor/raw/master/MCE.db'
INTEL_URL='https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files/archive/main.zip'
LINUXFW_URL='https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/plain/amd-ucode/README'
# --- sanity checks ----------------------------------------------------------
[ -r "$OUTFILE" ] || { echo "ERROR: cannot read $OUTFILE" >&2; exit 1; }
need() {
command -v "$1" >/dev/null 2>&1 || { echo "ERROR: please install the \`$1\` program" >&2; exit 1; }
}
need sqlite3
need unzip
need md5sum
# iucode-tool is preferred for listing Intel microcodes, but it has no arm64
# package, so we fall back to a pure-shell parser (parse_intel_shell) when it's
# absent. The shell parser needs `od`, which is part of coreutils everywhere.
if command -v iucode_tool >/dev/null 2>&1; then
iucode_tool=iucode_tool
elif command -v iucode-tool >/dev/null 2>&1; then
iucode_tool=iucode-tool
else
iucode_tool=
need od
fi
# download_file URL DEST
download_file() {
if command -v wget >/dev/null 2>&1; then
wget -q -O "$2" "$1"
elif command -v curl >/dev/null 2>&1; then
curl -sL -o "$2" "$1"
else
echo "ERROR: please install either \`wget\` or \`curl\`" >&2
exit 1
fi
}
# fms2cpuid FAMILY MODEL STEPPING -- replicates the helper from the main script
fms2cpuid() {
family="$1"
model="$2"
stepping="$3"
if [ "$((family))" -le 15 ]; then
extfamily=0
lowfamily=$((family))
else
lowfamily=15
extfamily=$(((family) - 15))
fi
extmodel=$(((model & 0xF0) >> 4))
lowmodel=$(((model & 0x0F) >> 0))
echo $(((stepping & 0x0F) | (lowmodel << 4) | (lowfamily << 8) | (extmodel << 16) | (extfamily << 20)))
}
# Emit a normalized "CPUID PFMASK VERSION YYYYMMDD" line (all hex except date).
# Args: $1=sig $2=pf $3=rev (all hex, no 0x) $4=date as stored (0xMMDDYYYY hex)
emit_intel() {
_mm=${4%????}; _yyyy=${4#????} # date is MMDDYYYY -> reorder to YYYYMMDD
printf '%08X %02X %08X %s\n' "$((0x$1))" "$((0x$2))" "$((0x$3))" "${_yyyy}${_mm}"
}
# Pure-shell equivalent of `iucode-tool -l`: walk every microcode in a directory
# and print one normalized line per (signature, processor-flags) pair, including
# those that exist only via a microcode's extended signature table.
# The Intel microcode header is 48 bytes of little-endian uint32 fields:
# off 0 hdrver, 4 rev, 8 date, 12 sig, 24 pf, 28 datasize, 32 totalsize.
# An extended signature table (if totalsize > 48+datasize) sits at 48+datasize:
# a 20-byte sub-header (count at off 0) then 12 bytes per entry (sig, pf, cksum).
parse_intel_shell() {
for _f in "$1"/*; do
[ -f "$_f" ] || continue
_fsize=$(wc -c <"$_f")
_base=0
while [ "$_base" -lt "$_fsize" ] && [ $((_base + 48)) -le "$_fsize" ]; do
# shellcheck disable=SC2046 # intentional word-splitting of the 12 header words
set -- $(od -An -tx4 -j "$_base" -N48 "$_f" | tr '\n' ' ')
[ "$1" = "00000001" ] || break # not a microcode header, stop
_rev=$2; _date=$3; _sig=$4; _pf=$7
_datasize=$((0x$8)); [ "$_datasize" = 0 ] && _datasize=2000
_totalsize=$((0x$9)); [ "$_totalsize" = 0 ] && _totalsize=2048
emit_intel "$_sig" "$_pf" "$_rev" "$_date"
# extended signature table, if any
_extbase=$((_base + 48 + _datasize))
if [ "$_totalsize" -gt $((48 + _datasize)) ]; then
_count=$((0x$(od -An -tx4 -j "$_extbase" -N4 "$_f" | tr -d ' \n')))
_i=0
while [ "$_i" -lt "$_count" ]; do
_eoff=$((_extbase + 20 + _i * 12))
_esig=$(od -An -tx4 -j "$_eoff" -N4 "$_f" | tr -d ' \n')
_epf=$( od -An -tx4 -j $((_eoff + 4)) -N4 "$_f" | tr -d ' \n')
emit_intel "$_esig" "$_epf" "$_rev" "$_date"
_i=$((_i + 1))
done
fi
_base=$((_base + _totalsize))
done
done
}
# List Intel microcodes as normalized "CPUID PFMASK VERSION YYYYMMDD" lines,
# using iucode-tool when available, else the pure-shell parser.
intel_listing() {
if [ -n "$iucode_tool" ]; then
# 079/001: sig 0x000106c2, pf_mask 0x01, 2009-04-10, rev 0x0217, size 5120
"$iucode_tool" -l "$1" | grep -wF sig | while read -r line; do
_sig=$(echo "$line" | grep -Eio 'sig 0x[0-9a-f]+' | awk '{print $2}')
_pf=$(echo "$line" | grep -Eio 'pf_mask 0x[0-9a-f]+' | awk '{print $2}')
_rev=$(echo "$line" | grep -Eio 'rev 0x[0-9a-f]+' | awk '{print $2}')
_date=$(echo "$line" | grep -Eo '(19|20)[0-9][0-9]-[01][0-9]-[0-3][0-9]' | tr -d '-')
printf '%08X %02X %08X %s\n' "$((_sig))" "$((_pf))" "$((_rev))" "$_date"
done
else
parse_intel_shell "$1"
fi
}
# --- temp files -------------------------------------------------------------
MCEDB_TMP=$(mktemp -t smc-mcedb-XXXXXX)
INTEL_TMP=$(mktemp -d -t smc-intelfw-XXXXXX)
LINUXFW_TMP=$(mktemp -t smc-linuxfw-XXXXXX)
DATA_TMP=$(mktemp -t smc-mcedata-XXXXXX)
trap 'rm -rf "$MCEDB_TMP" "$INTEL_TMP" "$LINUXFW_TMP" "$DATA_TMP"' EXIT INT TERM
# --- 1. fetch MCExtractor's MCE.db ------------------------------------------
printf 'Fetching MCE.db from the MCExtractor project... '
download_file "$MCEDB_URL" "$MCEDB_TMP"
mcedb_revision=$(sqlite3 "$MCEDB_TMP" 'SELECT "revision" from "MCE"')
[ -n "$mcedb_revision" ] || { echo "ERROR: downloaded file seems invalid" >&2; exit 1; }
# add origin/pfmask columns; everything from MCE.db is tagged 'mce' with a wildcard pfmask
sqlite3 "$MCEDB_TMP" 'ALTER TABLE "Intel" ADD COLUMN "origin" TEXT'
sqlite3 "$MCEDB_TMP" 'ALTER TABLE "Intel" ADD COLUMN "pfmask" TEXT'
sqlite3 "$MCEDB_TMP" 'ALTER TABLE "AMD" ADD COLUMN "origin" TEXT'
sqlite3 "$MCEDB_TMP" 'ALTER TABLE "AMD" ADD COLUMN "pfmask" TEXT'
sqlite3 "$MCEDB_TMP" "UPDATE \"Intel\" SET \"origin\"='mce'"
sqlite3 "$MCEDB_TMP" "UPDATE \"Intel\" SET \"pfmask\"='FF'"
sqlite3 "$MCEDB_TMP" "UPDATE \"AMD\" SET \"origin\"='mce'"
sqlite3 "$MCEDB_TMP" "UPDATE \"AMD\" SET \"pfmask\"='FF'"
echo "OK (MCExtractor database revision $mcedb_revision)"
# --- 2. integrate Intel's official firmwares (these take precedence) --------
printf 'Fetching Intel firmwares... '
download_file "$INTEL_URL" "$INTEL_TMP/fw.zip"
(cd "$INTEL_TMP" && unzip -q fw.zip)
INTEL_UCODE_DIR="$INTEL_TMP/Intel-Linux-Processor-Microcode-Data-Files-main"
[ -d "$INTEL_UCODE_DIR/intel-ucode" ] || { echo "ERROR: expected the 'intel-ucode' folder in the downloaded zip file" >&2; exit 1; }
echo OK
if [ -n "$iucode_tool" ]; then
printf 'Integrating Intel firmwares data to db (via %s)... ' "$iucode_tool"
else
printf 'Integrating Intel firmwares data to db (via shell parser)... '
fi
intel_listing "$INTEL_UCODE_DIR/intel-ucode" | while read -r cpuid pfmask version date; do
# ensure the official Intel DB always has precedence over mcedb, even if mcedb has seen a more recent fw
sqlite3 "$MCEDB_TMP" "DELETE FROM \"Intel\" WHERE \"origin\" != 'intel' AND \"cpuid\" = '$cpuid';"
sqlite3 "$MCEDB_TMP" "INSERT INTO \"Intel\" (\"origin\",\"cpuid\",\"pfmask\",\"version\",\"yyyymmdd\") VALUES ('intel','$cpuid','$pfmask','$version','$date');"
done
# the license file's mtime matches the upstream last commit date
intel_timestamp=$(stat -c %Y "$INTEL_UCODE_DIR/license" 2>/dev/null || stat -f %m "$INTEL_UCODE_DIR/license" 2>/dev/null || true)
if [ -n "$intel_timestamp" ]; then
intel_latest_date=$(date -d @"$intel_timestamp" +%Y%m%d 2>/dev/null || date -r "$intel_timestamp" +%Y%m%d)
else
echo "Falling back to the latest microcode date"
intel_latest_date=$(sqlite3 "$MCEDB_TMP" "SELECT \"yyyymmdd\" FROM \"Intel\" WHERE \"origin\"='intel' ORDER BY \"yyyymmdd\" DESC LIMIT 1;")
fi
echo "DONE (version $intel_latest_date)"
# --- 3. integrate AMD patch levels from linux-firmware ----------------------
printf 'Fetching latest amd-ucode README from linux-firmware project... '
download_file "$LINUXFW_URL" "$LINUXFW_TMP"
echo OK
printf 'Parsing the README... '
nbfound=0
for line in $(grep -E 'Family=0x[0-9a-f]+ Model=0x[0-9a-f]+ Stepping=0x[0-9a-f]+: Patch=0x[0-9a-f]+' "$LINUXFW_TMP" | tr " " ","); do
family=$(echo "$line" | grep -Eoi 'Family=0x[0-9a-f]+' | cut -d= -f2)
model=$(echo "$line" | grep -Eoi 'Model=0x[0-9a-f]+' | cut -d= -f2)
stepping=$(echo "$line" | grep -Eoi 'Stepping=0x[0-9a-f]+' | cut -d= -f2)
version=$(echo "$line" | grep -Eoi 'Patch=0x[0-9a-f]+' | cut -d= -f2)
version=$(printf "%08X" "$((version))")
cpuid=$(fms2cpuid "$family" "$model" "$stepping")
cpuid=$(printf "%08X" "$cpuid")
sqlite3 "$MCEDB_TMP" "INSERT INTO \"AMD\" (\"origin\",\"cpuid\",\"pfmask\",\"version\",\"yyyymmdd\") VALUES ('linux-firmware','$cpuid','FF','$version','20000101')"
nbfound=$((nbfound + 1))
done
echo "found $nbfound microcodes"
# --- 4. compute version string and dump the most recent fw per cpuid+pfmask -
dbversion="$mcedb_revision+i$intel_latest_date"
linuxfw_hash=$(md5sum "$LINUXFW_TMP" 2>/dev/null | cut -c1-4)
[ -n "$linuxfw_hash" ] && dbversion="$dbversion+$linuxfw_hash"
printf 'Building database... '
{
echo "# %%% MCEDB v$dbversion"
sqlite3 "$MCEDB_TMP" "SELECT '# I,0x'||\"t1\".\"cpuid\"||',0x'||\"t1\".\"pfmask\"||',0x'||MAX(\"t1\".\"version\")||','||\"t1\".\"yyyymmdd\" FROM \"Intel\" AS \"t1\" LEFT OUTER JOIN \"Intel\" AS \"t2\" ON \"t2\".\"cpuid\"=\"t1\".\"cpuid\" AND \"t2\".\"pfmask\"=\"t1\".\"pfmask\" AND \"t2\".\"yyyymmdd\" > \"t1\".\"yyyymmdd\" WHERE \"t2\".\"yyyymmdd\" IS NULL GROUP BY \"t1\".\"cpuid\",\"t1\".\"pfmask\" ORDER BY \"t1\".\"cpuid\",\"t1\".\"pfmask\" ASC;" | grep -v '^# .,0x00000000,'
sqlite3 "$MCEDB_TMP" "SELECT '# A,0x'||\"t1\".\"cpuid\"||',0x'||\"t1\".\"pfmask\"||',0x'||MAX(\"t1\".\"version\")||','||\"t1\".\"yyyymmdd\" FROM \"AMD\" AS \"t1\" LEFT OUTER JOIN \"AMD\" AS \"t2\" ON \"t2\".\"cpuid\"=\"t1\".\"cpuid\" AND \"t2\".\"pfmask\"=\"t1\".\"pfmask\" AND \"t2\".\"yyyymmdd\" > \"t1\".\"yyyymmdd\" WHERE \"t2\".\"yyyymmdd\" IS NULL GROUP BY \"t1\".\"cpuid\",\"t1\".\"pfmask\" ORDER BY \"t1\".\"cpuid\",\"t1\".\"pfmask\" ASC;" | grep -v '^# .,0x00000000,'
} >"$DATA_TMP"
echo "DONE (version $dbversion)"
# --- 5. rewrite src/db/200_mcedb.sh, preserving its header ------------------
newfile=$(mktemp -t smc-builtin-XXXXXX)
trap 'rm -rf "$MCEDB_TMP" "$INTEL_TMP" "$LINUXFW_TMP" "$DATA_TMP" "$newfile"' EXIT INT TERM
# keep everything before the "# %%% MCEDB" line, then append the freshly built data
awk '/^# %%% MCEDB / { exit }; { print }' "$OUTFILE" >"$newfile"
cat "$DATA_TMP" >>"$newfile"
cat "$newfile" >"$OUTFILE"
echo "Updated $OUTFILE ($(wc -l <"$OUTFILE") lines, version $dbversion)"
+35 -52
View File
@@ -24,9 +24,6 @@ show_usage() {
can be used multiple times (e.g. --variant 3a --variant l1tf). For a list use 'help'. can be used multiple times (e.g. --variant 3a --variant l1tf). For a list use 'help'.
--cve CVE specify which CVE you'd like to check, by default all supported CVEs are checked --cve CVE specify which CVE you'd like to check, by default all supported CVEs are checked
can be used multiple times (e.g. --cve CVE-2017-5753 --cve CVE-2020-0543) can be used multiple times (e.g. --cve CVE-2017-5753 --cve CVE-2020-0543)
--errata NUMBER specify a vendor-numbered erratum (e.g. ARM64 erratum 1530923) that has no CVE
assigned. Maps the erratum to the corresponding check. For a list use 'help'.
Can be used multiple times (e.g. --errata 1530923 --errata 3194386).
Check scope: Check scope:
--no-sysfs don't use the /sys interface even if present [Linux] --no-sysfs don't use the /sys interface even if present [Linux]
@@ -155,61 +152,47 @@ g_smc_system_info_line=''
g_smc_cpu_info_line='' g_smc_cpu_info_line=''
# CVE Registry: single source of truth for all CVE metadata. # CVE Registry: single source of truth for all CVE metadata.
# Fields: cve_id|json_key_name|affected_var_suffix|complete_name_and_aliases|arch # Fields: cve_id|json_key_name|affected_var_suffix|complete_name_and_aliases
# #
# The optional `arch` field gates whether the check is run at all, based on the # Two ranges of placeholder IDs are reserved when no real CVE applies:
# host CPU architecture and the inspected kernel architecture. Values:
# x86 - only relevant when host CPU or inspected kernel is x86/amd64
# arm - only relevant when host CPU or inspected kernel is ARM/ARM64
# (empty) - always relevant (shared logic across architectures, e.g. Spectre V1-V4)
# The gate only applies to default "all CVEs" runs; explicit --cve/--variant/--errata
# selection bypasses it (if the user asks for it, they get it regardless of arch).
#
# Three ranges of placeholder IDs are reserved when no real CVE applies:
# CVE-0000-NNNN: permanent placeholder for supplementary checks (--extra only) # CVE-0000-NNNN: permanent placeholder for supplementary checks (--extra only)
# that will never receive a real CVE (e.g. SLS, compile-time hardening). # that will never receive a real CVE (e.g. SLS, compile-time hardening).
# CVE-0001-NNNN: permanent placeholder for vendor-numbered errata that will never
# receive a CVE (e.g. ARM64 silicon errata tracked only by erratum ID).
# Selectable via --errata <number>.
# CVE-9999-NNNN: temporary placeholder for real vulnerabilities awaiting CVE # CVE-9999-NNNN: temporary placeholder for real vulnerabilities awaiting CVE
# assignment. Rename across the codebase once the real CVE is issued. # assignment. Rename across the codebase once the real CVE is issued.
readonly CVE_REGISTRY=' readonly CVE_REGISTRY='
CVE-2017-5753|SPECTRE VARIANT 1|variant1|Spectre Variant 1, bounds check bypass| CVE-2017-5753|SPECTRE VARIANT 1|variant1|Spectre Variant 1, bounds check bypass
CVE-2017-5715|SPECTRE VARIANT 2|variant2|Spectre Variant 2, branch target injection| CVE-2017-5715|SPECTRE VARIANT 2|variant2|Spectre Variant 2, branch target injection
CVE-2017-5754|MELTDOWN|variant3|Variant 3, Meltdown, rogue data cache load| CVE-2017-5754|MELTDOWN|variant3|Variant 3, Meltdown, rogue data cache load
CVE-2018-3640|VARIANT 3A|variant3a|Variant 3a, rogue system register read| CVE-2018-3640|VARIANT 3A|variant3a|Variant 3a, rogue system register read
CVE-2018-3639|VARIANT 4|variant4|Variant 4, speculative store bypass| CVE-2018-3639|VARIANT 4|variant4|Variant 4, speculative store bypass
CVE-2018-3615|L1TF SGX|variantl1tf_sgx|Foreshadow (SGX), L1 terminal fault|x86 CVE-2018-3615|L1TF SGX|variantl1tf_sgx|Foreshadow (SGX), L1 terminal fault
CVE-2018-3620|L1TF OS|variantl1tf|Foreshadow-NG (OS), L1 terminal fault|x86 CVE-2018-3620|L1TF OS|variantl1tf|Foreshadow-NG (OS), L1 terminal fault
CVE-2018-3646|L1TF VMM|variantl1tf|Foreshadow-NG (VMM), L1 terminal fault|x86 CVE-2018-3646|L1TF VMM|variantl1tf|Foreshadow-NG (VMM), L1 terminal fault
CVE-2018-12126|MSBDS|msbds|Fallout, microarchitectural store buffer data sampling (MSBDS)|x86 CVE-2018-12126|MSBDS|msbds|Fallout, microarchitectural store buffer data sampling (MSBDS)
CVE-2018-12130|MFBDS|mfbds|ZombieLoad, microarchitectural fill buffer data sampling (MFBDS)|x86 CVE-2018-12130|MFBDS|mfbds|ZombieLoad, microarchitectural fill buffer data sampling (MFBDS)
CVE-2018-12127|MLPDS|mlpds|RIDL, microarchitectural load port data sampling (MLPDS)|x86 CVE-2018-12127|MLPDS|mlpds|RIDL, microarchitectural load port data sampling (MLPDS)
CVE-2019-11091|MDSUM|mdsum|RIDL, microarchitectural data sampling uncacheable memory (MDSUM)|x86 CVE-2019-11091|MDSUM|mdsum|RIDL, microarchitectural data sampling uncacheable memory (MDSUM)
CVE-2019-11135|TAA|taa|ZombieLoad V2, TSX Asynchronous Abort (TAA)|x86 CVE-2019-11135|TAA|taa|ZombieLoad V2, TSX Asynchronous Abort (TAA)
CVE-2018-12207|ITLBMH|itlbmh|No eXcuses, iTLB Multihit, machine check exception on page size changes (MCEPSC)|x86 CVE-2018-12207|ITLBMH|itlbmh|No eXcuses, iTLB Multihit, machine check exception on page size changes (MCEPSC)
CVE-2020-0543|SRBDS|srbds|Special Register Buffer Data Sampling (SRBDS)|x86 CVE-2020-0543|SRBDS|srbds|Special Register Buffer Data Sampling (SRBDS)
CVE-2022-21123|SBDR|mmio|Shared Buffers Data Read (SBDR), MMIO Stale Data|x86 CVE-2022-21123|SBDR|mmio|Shared Buffers Data Read (SBDR), MMIO Stale Data
CVE-2022-21125|SBDS|mmio|Shared Buffers Data Sampling (SBDS), MMIO Stale Data|x86 CVE-2022-21125|SBDS|mmio|Shared Buffers Data Sampling (SBDS), MMIO Stale Data
CVE-2022-21166|DRPW|mmio|Device Register Partial Write (DRPW), MMIO Stale Data|x86 CVE-2022-21166|DRPW|mmio|Device Register Partial Write (DRPW), MMIO Stale Data
CVE-2023-20588|DIV0|div0|Division by Zero, AMD Zen1 speculative data leak|x86 CVE-2023-20588|DIV0|div0|Division by Zero, AMD Zen1 speculative data leak
CVE-2023-20593|ZENBLEED|zenbleed|Zenbleed, cross-process information leak|x86 CVE-2023-20593|ZENBLEED|zenbleed|Zenbleed, cross-process information leak
CVE-2022-40982|DOWNFALL|downfall|Downfall, gather data sampling (GDS)|x86 CVE-2022-40982|DOWNFALL|downfall|Downfall, gather data sampling (GDS)
CVE-2022-29900|RETBLEED AMD|retbleed|Retbleed, arbitrary speculative code execution with return instructions (AMD)|x86 CVE-2022-29900|RETBLEED AMD|retbleed|Retbleed, arbitrary speculative code execution with return instructions (AMD)
CVE-2022-29901|RETBLEED INTEL|retbleed|Retbleed, arbitrary speculative code execution with return instructions (Intel)|x86 CVE-2022-29901|RETBLEED INTEL|retbleed|Retbleed, arbitrary speculative code execution with return instructions (Intel)
CVE-2023-20569|INCEPTION|inception|Inception, return address security (RAS)|x86 CVE-2023-20569|INCEPTION|inception|Inception, return address security (RAS)
CVE-2023-23583|REPTAR|reptar|Reptar, redundant prefix issue|x86 CVE-2023-23583|REPTAR|reptar|Reptar, redundant prefix issue
CVE-2024-36350|TSA_SQ|tsa|Transient Scheduler Attack - Store Queue (TSA-SQ)|x86 CVE-2024-36350|TSA_SQ|tsa|Transient Scheduler Attack - Store Queue (TSA-SQ)
CVE-2024-36357|TSA_L1|tsa|Transient Scheduler Attack - L1 (TSA-L1)|x86 CVE-2024-36357|TSA_L1|tsa|Transient Scheduler Attack - L1 (TSA-L1)
CVE-2024-28956|ITS|its|Indirect Target Selection (ITS)|x86 CVE-2024-28956|ITS|its|Indirect Target Selection (ITS)
CVE-2025-40300|VMSCAPE|vmscape|VMScape, VM-exit stale branch prediction|x86 CVE-2025-40300|VMSCAPE|vmscape|VMScape, VM-exit stale branch prediction
CVE-2023-28746|RFDS|rfds|Register File Data Sampling (RFDS)|x86 CVE-2023-28746|RFDS|rfds|Register File Data Sampling (RFDS)
CVE-2024-45332|BPI|bpi|Branch Privilege Injection (BPI)|x86 CVE-2024-45332|BPI|bpi|Branch Privilege Injection (BPI)
CVE-0000-0001|SLS|sls|Straight-Line Speculation (SLS)| CVE-0000-0001|SLS|sls|Straight-Line Speculation (SLS)
CVE-2025-54505|FPDSS|fpdss|FPDSS, AMD Zen1 Floating-Point Divider Stale Data Leak|x86 CVE-2025-54505|FPDSS|fpdss|FPDSS, AMD Zen1 Floating-Point Divider Stale Data Leak
CVE-0001-0001|ARM SPEC AT|arm_spec_at|ARM64 errata 1165522/1319367/1319537/1530923, Speculative AT TLB corruption|arm
CVE-0001-0002|ARM SPEC UNPRIV LOAD|arm_spec_unpriv_load|ARM64 errata 2966298/3117295, Speculative unprivileged load|arm
CVE-0001-0003|ARM SSBS NOSYNC|arm_ssbs_nosync|ARM64 erratum 3194386, MSR SSBS not self-synchronizing|arm
' '
# Derive the supported CVE list from the registry # Derive the supported CVE list from the registry
-106
View File
@@ -27,36 +27,6 @@ _infer_immune() { eval "[ -z \"\$affected_$1\" ] && affected_$1=1 || :"; }
# Use for: family-level catch-all fallbacks (Intel L1TF non-whitelist, itlbmh non-whitelist). # Use for: family-level catch-all fallbacks (Intel L1TF non-whitelist, itlbmh non-whitelist).
_infer_vuln() { eval "[ -z \"\$affected_$1\" ] && affected_$1=0 || :"; } _infer_vuln() { eval "[ -z \"\$affected_$1\" ] && affected_$1=0 || :"; }
# Return 0 (true) if a CVE's arch tag matches the current context (host CPU
# and/or target kernel), so the check is worth running. Untagged CVEs are
# always relevant.
# - In no-hw mode the host CPU is ignored: gate only on target kernel arch.
# - Otherwise a match on either the host CPU or the target kernel is enough
# (they normally agree in live mode; if they disagree, check_kernel_cpu_arch_mismatch
# has already forced no-hw, handled by the branch above).
# Args: $1=cve_id
# Callers: src/main.sh (CVE dispatch loop), check_cpu_vulnerabilities
_is_cve_relevant_arch() {
local arch
arch=$(_cve_registry_field "$1" 5)
# Untagged CVE: always relevant
[ -z "$arch" ] && return 0
case "$arch" in
x86)
[ "$g_mode" != no-hw ] && is_x86_cpu && return 0
is_x86_kernel && return 0
return 1
;;
arm)
[ "$g_mode" != no-hw ] && is_arm_cpu && return 0
is_arm_kernel && return 0
return 1
;;
esac
# Unknown tag value: don't gate (fail open)
return 0
}
# Return the cached affected_* status for a given CVE # Return the cached affected_* status for a given CVE
# Args: $1=cve_id # Args: $1=cve_id
# Returns: 0 if affected, 1 if not affected # Returns: 0 if affected, 1 if not affected
@@ -136,10 +106,6 @@ is_cpu_affected() {
affected_srbds='' affected_srbds=''
affected_mmio='' affected_mmio=''
affected_sls='' affected_sls=''
# ARM64 speculation-related errata (ARM Ltd, implementer 0x41); non-ARM systems are immune below.
affected_arm_spec_at=''
affected_arm_spec_unpriv_load=''
affected_arm_ssbs_nosync=''
# DIV0, FPDSS, Zenbleed and Inception are all AMD specific, look for "is_amd" below: # DIV0, FPDSS, Zenbleed and Inception are all AMD specific, look for "is_amd" below:
_set_immune div0 _set_immune div0
_set_immune fpdss _set_immune fpdss
@@ -861,77 +827,6 @@ is_cpu_affected() {
_infer_immune sls _infer_immune sls
fi fi
# ARM64 silicon errata (speculation/security-relevant, no CVE assignments).
# References: arch/arm64/Kconfig (ARM64_ERRATUM_*), arch/arm64/kernel/cpu_errata.c MIDR lists.
# Iterates per-core (impl, part, variant, revision) tuples. Implementers currently handled:
# 0x41 ARM Ltd; 0x51 Qualcomm (Kryo4xx Silver for erratum 1530923).
# Revision ranges mirror the kernel's MIDR_RANGE/MIDR_REV_RANGE/MIDR_REV macros. A variant
# 'v' and revision 'p' are packed as (v<<4)|p for range compares — equivalent to the kernel's
# layout (MIDR_VARIANT_SHIFT=20, MIDR_REVISION_MASK=0xf) under the same order semantics.
# Unknown variant/revision ⇒ treat as in range (whitelist principle, DEVELOPMENT.md rule 5).
if [ -n "$cpu_part_list" ]; then
i=0
for cpupart in $cpu_part_list; do
i=$((i + 1))
# shellcheck disable=SC2086
cpuimpl=$(echo $cpu_impl_list | awk '{print $'$i'}')
# shellcheck disable=SC2086
cpuvar=$(echo $cpu_variant_list | awk '{print $'$i'}')
# shellcheck disable=SC2086
cpurev=$(echo $cpu_revision_list | awk '{print $'$i'}')
packed=''
[ -n "$cpuvar" ] && [ -n "$cpurev" ] && packed=$(((cpuvar << 4) | cpurev))
# Speculative AT TLB corruption (errata 1165522, 1319367, 1319537, 1530923)
if [ "$cpuimpl" = 0x41 ]; then
if echo "$cpupart" | grep -q -w -e 0xd07 -e 0xd08; then
# Cortex-A57 (0xd07) / A72 (0xd08): all revisions
_set_vuln arm_spec_at
elif echo "$cpupart" | grep -q -w -e 0xd05 -e 0xd0b; then
# Cortex-A55 (0xd05) / A76 (0xd0b): r0p0..r2p0 (packed 0..32)
if [ -z "$packed" ] || [ "$packed" -le 32 ]; then
_set_vuln arm_spec_at
fi
fi
elif [ "$cpuimpl" = 0x51 ] && [ "$cpupart" = 0x805 ]; then
# Qualcomm Kryo4xx Silver: kernel matches MIDR_REV(var 0xd, rev 0xe) only — packed 0xde = 222
if [ -z "$packed" ] || [ "$packed" = 222 ]; then
_set_vuln arm_spec_at
fi
fi
# Speculative unprivileged load (errata 2966298 A520, 3117295 A510) — ARM Ltd only
if [ "$cpuimpl" = 0x41 ]; then
if [ "$cpupart" = 0xd46 ]; then
# Cortex-A510: all revisions
_set_vuln arm_spec_unpriv_load
elif [ "$cpupart" = 0xd80 ]; then
# Cortex-A520: r0p0..r0p1 (packed 0..1)
if [ -z "$packed" ] || [ "$packed" -le 1 ]; then
_set_vuln arm_spec_unpriv_load
fi
fi
fi
# MSR SSBS not self-synchronizing (erratum 3194386 + siblings) — ARM Ltd only, all revisions.
# A76/A77/A78/A78C/A710/A715/A720/A720AE/A725, X1/X1C/X2/X3/X4/X925, N1/N2/N3, V1/V2/V3/V3AE
if [ "$cpuimpl" = 0x41 ]; then
if echo "$cpupart" | grep -q -w \
-e 0xd0b -e 0xd0d -e 0xd41 -e 0xd4b \
-e 0xd47 -e 0xd4d -e 0xd81 -e 0xd89 -e 0xd87 \
-e 0xd44 -e 0xd4c -e 0xd48 -e 0xd4e -e 0xd82 -e 0xd85 \
-e 0xd0c -e 0xd49 -e 0xd8e \
-e 0xd40 -e 0xd4f -e 0xd84 -e 0xd83; then
_set_vuln arm_ssbs_nosync
fi
fi
done
fi
# Default everything else to immune (covers non-ARM, and ARM cores not in the affected lists)
_infer_immune arm_spec_at
_infer_immune arm_spec_unpriv_load
_infer_immune arm_ssbs_nosync
# shellcheck disable=SC2154 # shellcheck disable=SC2154
{ {
pr_debug "is_cpu_affected: final results: variant1=$affected_variant1 variant2=$affected_variant2 variant3=$affected_variant3 variant3a=$affected_variant3a" pr_debug "is_cpu_affected: final results: variant1=$affected_variant1 variant2=$affected_variant2 variant3=$affected_variant3 variant3a=$affected_variant3a"
@@ -939,7 +834,6 @@ is_cpu_affected() {
pr_debug "is_cpu_affected: final results: mlpds=$affected_mlpds mdsum=$affected_mdsum taa=$affected_taa itlbmh=$affected_itlbmh srbds=$affected_srbds" pr_debug "is_cpu_affected: final results: mlpds=$affected_mlpds mdsum=$affected_mdsum taa=$affected_taa itlbmh=$affected_itlbmh srbds=$affected_srbds"
pr_debug "is_cpu_affected: final results: div0=$affected_div0 fpdss=$affected_fpdss zenbleed=$affected_zenbleed inception=$affected_inception retbleed=$affected_retbleed tsa=$affected_tsa downfall=$affected_downfall reptar=$affected_reptar rfds=$affected_rfds its=$affected_its" pr_debug "is_cpu_affected: final results: div0=$affected_div0 fpdss=$affected_fpdss zenbleed=$affected_zenbleed inception=$affected_inception retbleed=$affected_retbleed tsa=$affected_tsa downfall=$affected_downfall reptar=$affected_reptar rfds=$affected_rfds its=$affected_its"
pr_debug "is_cpu_affected: final results: vmscape=$affected_vmscape bpi=$affected_bpi sls=$affected_sls mmio=$affected_mmio" pr_debug "is_cpu_affected: final results: vmscape=$affected_vmscape bpi=$affected_bpi sls=$affected_sls mmio=$affected_mmio"
pr_debug "is_cpu_affected: final results: arm_spec_at=$affected_arm_spec_at arm_spec_unpriv_load=$affected_arm_spec_unpriv_load arm_ssbs_nosync=$affected_arm_ssbs_nosync"
} }
affected_variantl1tf_sgx="$affected_variantl1tf" affected_variantl1tf_sgx="$affected_variantl1tf"
# even if we are affected to L1TF, if there's no SGX, we're not affected to the original foreshadow # even if we are affected to L1TF, if there's no SGX, we're not affected to the original foreshadow
+43 -69
View File
@@ -187,84 +187,58 @@ is_cpu_srbds_free() {
} }
# Check whether the CPU is architecturally immune to MMIO Stale Data
# Mirrors the kernel's arch_cap_mmio_immune() helper: ALL THREE ARCH_CAP bits must be set:
# ARCH_CAP_SBDR_SSDP_NO (bit 13), ARCH_CAP_FBSDP_NO (bit 14), ARCH_CAP_PSDP_NO (bit 15)
# Returns: 0 if immune, 1 otherwise
is_arch_cap_mmio_immune() {
[ "$cap_sbdr_ssdp_no" = 1 ] && [ "$cap_fbsdp_no" = 1 ] && [ "$cap_psdp_no" = 1 ]
}
# Whether the MMIO arch-cap immunity bits are undetermined because the
# IA32_ARCH_CAPABILITIES MSR couldn't be read (msr module unavailable or kernel
# lockdown).
# Returns: 0 if undetermined, 1 otherwise
is_arch_cap_mmio_undetermined() {
[ "$cap_sbdr_ssdp_no" = -1 ] || [ "$cap_fbsdp_no" = -1 ] || [ "$cap_psdp_no" = -1 ]
}
# Check whether the CPU is known to be unaffected by MMIO Stale Data (CVE-2022-21123/21125/21166) # Check whether the CPU is known to be unaffected by MMIO Stale Data (CVE-2022-21123/21125/21166)
# Matches the kernel's NO_MMIO whitelist plus arch_cap_mmio_immune().
# Model inventory and kernel-commit history are documented in check_mmio_linux().
# Returns: 0 if MMIO-free, 1 if affected or unknown # Returns: 0 if MMIO-free, 1 if affected or unknown
is_cpu_mmio_free() { is_cpu_mmio_free() {
# source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c
#
# CPU affection logic from kernel (51802186158c, v5.19):
# Bug is set when: cpu_matches(blacklist, MMIO) AND NOT arch_cap_mmio_immune()
# arch_cap_mmio_immune() requires ALL THREE bits set:
# ARCH_CAP_FBSDP_NO (bit 14) AND ARCH_CAP_PSDP_NO (bit 15) AND ARCH_CAP_SBDR_SSDP_NO (bit 13)
#
# Intel Family 6 model blacklist (unchanged since v5.19):
# HASWELL_X (0x3F)
# BROADWELL_D (0x56), BROADWELL_X (0x4F)
# SKYLAKE_X (0x55), SKYLAKE_L (0x4E), SKYLAKE (0x5E)
# KABYLAKE_L (0x8E), KABYLAKE (0x9E)
# ICELAKE_L (0x7E), ICELAKE_D (0x6C), ICELAKE_X (0x6A)
# COMETLAKE (0xA5), COMETLAKE_L (0xA6)
# LAKEFIELD (0x8A)
# ROCKETLAKE (0xA7)
# ATOM_TREMONT (0x96), ATOM_TREMONT_D (0x86), ATOM_TREMONT_L (0x9C)
#
# Vendor scope: Intel only. Non-Intel CPUs are not affected.
parse_cpu_details parse_cpu_details
is_arch_cap_mmio_immune && return 0 # ARCH_CAP immunity: all three bits must be set
# Non-Intel x86 vendors the kernel unconditionally whitelists (AMD/Hygon all if [ "$cap_sbdr_ssdp_no" = 1 ] && [ "$cap_fbsdp_no" = 1 ] && [ "$cap_psdp_no" = 1 ]; then
# families; Centaur/Zhaoxin fam 7 only).
if is_amd || is_hygon; then
return 0 return 0
fi fi
if { [ "$cpu_vendor" = "CentaurHauls" ] || [ "$cpu_vendor" = "Shanghai" ]; } && [ "$cpu_family" = 7 ]; then if is_intel; then
return 0 if [ "$cpu_family" = 6 ]; then
fi if [ "$cpu_model" = "$INTEL_FAM6_HASWELL_X" ] ||
# Intel NO_MMIO whitelist [ "$cpu_model" = "$INTEL_FAM6_BROADWELL_D" ] ||
if is_intel && [ "$cpu_family" = 6 ]; then [ "$cpu_model" = "$INTEL_FAM6_BROADWELL_X" ] ||
if [ "$cpu_model" = "$INTEL_FAM6_TIGERLAKE" ] || [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_TIGERLAKE_L" ] || [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ALDERLAKE" ] || [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ALDERLAKE_L" ] || [ "$cpu_model" = "$INTEL_FAM6_KABYLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT" ] || [ "$cpu_model" = "$INTEL_FAM6_KABYLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_D" ] || [ "$cpu_model" = "$INTEL_FAM6_ICELAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_PLUS" ]; then [ "$cpu_model" = "$INTEL_FAM6_ICELAKE_D" ] ||
return 0 [ "$cpu_model" = "$INTEL_FAM6_ICELAKE_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_COMETLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_COMETLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_LAKEFIELD" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ROCKETLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT_L" ]; then
return 1
fi
fi fi
fi fi
return 1
}
# Check whether the CPU's MMIO Stale Data status is unknown ("out of servicing period")
# Matches the kernel's X86_BUG_MMIO_UNKNOWN: Intel CPU not MMIO-free and not in the
# MMIO blacklist. The kernel reports "Unknown: No mitigations" for such CPUs.
# Callers: check_mmio_linux, check_mmio_bsd
# Returns: 0 if unknown, 1 if known (either affected or not affected)
is_cpu_mmio_unknown() {
parse_cpu_details
# Only Intel can reach the unknown bucket — other x86 vendors are whitelisted by vendor-id.
is_intel || return 1
is_cpu_mmio_free && return 1
if [ "$cpu_family" = 6 ]; then
if [ "$cpu_model" = "$INTEL_FAM6_HASWELL_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_BROADWELL_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_BROADWELL_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_KABYLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_KABYLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_COMETLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_COMETLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_LAKEFIELD" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ROCKETLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT_L" ]; then
return 1
fi
fi
return 0 return 0
} }
+1 -49
View File
@@ -170,7 +170,7 @@ while [ -n "${1:-}" ]; do
case "$2" in case "$2" in
help) help)
echo "The following parameters are supported for --variant (can be used multiple times):" echo "The following parameters are supported for --variant (can be used multiple times):"
echo "1, 2, 3, 3a, 4, msbds, mfbds, mlpds, mdsum, l1tf, taa, mcepsc, srbds, mmio, sbdr, sbds, drpw, div0, fpdss, zenbleed, downfall, retbleed, inception, reptar, rfds, tsa, tsa-sq, tsa-l1, its, vmscape, bpi, sls, arm-spec-at, arm-spec-unpriv-load, arm-ssbs-nosync" echo "1, 2, 3, 3a, 4, msbds, mfbds, mlpds, mdsum, l1tf, taa, mcepsc, srbds, mmio, sbdr, sbds, drpw, div0, fpdss, zenbleed, downfall, retbleed, inception, reptar, rfds, tsa, tsa-sq, tsa-l1, its, vmscape, bpi, sls"
exit 0 exit 0
;; ;;
1) 1)
@@ -301,60 +301,12 @@ while [ -n "${1:-}" ]; do
opt_cve_list="$opt_cve_list CVE-0000-0001" opt_cve_list="$opt_cve_list CVE-0000-0001"
opt_cve_all=0 opt_cve_all=0
;; ;;
arm-spec-at)
opt_cve_list="$opt_cve_list CVE-0001-0001"
opt_cve_all=0
;;
arm-spec-unpriv-load)
opt_cve_list="$opt_cve_list CVE-0001-0002"
opt_cve_all=0
;;
arm-ssbs-nosync)
opt_cve_list="$opt_cve_list CVE-0001-0003"
opt_cve_all=0
;;
*) *)
echo "$0: error: invalid parameter '$2' for --variant, see --variant help for a list" >&2 echo "$0: error: invalid parameter '$2' for --variant, see --variant help for a list" >&2
exit 255 exit 255
;; ;;
esac esac
shift 2 shift 2
elif [ "$1" = "--errata" ]; then
# Vendor-numbered errata selector (currently ARM64). Maps an erratum number
# (e.g. 1530923) to the CVE-0001-NNNN check that covers it.
if [ -z "$2" ]; then
echo "$0: error: option --errata expects a parameter (an erratum number, e.g. 1530923, or 'help')" >&2
exit 255
fi
case "$2" in
help)
echo "The following erratum numbers are supported for --errata (can be used multiple times):"
echo " Speculative AT TLB corruption: 1165522, 1319367, 1319537, 1530923"
echo " Speculative unprivileged load: 2966298, 3117295"
echo " MSR SSBS not self-synchronizing: 3194386 (and siblings: 3312417, 3324334, 3324335,"
echo " 3324336, 3324338, 3324339, 3324341, 3324344, 3324346,"
echo " 3324347, 3324348, 3324349, 3456084, 3456091, 3456106,"
echo " 3456111)"
exit 0
;;
1165522 | 1319367 | 1319537 | 1530923)
opt_cve_list="$opt_cve_list CVE-0001-0001"
opt_cve_all=0
;;
2966298 | 3117295)
opt_cve_list="$opt_cve_list CVE-0001-0002"
opt_cve_all=0
;;
3194386 | 3312417 | 3324334 | 3324335 | 3324336 | 3324338 | 3324339 | 3324341 | 3324344 | 3324346 | 3324347 | 3324348 | 3324349 | 3456084 | 3456091 | 3456106 | 3456111)
opt_cve_list="$opt_cve_list CVE-0001-0003"
opt_cve_all=0
;;
*)
echo "$0: error: unsupported erratum number '$2' for --errata, see --errata help for a list" >&2
exit 255
;;
esac
shift 2
elif [ "$1" = "-h" ] || [ "$1" = "--help" ]; then elif [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
show_header show_header
show_usage show_usage
+4 -8
View File
@@ -110,8 +110,7 @@ _build_json_system() {
1) smt_val='false' ;; 1) smt_val='false' ;;
*) smt_val='null' ;; *) smt_val='null' ;;
esac esac
is_running_as_guest || true g_json_system=$(printf '{"kernel_release":%s,"kernel_version":%s,"kernel_arch":%s,"kernel_image":%s,"kernel_config":%s,"kernel_version_string":%s,"kernel_cmdline":%s,"cpu_count":%s,"smt_enabled":%s,"hypervisor_host":%s,"hypervisor_host_reason":%s}' \
g_json_system=$(printf '{"kernel_release":%s,"kernel_version":%s,"kernel_arch":%s,"kernel_image":%s,"kernel_config":%s,"kernel_version_string":%s,"kernel_cmdline":%s,"cpu_count":%s,"smt_enabled":%s,"hypervisor_host":%s,"hypervisor_host_reason":%s,"guest_vm":%s,"guest_vm_reason":%s}' \
"$(_json_str "$kernel_release")" \ "$(_json_str "$kernel_release")" \
"$(_json_str "$kernel_version")" \ "$(_json_str "$kernel_version")" \
"$(_json_str "$kernel_arch")" \ "$(_json_str "$kernel_arch")" \
@@ -122,9 +121,7 @@ _build_json_system() {
"$(_json_num "${g_max_core_id:+$((g_max_core_id + 1))}")" \ "$(_json_num "${g_max_core_id:+$((g_max_core_id + 1))}")" \
"$smt_val" \ "$smt_val" \
"$(_json_bool "${g_has_vmm:-}")" \ "$(_json_bool "${g_has_vmm:-}")" \
"$(_json_str "${g_has_vmm_reason:-}")" \ "$(_json_str "${g_has_vmm_reason:-}")")
"$(_json_bool "${g_is_guest_vm:-}")" \
"$(_json_str "${g_is_guest_vm_reason:-}")")
} }
# Build the "cpu" section of the comprehensive JSON output # Build the "cpu" section of the comprehensive JSON output
@@ -265,15 +262,14 @@ _build_json_cpu_microcode() {
blacklisted='false' blacklisted='false'
fi fi
latest_hex="${ret_is_latest_known_ucode_version:-}" latest_hex="${ret_is_latest_known_ucode_version:-}"
g_json_cpu_microcode=$(printf '{"installed_version":%s,"latest_version":%s,"microcode_up_to_date":%s,"is_blacklisted":%s,"message":%s,"db_source":%s,"db_info":%s,"unreliable_in_vm":%s}' \ g_json_cpu_microcode=$(printf '{"installed_version":%s,"latest_version":%s,"microcode_up_to_date":%s,"is_blacklisted":%s,"message":%s,"db_source":%s,"db_info":%s}' \
"$(_json_str "$ucode_hex")" \ "$(_json_str "$ucode_hex")" \
"$(_json_str "$latest_hex")" \ "$(_json_str "$latest_hex")" \
"$ucode_uptodate" \ "$ucode_uptodate" \
"$blacklisted" \ "$blacklisted" \
"$(_json_str "${ret_is_latest_known_ucode_latest:-}")" \ "$(_json_str "${ret_is_latest_known_ucode_latest:-}")" \
"$(_json_str "${g_mcedb_source:-}")" \ "$(_json_str "${g_mcedb_source:-}")" \
"$(_json_str "${g_mcedb_info:-}")" \ "$(_json_str "${g_mcedb_info:-}")")
"$(_json_bool "${g_is_guest_vm:-}")")
} }
# --- Format-specific batch emitters --- # --- Format-specific batch emitters ---
+1 -7
View File
@@ -9,7 +9,7 @@ dmesg_grep() {
# dmesg truncated # dmesg truncated
return 2 return 2
fi fi
ret_dmesg_grep_grepped=$(dmesg 2>/dev/null | grep -m 1 -E "$1") ret_dmesg_grep_grepped=$(dmesg 2>/dev/null | grep -E "$1" | head -n1)
# not found: # not found:
[ -z "$ret_dmesg_grep_grepped" ] && return 1 [ -z "$ret_dmesg_grep_grepped" ] && return 1
# found, output is in $ret_dmesg_grep_grepped # found, output is in $ret_dmesg_grep_grepped
@@ -22,9 +22,3 @@ is_coreos() {
command -v coreos-install >/dev/null 2>&1 && command -v toolbox >/dev/null 2>&1 && return 0 command -v coreos-install >/dev/null 2>&1 && command -v toolbox >/dev/null 2>&1 && return 0
return 1 return 1
} }
# Check whether /proc/cpuinfo has $1 in the flags line
# Returns: 0 if flag found, 1 otherwise
cpuinfo_has_flag() {
grep -Eq '^flags\b.+\b'"$1"'\b' "$g_procfs/cpuinfo" 2>/dev/null
}
+7 -23
View File
@@ -20,33 +20,17 @@ parse_cpu_details() {
cap_avx2=0 cap_avx2=0
cap_avx512=0 cap_avx512=0
if [ -e "$g_procfs/cpuinfo" ]; then if [ -e "$g_procfs/cpuinfo" ]; then
if cpuinfo_has_flag avx2; then cap_avx2=1; fi if grep -qw avx2 "$g_procfs/cpuinfo" 2>/dev/null; then cap_avx2=1; fi
if cpuinfo_has_flag avx512; then cap_avx512=1; fi if grep -qw avx512 "$g_procfs/cpuinfo" 2>/dev/null; then cap_avx512=1; fi
cpu_vendor=$(grep '^vendor_id' "$g_procfs/cpuinfo" | awk '{print $3}' | head -n1) cpu_vendor=$(grep '^vendor_id' "$g_procfs/cpuinfo" | awk '{print $3}' | head -n1)
cpu_friendly_name=$(grep '^model name' "$g_procfs/cpuinfo" | cut -d: -f2- | head -n1 | sed -e 's/^ *//') cpu_friendly_name=$(grep '^model name' "$g_procfs/cpuinfo" | cut -d: -f2- | head -n1 | sed -e 's/^ *//')
# ARM-style cpuinfo: parse per-core implementer/part/arch/variant/revision lists # special case for ARM follows
# (big.LITTLE / heterogeneous systems have different values per core).
# cpu_variant_list and cpu_revision_list are consumed by ARM64 errata affection checks
# that need to match a specific revision range.
if grep -q 'CPU implementer' "$g_procfs/cpuinfo"; then
# keep these single-line (space-separated) so consumers and outputs (JSON, prometheus)
# don't end up with embedded newlines; per-core order is preserved for the errata checks
cpu_impl_list=$(awk '/CPU implementer/ {print $4}' "$g_procfs/cpuinfo" | tr '\n' ' ')
cpu_impl_list=${cpu_impl_list% }
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
# 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
# per-core vendor decisions are made via cpu_impl_list where needed.
if grep -qi 'CPU implementer[[:space:]]*:[[:space:]]*0x41' "$g_procfs/cpuinfo"; then if grep -qi 'CPU implementer[[:space:]]*:[[:space:]]*0x41' "$g_procfs/cpuinfo"; then
cpu_vendor='ARM' cpu_vendor='ARM'
# some devices (phones or other) have several ARMs and as such different part numbers,
# an example is "bigLITTLE", so we need to store the whole list, this is needed for is_cpu_affected
cpu_part_list=$(awk '/CPU part/ {print $4}' "$g_procfs/cpuinfo")
cpu_arch_list=$(awk '/CPU architecture/ {print $3}' "$g_procfs/cpuinfo")
# take the first one to fill the friendly name, do NOT quote the vars below # take the first one to fill the friendly name, do NOT quote the vars below
# shellcheck disable=SC2086 # shellcheck disable=SC2086
arch=$(echo $cpu_arch_list | awk '{ print $1 }') arch=$(echo $cpu_arch_list | awk '{ print $1 }')
+25 -112
View File
@@ -1,39 +1,23 @@
# 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
# Probe Xen presence and guest type using the most reliable sources available. # Returns: 0 if Xen PV, 1 otherwise
# Prefer /sys/hypervisor when avalable, fallback to dmesg otherwise.
# Caches results in g_xen (1/0) and g_xen_guest_type (PV|PVH|HVM|'').
_detect_xen() {
[ "${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
# Fallback for kernels without /sys/hypervisor: /proc/xen plus a dmesg probe.
if [ -d "$g_procfs/xen" ]; then
dmesg_grep 'Booting paravirtualized kernel on Xen$'
case $? in
0) g_xen=1 ;;
2) pr_warn "dmesg truncated, Xen detection will be unreliable. Please reboot and relaunch this script" ;;
esac
fi
}
# Check whether the system is running on Xen (any domain type, dom0 included).
# Returns: 0 if Xen, 1 otherwise
is_xen() { is_xen() {
_detect_xen local ret
[ "$g_xen" = 1 ] if [ ! -d "$g_procfs/xen" ]; then
return 1
fi
# XXX do we have a better way that relying on dmesg?
dmesg_grep 'Booting paravirtualized kernel on Xen$'
ret=$?
if [ "$ret" -eq 2 ]; then
pr_warn "dmesg truncated, Xen detection will be unreliable. Please reboot and relaunch this script"
return 1
elif [ "$ret" -eq 0 ]; then
return 0
else
return 1
fi
} }
# Check whether the system is a Xen Dom0 (privileged domain) # Check whether the system is a Xen Dom0 (privileged domain)
@@ -50,95 +34,24 @@ is_xen_dom0() {
fi fi
} }
# Check whether the system is running as a Xen PV DomU (the only Xen guest type # Check whether the system is a Xen DomU (unprivileged PV guest)
# affected by Meltdown, which needs Xen-level mitigation). # Returns: 0 if DomU, 1 otherwise
# 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
if is_xen_dom0; then # PVHVM guests also print 'Booting paravirtualized kernel', so we need this check.
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
return 0 if ! is_xen_dom0; then
} return 0
else
# Check whether we're running inside an OS-level container (LXC, Docker, return 1
# 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 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,
# 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
# Sets: g_is_guest_vm (1=guest, 0=not a guest), g_is_guest_vm_reason
is_running_as_guest() {
if [ "${g_is_guest_vm_cached:-0}" != 1 ]; then
g_is_guest_vm=0
g_is_guest_vm_reason=''
if [ -e "$g_procfs/cpuinfo" ] && grep -qw 'hypervisor' "$g_procfs/cpuinfo" 2>/dev/null; then
g_is_guest_vm=1
g_is_guest_vm_reason="'hypervisor' flag in $g_procfs/cpuinfo"
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
fi
[ "$g_is_guest_vm" = 1 ]
} }
+10 -105
View File
@@ -384,56 +384,10 @@ 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
if is_arm_cpu; then
pr_info "* CPU details"
pr_info " * Vendor: $cpu_vendor"
pr_info " * Model name: $cpu_friendly_name"
if [ -n "${cpu_impl_list:-}" ]; then
pr_info " * Implementer(s): $(_uniq_list "$cpu_impl_list")"
fi
if [ -n "${cpu_part_list:-}" ]; then
pr_info " * Part(s): $(_uniq_list "$cpu_part_list")"
fi
if [ -n "${cpu_arch_list:-}" ]; then
pr_info " * Architecture(s): $(_uniq_list "$cpu_arch_list")"
fi
if has_runtime; then
pr_info_nol " * Running as VM guest: "
if is_running_as_guest; then
pstatus yellow YES "$g_is_guest_vm_reason"
else
pstatus green NO
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
fi
if ! uname -m | grep -qwE 'x86_64|i[3-6]86|amd64'; then if ! uname -m | grep -qwE 'x86_64|i[3-6]86|amd64'; then
return return
fi fi
@@ -462,15 +416,6 @@ check_cpu() {
fi fi
fi fi
if has_runtime; then
pr_info_nol " * Running as VM guest: "
if is_running_as_guest; then
pstatus yellow YES "$g_is_guest_vm_reason"
else
pstatus green NO
fi
fi
pr_info "* Hardware support (CPU microcode) for mitigation techniques" pr_info "* Hardware support (CPU microcode) for mitigation techniques"
pr_info " * Indirect Branch Restricted Speculation (IBRS)" pr_info " * Indirect Branch Restricted Speculation (IBRS)"
pr_info_nol " * SPEC_CTRL MSR is available: " pr_info_nol " * SPEC_CTRL MSR is available: "
@@ -513,7 +458,7 @@ check_cpu() {
fi fi
if [ -z "$cap_ibrs" ] && [ $ret = $READ_CPUID_RET_ERR ] && has_runtime; then if [ -z "$cap_ibrs" ] && [ $ret = $READ_CPUID_RET_ERR ] && has_runtime; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
if cpuinfo_has_flag ibrs; then if grep ^flags "$g_procfs/cpuinfo" | grep -qw ibrs; then
cap_ibrs='IBRS (cpuinfo)' cap_ibrs='IBRS (cpuinfo)'
cap_spec_ctrl=1 cap_spec_ctrl=1
pstatus green YES "ibrs flag in $g_procfs/cpuinfo" pstatus green YES "ibrs flag in $g_procfs/cpuinfo"
@@ -588,7 +533,7 @@ check_cpu() {
if [ $ret = $READ_CPUID_RET_OK ]; then if [ $ret = $READ_CPUID_RET_OK ]; then
cap_ibpb='IBPB_SUPPORT' cap_ibpb='IBPB_SUPPORT'
pstatus green YES "IBPB_SUPPORT feature bit" pstatus green YES "IBPB_SUPPORT feature bit"
elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && cpuinfo_has_flag ibpb; then elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && grep ^flags "$g_procfs/cpuinfo" | grep -qw ibpb; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
cap_ibpb='IBPB (cpuinfo)' cap_ibpb='IBPB (cpuinfo)'
pstatus green YES "ibpb flag in $g_procfs/cpuinfo" pstatus green YES "ibpb flag in $g_procfs/cpuinfo"
@@ -661,7 +606,7 @@ check_cpu() {
fi fi
if [ -z "$cap_stibp" ] && [ $ret = $READ_CPUID_RET_ERR ] && has_runtime; then if [ -z "$cap_stibp" ] && [ $ret = $READ_CPUID_RET_ERR ] && has_runtime; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
if cpuinfo_has_flag stibp; then if grep ^flags "$g_procfs/cpuinfo" | grep -qw stibp; then
cap_stibp='STIBP (cpuinfo)' cap_stibp='STIBP (cpuinfo)'
pstatus green YES "stibp flag in $g_procfs/cpuinfo" pstatus green YES "stibp flag in $g_procfs/cpuinfo"
ret=$READ_CPUID_RET_OK ret=$READ_CPUID_RET_OK
@@ -733,9 +678,9 @@ check_cpu() {
if [ -z "$cap_ssbd" ] && [ "$ret24" = $READ_CPUID_RET_ERR ] && [ "$ret25" = $READ_CPUID_RET_ERR ] && has_runtime; then if [ -z "$cap_ssbd" ] && [ "$ret24" = $READ_CPUID_RET_ERR ] && [ "$ret25" = $READ_CPUID_RET_ERR ] && has_runtime; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
if cpuinfo_has_flag ssbd; then if grep ^flags "$g_procfs/cpuinfo" | grep -qw ssbd; then
cap_ssbd='SSBD (cpuinfo)' cap_ssbd='SSBD (cpuinfo)'
elif cpuinfo_has_flag virt_ssbd; then elif grep ^flags "$g_procfs/cpuinfo" | grep -qw virt_ssbd; then
cap_ssbd='SSBD in VIRT_SPEC_CTRL (cpuinfo)' cap_ssbd='SSBD in VIRT_SPEC_CTRL (cpuinfo)'
fi fi
fi fi
@@ -795,7 +740,7 @@ check_cpu() {
if [ $ret = $READ_CPUID_RET_OK ]; then if [ $ret = $READ_CPUID_RET_OK ]; then
pstatus green YES "L1D flush feature bit" pstatus green YES "L1D flush feature bit"
cap_l1df=1 cap_l1df=1
elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && cpuinfo_has_flag flush_l1d; then elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && grep ^flags "$g_procfs/cpuinfo" | grep -qw flush_l1d; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
pstatus green YES "flush_l1d flag in $g_procfs/cpuinfo" pstatus green YES "flush_l1d flag in $g_procfs/cpuinfo"
cap_l1df=1 cap_l1df=1
@@ -815,7 +760,7 @@ check_cpu() {
if [ $ret = $READ_CPUID_RET_OK ]; then if [ $ret = $READ_CPUID_RET_OK ]; then
cap_md_clear=1 cap_md_clear=1
pstatus green YES "MD_CLEAR feature bit" pstatus green YES "MD_CLEAR feature bit"
elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && cpuinfo_has_flag md_clear; then elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && grep ^flags "$g_procfs/cpuinfo" | grep -qw md_clear; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
cap_md_clear=1 cap_md_clear=1
pstatus green YES "md_clear flag in $g_procfs/cpuinfo" pstatus green YES "md_clear flag in $g_procfs/cpuinfo"
@@ -885,7 +830,7 @@ check_cpu() {
if [ $ret = $READ_CPUID_RET_OK ]; then if [ $ret = $READ_CPUID_RET_OK ]; then
pstatus green YES pstatus green YES
cap_arch_capabilities=1 cap_arch_capabilities=1
elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && cpuinfo_has_flag arch_capabilities; then elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && grep ^flags "$g_procfs/cpuinfo" | grep -qw arch_capabilities; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
pstatus green YES "arch_capabilities flag in $g_procfs/cpuinfo" pstatus green YES "arch_capabilities flag in $g_procfs/cpuinfo"
cap_arch_capabilities=1 cap_arch_capabilities=1
@@ -987,33 +932,8 @@ check_cpu() {
pstatus yellow NO pstatus yellow NO
fi fi
elif [ $ret = $READ_MSR_RET_KO ]; then elif [ $ret = $READ_MSR_RET_KO ]; then
# the MSR access faulted: the register is genuinely absent, so the
# pre-seeded 0 ("not advertised") values are correct.
pstatus yellow NO pstatus yellow NO
else else
# RET_ERR (no msr module) or RET_LOCKDOWN (MSR reads restricted):
# CPUID told us the MSR exists but we couldn't read it, so its bits
# are undetermined, not 0. Leaving them at 0 would falsely claim the
# CPU "explicitly indicates not immune".
# Reset every arch-cap-derived value to -1 (UNKNOWN) instead.
cap_rdcl_no=-1
cap_taa_no=-1
cap_mds_no=-1
cap_ibrs_all=-1
cap_rsba=-1
cap_l1dflush_no=-1
cap_ssb_no=-1
cap_pschange_msc_no=-1
cap_tsx_ctrl_msr=-1
cap_gds_ctrl=-1
cap_gds_no=-1
cap_rfds_no=-1
cap_rfds_clear=-1
cap_its_no=-1
cap_sbdr_ssdp_no=-1
cap_fbsdp_no=-1
cap_psdp_no=-1
cap_fb_clear=-1
pstatus yellow UNKNOWN "$ret_read_msr_msg" pstatus yellow UNKNOWN "$ret_read_msr_msg"
fi fi
fi fi
@@ -1173,7 +1093,7 @@ check_cpu() {
pr_info_nol " * CPU explicitly indicates not being affected by MMIO Stale Data (FBSDP_NO & PSDP_NO & SBDR_SSDP_NO): " pr_info_nol " * CPU explicitly indicates not being affected by MMIO Stale Data (FBSDP_NO & PSDP_NO & SBDR_SSDP_NO): "
if [ "$cap_sbdr_ssdp_no" = -1 ]; then if [ "$cap_sbdr_ssdp_no" = -1 ]; then
pstatus yellow UNKNOWN "couldn't read MSR" pstatus yellow UNKNOWN "couldn't read MSR"
elif is_arch_cap_mmio_immune; then elif [ "$cap_sbdr_ssdp_no" = 1 ] && [ "$cap_fbsdp_no" = 1 ] && [ "$cap_psdp_no" = 1 ]; then
pstatus green YES pstatus green YES
else else
pstatus yellow NO pstatus yellow NO
@@ -1445,28 +1365,13 @@ check_cpu() {
else else
pstatus blue UNKNOWN "$ret_is_latest_known_ucode_latest" pstatus blue UNKNOWN "$ret_is_latest_known_ucode_latest"
fi fi
if is_running_as_guest; then
pr_warn
pr_warn "Note: this system is running inside a VM ($g_is_guest_vm_reason)."
pr_warn "The hypervisor may be faking the CPU model and microcode version;"
pr_warn "verify the above microcode information on the hypervisor host for accuracy."
pr_warn
fi
} }
# Display per-CVE CPU vulnerability status based on CPU model/family. # Display per-CVE CPU vulnerability status based on CPU model/family
# Mirrors the main dispatch gate: under a default "all CVEs" run, skip CVEs
# whose arch tag doesn't match this system. Explicit selection via
# --cve/--variant/--errata bypasses the gate.
check_cpu_vulnerabilities() { check_cpu_vulnerabilities() {
local cve local cve
pr_info "* CPU vulnerability to the speculative execution attack variants" pr_info "* CPU vulnerability to the speculative execution attack variants"
for cve in $g_supported_cve_list; do for cve in $g_supported_cve_list; do
if [ "$opt_cve_all" = 1 ]; then
_is_cve_relevant_arch "$cve" || continue
elif ! echo "$opt_cve_list" | grep -qw "$cve"; then
continue
fi
pr_info_nol " * Affected by $cve ($(cve2name "$cve")): " pr_info_nol " * Affected by $cve ($(cve2name "$cve")): "
if is_cpu_affected "$cve"; then if is_cpu_affected "$cve"; then
pstatus yellow YES pstatus yellow YES
+3 -12
View File
@@ -43,19 +43,10 @@ if [ "$g_mode" = hw-only ]; then
pr_info "Hardware-only mode, skipping vulnerability checks" pr_info "Hardware-only mode, skipping vulnerability checks"
else else
for cve in $g_supported_cve_list; do for cve in $g_supported_cve_list; do
# In a default "all CVEs" run, skip checks whose arch tag doesn't match if [ "$opt_cve_all" = 1 ] || echo "$opt_cve_list" | grep -qw "$cve"; then
# the host CPU or the inspected kernel. Explicit --cve/--variant/--errata check_"$(echo "$cve" | tr - _)"
# selection bypasses the gate. pr_info
if [ "$opt_cve_all" = 1 ]; then
if ! _is_cve_relevant_arch "$cve"; then
pr_debug "main: skipping $cve (arch tag not relevant)"
continue
fi
elif ! echo "$opt_cve_list" | grep -qw "$cve"; then
continue
fi fi
check_"$(echo "$cve" | tr - _)"
pr_info
done done
fi # g_mode != hw-only fi # g_mode != hw-only
+1 -10
View File
@@ -138,7 +138,7 @@ check_mds_linux() {
if is_x86_kernel; then if is_x86_kernel; then
pr_info_nol "* Kernel supports using MD_CLEAR mitigation: " pr_info_nol "* Kernel supports using MD_CLEAR mitigation: "
kernel_md_clear_can_tell=1 kernel_md_clear_can_tell=1
if [ "$g_mode" = live ] && cpuinfo_has_flag md_clear; then if [ "$g_mode" = live ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw md_clear; then
kernel_md_clear="md_clear found in $g_procfs/cpuinfo" kernel_md_clear="md_clear found in $g_procfs/cpuinfo"
pstatus green YES "$kernel_md_clear" pstatus green YES "$kernel_md_clear"
fi fi
@@ -174,12 +174,6 @@ 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
@@ -206,9 +200,6 @@ 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"
+3 -97
View File
@@ -1,37 +1,16 @@
# vim: set ts=4 sw=4 sts=4 et: # vim: set ts=4 sw=4 sts=4 et:
# MMIO Stale Data (Processor MMIO Stale Data Vulnerabilities) - BSD mitigation check # MMIO Stale Data (Processor MMIO Stale Data Vulnerabilities) - BSD mitigation check
check_mmio_bsd() { check_mmio_bsd() {
# No BSD (FreeBSD, OpenBSD, NetBSD, DragonFlyBSD) has implemented an OS-level
# MMIO Stale Data mitigation. All four stopped at MDS/TAA. Microcode update is
# the only partial defense available, and without OS-level VERW invocation it
# cannot close the vulnerability.
local unk
if ! is_cpu_affected "$cve"; then if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected" pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif is_cpu_mmio_unknown; then
if is_arch_cap_mmio_undetermined; then
# We only landed in the "unknown" bucket because the IA32_ARCH_CAPABILITIES
# MSR couldn't be read: the CPU might actually advertise MMIO immunity.
unk="your CPU's MMIO Stale Data status could not be determined: the IA32_ARCH_CAPABILITIES MSR (0x10a) couldn't be read"
pvulnstatus "$cve" UNK "$unk; load the cpuctl module and/or re-run as root to get a definitive answer"
else
unk="your CPU's MMIO Stale Data status is unknown (Intel never officially assessed this CPU, its servicing period has ended)"
if [ "$opt_paranoid" = 1 ]; then
pvulnstatus "$cve" VULN "$unk, and no BSD mitigation exists"
explain "There is no known mitigation for this CPU model. Even with up-to-date microcode, BSD kernels do not invoke VERW for MMIO Stale Data clearing. Only a hardware replacement can fully address this."
else
pvulnstatus "$cve" UNK "$unk; no BSD mitigation exists in any case"
fi
fi
else else
pvulnstatus "$cve" VULN "your CPU is affected and no BSD has implemented an MMIO Stale Data mitigation" pvulnstatus "$cve" UNK "your CPU is affected, but mitigation detection has not yet been implemented for BSD in this script"
explain "No BSD kernel currently implements an MMIO Stale Data mitigation (which would require invoking VERW at context switches and VM-entries). Updating CPU microcode alone does not mitigate this vulnerability without OS cooperation."
fi fi
} }
# MMIO Stale Data (Processor MMIO Stale Data Vulnerabilities) - Linux mitigation check # MMIO Stale Data (Processor MMIO Stale Data Vulnerabilities) - Linux mitigation check
check_mmio_linux() { check_mmio_linux() {
local status sys_interface_available msg kernel_mmio kernel_mmio_can_tell kernel_mmio_unknown_aware mmio_mitigated mmio_smt_mitigated mystatus mymsg unk local status sys_interface_available msg kernel_mmio kernel_mmio_can_tell mmio_mitigated mmio_smt_mitigated mystatus mymsg
status=UNK status=UNK
sys_interface_available=0 sys_interface_available=0
msg='' msg=''
@@ -133,33 +112,9 @@ check_mmio_linux() {
# #
# No models have been added to or removed from the MMIO blacklist since v5.19. # No models have been added to or removed from the MMIO blacklist since v5.19.
# #
# 7df548840c49 (v6.0, NO_MMIO whitelist added, Pawan Gupta 2022-08-03):
# Intel Family 6:
# TIGERLAKE (0x8D), TIGERLAKE_L (0x8C)
# ALDERLAKE (0x97), ALDERLAKE_L (0x9A)
# ATOM_GOLDMONT (0x5C), ATOM_GOLDMONT_D (0x5F), ATOM_GOLDMONT_PLUS (0x7A)
# AMD: fam 0x0f-0x12 + X86_FAMILY_ANY (all families)
# Hygon: all families
# Centaur fam 7, Zhaoxin fam 7
#
# Kernel logic (v6.0+):
# if (!arch_cap_mmio_immune(ia32_cap)) {
# if (cpu_matches(cpu_vuln_blacklist, MMIO))
# setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
# else if (!cpu_matches(cpu_vuln_whitelist, NO_MMIO))
# setup_force_cpu_bug(X86_BUG_MMIO_UNKNOWN);
# }
# => Intel CPUs that are neither blacklisted nor whitelisted (e.g. Ivy Bridge,
# Haswell client, Broadwell client, Sandy Bridge, pre-Goldmont Atom, etc.) get
# X86_BUG_MMIO_UNKNOWN and report "Unknown: No mitigations" in sysfs. Intel
# never published an affected-processor evaluation for these models because
# their servicing period had already ended.
# => is_cpu_mmio_unknown() matches this set so the script can report UNK (or
# VULN under --paranoid) rather than the misleading "not affected" that
# a plain blacklist check would produce.
#
# immunity: ARCH_CAP_SBDR_SSDP_NO (bit 13) AND ARCH_CAP_FBSDP_NO (bit 14) AND ARCH_CAP_PSDP_NO (bit 15) # immunity: ARCH_CAP_SBDR_SSDP_NO (bit 13) AND ARCH_CAP_FBSDP_NO (bit 14) AND ARCH_CAP_PSDP_NO (bit 15)
# All three must be set. Checked via arch_cap_mmio_immune() in common.c. # All three must be set. Checked via arch_cap_mmio_immune() in common.c.
# Bug is set only when: cpu_matches(blacklist, MMIO) AND NOT arch_cap_mmio_immune().
# #
# microcode mitigation: ARCH_CAP_FB_CLEAR (bit 17) -- VERW clears fill buffers. # microcode mitigation: ARCH_CAP_FB_CLEAR (bit 17) -- VERW clears fill buffers.
# Alternative: MD_CLEAR CPUID + FLUSH_L1D CPUID when MDS_NO is not set (legacy path). # Alternative: MD_CLEAR CPUID + FLUSH_L1D CPUID when MDS_NO is not set (legacy path).
@@ -173,11 +128,6 @@ check_mmio_linux() {
# MMIO Stale Data is Intel-only; skip x86-specific kernel/MSR checks on non-x86 kernels # MMIO Stale Data is Intel-only; skip x86-specific kernel/MSR checks on non-x86 kernels
kernel_mmio='' kernel_mmio=''
kernel_mmio_can_tell=0 kernel_mmio_can_tell=0
# Whether this kernel implements the X86_BUG_MMIO_UNKNOWN distinction, i.e. can
# report "Unknown: No mitigations" for CPUs Intel never assessed. Only such kernels
# emit a *trustworthy* "Not affected": they would have said "Unknown" instead if the
# CPU were in the unknown bucket. Detected by the presence of the literal sysfs string in the kernel image.
kernel_mmio_unknown_aware=0
if is_x86_kernel; then if is_x86_kernel; then
pr_info_nol "* Kernel supports MMIO Stale Data mitigation: " pr_info_nol "* Kernel supports MMIO Stale Data mitigation: "
kernel_mmio_can_tell=1 kernel_mmio_can_tell=1
@@ -188,10 +138,6 @@ check_mmio_linux() {
kernel_mmio='found MMIO Stale Data mitigation evidence in kernel image' kernel_mmio='found MMIO Stale Data mitigation evidence in kernel image'
pstatus green YES "$kernel_mmio" pstatus green YES "$kernel_mmio"
fi fi
if [ -z "$g_kernel_err" ] && grep -qF 'Unknown: No mitigations' "$g_kernel" 2>/dev/null; then
pr_debug "mmio: kernel image knows the 'Unknown: No mitigations' state (X86_BUG_MMIO_UNKNOWN-aware)"
kernel_mmio_unknown_aware=1
fi
if [ -z "$kernel_mmio" ] && [ -n "$opt_config" ] && grep -q '^CONFIG_MITIGATION_MMIO_STALE_DATA=y' "$opt_config"; then if [ -z "$kernel_mmio" ] && [ -n "$opt_config" ] && grep -q '^CONFIG_MITIGATION_MMIO_STALE_DATA=y' "$opt_config"; then
kernel_mmio='found MMIO Stale Data mitigation config option enabled' kernel_mmio='found MMIO Stale Data mitigation config option enabled'
pstatus green YES "$kernel_mmio" pstatus green YES "$kernel_mmio"
@@ -232,12 +178,6 @@ 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,37 +193,6 @@ check_mmio_linux() {
if ! is_cpu_affected "$cve"; then if ! is_cpu_affected "$cve"; then
# override status & msg in case CPU is not vulnerable after all # override status & msg in case CPU is not vulnerable after all
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected" pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif [ "$opt_sysfs_only" != 1 ] && is_cpu_mmio_unknown; then
# Bypass the normal sysfs reconciliation: sysfs reports "Unknown: No mitigations"
# only on v6.0-v6.15. On earlier and on v6.16+ kernels it wrongly says "Not affected"
# for these CPUs (which predate FB_CLEAR microcode and Intel's affected-processor list).
if is_arch_cap_mmio_undetermined; then
# We landed in the "unknown" bucket only because the IA32_ARCH_CAPABILITIES
# MSR couldn't be read from userspace (no msr module, or kernel lockdown under
# Secure Boot): the CPU might actually advertise MMIO immunity
# through FBSDP_NO/PSDP_NO/SBDR_SSDP_NO, but we can't read it, however the kernel can.
#
# We can trust a sysfs "Not affected" only if this kernel is X86_BUG_MMIO_UNKNOWN-aware:
# such a kernel would have reported "Unknown: No mitigations" instead if the CPU were in
# the unknown bucket, so "Not affected" genuinely means arch-cap immune.
# On kernels that lack that distinction, a "Not affected" is not trustworthy for these CPUs,
# so we keep UNK.
if [ "$g_mode" = live ] && [ "$sys_interface_available" = 1 ] &&
[ "$kernel_mmio_unknown_aware" = 1 ] && [ "$status" = OK ]; then
pvulnstatus "$cve" OK "your kernel reports your CPU as not affected, and this kernel distinguishes the MMIO 'unknown' state, so its verdict is trustworthy (we couldn't read the IA32_ARCH_CAPABILITIES MSR ourselves)"
else
unk="your CPU's MMIO Stale Data status could not be determined: the IA32_ARCH_CAPABILITIES MSR (0x10a) couldn't be read"
pvulnstatus "$cve" UNK "$unk; load the msr module and/or disable kernel lockdown, then re-run as root to get a definitive answer"
fi
else
unk="your CPU's MMIO Stale Data status is unknown (Intel never officially assessed this CPU, its servicing period has ended)"
if [ "$opt_paranoid" = 1 ]; then
pvulnstatus "$cve" VULN "$unk, and no mitigation is available"
explain "There is no known mitigation for this CPU model. Intel ended its servicing period without evaluating whether it is affected by MMIO Stale Data vulnerabilities, so no FB_CLEAR-capable microcode was released."
else
pvulnstatus "$cve" UNK "$unk; no mitigation is available in any case"
fi
fi
else else
if [ "$opt_sysfs_only" != 1 ]; then if [ "$opt_sysfs_only" != 1 ]; then
# compute mystatus and mymsg from our own logic # compute mystatus and mymsg from our own logic
@@ -295,9 +204,6 @@ 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"
-78
View File
@@ -1,78 +0,0 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-0001-0001, ARM SPEC AT, ARM64 errata 1165522/1319367/1319537/1530923, Speculative AT TLB corruption
check_CVE_0001_0001() {
check_cve 'CVE-0001-0001'
}
# On affected cores, a speculative address translation (AT) instruction issued from the hypervisor
# using an out-of-context translation regime may poison the TLB, causing a subsequent guest-context
# request to see an incorrect translation. Relevant mainly to KVM hosts. Kernel workaround:
# invalidate TLB state across world-switch for affected cores (ARM64_WORKAROUND_SPECULATIVE_AT).
# * Cortex-A76 r0p0..r2p0 erratum 1165522 CONFIG_ARM64_ERRATUM_1165522
# * Cortex-A72 all revs erratum 1319367 CONFIG_ARM64_ERRATUM_1319367
# * Cortex-A57 all revs erratum 1319537 CONFIG_ARM64_ERRATUM_1319367 (same kconfig)
# * Cortex-A55 r0p0..r2p0 erratum 1530923 CONFIG_ARM64_ERRATUM_1530923
# References:
# arch/arm64/Kconfig (ARM64_ERRATUM_{1165522,1319367,1530923})
# arch/arm64/kernel/cpu_errata.c (erratum_speculative_at_list, "ARM errata 1165522, 1319367, or 1530923")
# Cortex-A55 SDEN: https://developer.arm.com/documentation/SDEN-1301074/latest
check_CVE_0001_0001_linux() {
local cve kernel_mitigated config_found
cve='CVE-0001-0001'
kernel_mitigated=''
config_found=''
if [ "$opt_sysfs_only" != 1 ] && is_arm_kernel; then
# kconfig: any of the three erratum config options implies the workaround is compiled in
if [ -n "$opt_config" ]; then
for erratum in 1165522 1319367 1530923; do
if grep -q "^CONFIG_ARM64_ERRATUM_$erratum=y" "$opt_config"; then
config_found="${config_found:+$config_found, }$erratum"
fi
done
[ -n "$config_found" ] && kernel_mitigated="found CONFIG_ARM64_ERRATUM_$config_found=y in kernel config"
fi
# kernel image: look for the descriptor string the kernel prints at boot
if [ -z "$kernel_mitigated" ] && [ -n "$g_kernel" ]; then
if "${opt_arch_prefix}strings" "$g_kernel" 2>/dev/null | grep -qE 'ARM errata 1165522, 1319367'; then
kernel_mitigated="found erratum descriptor string in kernel image"
fi
fi
# live mode: dmesg prints the workaround once at boot
if [ -z "$kernel_mitigated" ] && [ "$g_mode" = live ]; then
if dmesg 2>/dev/null | grep -qE 'ARM errata 1165522, 1319367'; then
kernel_mitigated="erratum workaround reported as applied in dmesg"
fi
fi
pr_info_nol "* Kernel has the ARM64 Speculative-AT workaround compiled in: "
if [ -n "$kernel_mitigated" ]; then
pstatus green YES "$kernel_mitigated"
else
pstatus yellow NO
fi
fi
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU is not affected by this erratum family"
elif [ "$opt_sysfs_only" = 1 ]; then
pvulnstatus "$cve" UNK "no sysfs interface exists for this erratum, own checks have been skipped (--sysfs-only)"
elif [ -n "$kernel_mitigated" ]; then
pvulnstatus "$cve" OK "your kernel includes the erratum workaround"
else
pvulnstatus "$cve" VULN "your CPU is affected by this erratum family and the kernel does not appear to include the workaround"
explain "Run a kernel built with CONFIG_ARM64_ERRATUM_1165522=y, CONFIG_ARM64_ERRATUM_1319367=y, and/or CONFIG_ARM64_ERRATUM_1530923=y (matching your CPU core). These options are 'default y' in mainline and enabled by most distro kernels. Refer to the ARM Software Developers Errata Notice for your core for full details."
fi
}
check_CVE_0001_0001_bsd() {
local cve
cve='CVE-0001-0001'
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU is not affected by this erratum family"
else
pvulnstatus "$cve" UNK "your CPU is affected, but mitigation detection has not yet been implemented for BSD in this script"
fi
}
-75
View File
@@ -1,75 +0,0 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-0001-0002, ARM SPEC UNPRIV LOAD, ARM64 errata 2966298/3117295, Speculative unprivileged load
check_CVE_0001_0002() {
check_cve 'CVE-0001-0002'
}
# On affected cores, a speculatively-executed unprivileged load from a page that is mapped as
# privileged can leak the loaded value into the cache hierarchy, allowing a Spectre-style
# cache side-channel to expose privileged kernel data to userspace. Kernel workaround:
# sandwich kernel-exit sequences with an additional speculation barrier/DSB so that
# speculative unprivileged loads cannot observe privileged state
# (ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD).
# * Cortex-A510 all revs erratum 3117295 CONFIG_ARM64_ERRATUM_3117295
# * Cortex-A520 r0p0..r0p1 erratum 2966298 CONFIG_ARM64_ERRATUM_2966298
# References:
# arch/arm64/Kconfig (ARM64_ERRATUM_{2966298,3117295})
# arch/arm64/kernel/cpu_errata.c (erratum_spec_unpriv_load_list, "ARM errata 2966298, 3117295")
# Cortex-A510 SDEN: https://developer.arm.com/documentation/SDEN-2397239/latest
check_CVE_0001_0002_linux() {
local cve kernel_mitigated config_found erratum
cve='CVE-0001-0002'
kernel_mitigated=''
config_found=''
if [ "$opt_sysfs_only" != 1 ] && is_arm_kernel; then
if [ -n "$opt_config" ]; then
for erratum in 2966298 3117295; do
if grep -q "^CONFIG_ARM64_ERRATUM_$erratum=y" "$opt_config"; then
config_found="${config_found:+$config_found, }$erratum"
fi
done
[ -n "$config_found" ] && kernel_mitigated="found CONFIG_ARM64_ERRATUM_$config_found=y in kernel config"
fi
if [ -z "$kernel_mitigated" ] && [ -n "$g_kernel" ]; then
if "${opt_arch_prefix}strings" "$g_kernel" 2>/dev/null | grep -qE 'ARM errata 2966298, 3117295'; then
kernel_mitigated="found erratum descriptor string in kernel image"
fi
fi
if [ -z "$kernel_mitigated" ] && [ "$g_mode" = live ]; then
if dmesg 2>/dev/null | grep -qE 'ARM errata 2966298, 3117295'; then
kernel_mitigated="erratum workaround reported as applied in dmesg"
fi
fi
pr_info_nol "* Kernel has the ARM64 Speculative-Unprivileged-Load workaround compiled in: "
if [ -n "$kernel_mitigated" ]; then
pstatus green YES "$kernel_mitigated"
else
pstatus yellow NO
fi
fi
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU is not affected by this erratum family"
elif [ "$opt_sysfs_only" = 1 ]; then
pvulnstatus "$cve" UNK "no sysfs interface exists for this erratum, own checks have been skipped (--sysfs-only)"
elif [ -n "$kernel_mitigated" ]; then
pvulnstatus "$cve" OK "your kernel includes the erratum workaround"
else
pvulnstatus "$cve" VULN "your CPU is affected by this erratum family and the kernel does not appear to include the workaround"
explain "Run a kernel built with CONFIG_ARM64_ERRATUM_2966298=y (Cortex-A520) and/or CONFIG_ARM64_ERRATUM_3117295=y (Cortex-A510). These options are 'default y' in mainline and enabled by most distro kernels. Refer to the ARM Software Developers Errata Notice for your core for full details."
fi
}
check_CVE_0001_0002_bsd() {
local cve
cve='CVE-0001-0002'
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU is not affected by this erratum family"
else
pvulnstatus "$cve" UNK "your CPU is affected, but mitigation detection has not yet been implemented for BSD in this script"
fi
}
-70
View File
@@ -1,70 +0,0 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-0001-0003, ARM SSBS NOSYNC, ARM64 erratum 3194386, MSR SSBS not self-synchronizing
check_CVE_0001_0003() {
check_cve 'CVE-0001-0003'
}
# On affected cores, the "MSR SSBS, #x" instruction is not self-synchronizing, so subsequent
# speculative instructions may execute without observing the new SSBS state. This can permit
# unintended speculative store bypass (Spectre V4 / CVE-2018-3639) even when software thinks
# the mitigation is in effect. Kernel workaround (ARM64_WORKAROUND_SPECULATIVE_SSBS):
# - place a Speculation Barrier (SB) or ISB after every kernel-side SSBS change
# - hide SSBS from userspace hwcaps and EL0 reads of ID_AA64PFR1_EL1 so that userspace
# routes SSB mitigation changes through the prctl(PR_SET_SPECULATION_CTRL) path
# Affected cores (via ARM64_ERRATUM_3194386, with individual sub-errata numbers):
# Cortex-A76/A77/A78/A78C/A710/A715/A720/A720AE/A725, X1/X1C/X2/X3/X4/X925,
# Neoverse-N1/N2/N3, Neoverse-V1/V2/V3/V3AE
# References:
# arch/arm64/Kconfig (ARM64_ERRATUM_3194386)
# arch/arm64/kernel/cpu_errata.c (erratum_spec_ssbs_list, "SSBS not fully self-synchronizing")
check_CVE_0001_0003_linux() {
local cve kernel_mitigated
cve='CVE-0001-0003'
kernel_mitigated=''
if [ "$opt_sysfs_only" != 1 ] && is_arm_kernel; then
if [ -n "$opt_config" ] && grep -q '^CONFIG_ARM64_ERRATUM_3194386=y' "$opt_config"; then
kernel_mitigated="found CONFIG_ARM64_ERRATUM_3194386=y in kernel config"
fi
if [ -z "$kernel_mitigated" ] && [ -n "$g_kernel" ]; then
if "${opt_arch_prefix}strings" "$g_kernel" 2>/dev/null | grep -qE 'SSBS not fully self-synchronizing'; then
kernel_mitigated="found erratum descriptor string in kernel image"
fi
fi
if [ -z "$kernel_mitigated" ] && [ "$g_mode" = live ]; then
if dmesg 2>/dev/null | grep -qE 'SSBS not fully self-synchronizing'; then
kernel_mitigated="erratum workaround reported as applied in dmesg"
fi
fi
pr_info_nol "* Kernel has the ARM64 SSBS self-sync workaround compiled in: "
if [ -n "$kernel_mitigated" ]; then
pstatus green YES "$kernel_mitigated"
else
pstatus yellow NO
fi
fi
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU is not affected by this erratum"
elif [ "$opt_sysfs_only" = 1 ]; then
pvulnstatus "$cve" UNK "no sysfs interface exists for this erratum, own checks have been skipped (--sysfs-only)"
elif [ -n "$kernel_mitigated" ]; then
pvulnstatus "$cve" OK "your kernel includes the erratum workaround"
else
pvulnstatus "$cve" VULN "your CPU is affected by this erratum and the kernel does not appear to include the workaround; Spectre V4 (CVE-2018-3639) mitigation may be unreliable on this system"
explain "Run a kernel built with CONFIG_ARM64_ERRATUM_3194386=y. This option is 'default y' in mainline and enabled by most distro kernels. Without it, the Spectre V4 / speculative-store-bypass mitigation advertised by SSBS is not reliably applied. Userspace should use prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, ...) to request the mitigation rather than rely on the SSBS hwcap."
fi
}
check_CVE_0001_0003_bsd() {
local cve
cve='CVE-0001-0003'
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU is not affected by this erratum"
else
pvulnstatus "$cve" UNK "your CPU is affected, but mitigation detection has not yet been implemented for BSD in this script"
fi
}
+1 -1
View File
@@ -306,7 +306,7 @@ check_CVE_2017_5715_linux() {
# which in that case means ibrs is supported *and* enabled for kernel & user # which in that case means ibrs is supported *and* enabled for kernel & user
# as per the ibrs patch series v3 # as per the ibrs patch series v3
if [ -z "$g_ibrs_supported" ]; then if [ -z "$g_ibrs_supported" ]; then
if cpuinfo_has_flag spec_ctrl_ibrs; then if grep ^flags "$g_procfs/cpuinfo" | grep -qw spec_ctrl_ibrs; then
pr_debug "ibrs: found spec_ctrl_ibrs flag in $g_procfs/cpuinfo" pr_debug "ibrs: found spec_ctrl_ibrs flag in $g_procfs/cpuinfo"
g_ibrs_supported="spec_ctrl_ibrs flag in $g_procfs/cpuinfo" g_ibrs_supported="spec_ctrl_ibrs flag in $g_procfs/cpuinfo"
# enabled=2 -> kernel & user # enabled=2 -> kernel & user
+9 -22
View File
@@ -11,7 +11,7 @@
pti_performance_check() { pti_performance_check() {
local ret pcid invpcid local ret pcid invpcid
pr_info_nol " * Reduced performance impact of PTI: " pr_info_nol " * Reduced performance impact of PTI: "
if cpuinfo_has_flag pcid; then if [ -e "$g_procfs/cpuinfo" ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw pcid; then
pcid=1 pcid=1
else else
read_cpuid 0x1 0x0 "$ECX" 17 1 1 read_cpuid 0x1 0x0 "$ECX" 17 1 1
@@ -21,7 +21,7 @@ pti_performance_check() {
fi fi
fi fi
if cpuinfo_has_flag invpcid; then if [ -e "$g_procfs/cpuinfo" ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw invpcid; then
invpcid=1 invpcid=1
else else
read_cpuid 0x7 0x0 "$EBX" 10 1 1 read_cpuid 0x7 0x0 "$EBX" 10 1 1
@@ -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 xen_unknown_container 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 explain_text
status=UNK status=UNK
sys_interface_available=0 sys_interface_available=0
msg='' msg=''
@@ -110,11 +110,11 @@ check_CVE_2017_5754_linux() {
dmesg_grep="$dmesg_grep|x86/pti: Unmapping kernel while in userspace" dmesg_grep="$dmesg_grep|x86/pti: Unmapping kernel while in userspace"
# aarch64 # aarch64
dmesg_grep="$dmesg_grep|CPU features: detected( feature)?: Kernel page table isolation \(KPTI\)" dmesg_grep="$dmesg_grep|CPU features: detected( feature)?: Kernel page table isolation \(KPTI\)"
if cpuinfo_has_flag pti; then if grep ^flags "$g_procfs/cpuinfo" | grep -qw pti; then
# vanilla PTI patch sets the 'pti' flag in cpuinfo # vanilla PTI patch sets the 'pti' flag in cpuinfo
pr_debug "kpti_enabled: found 'pti' flag in $g_procfs/cpuinfo" pr_debug "kpti_enabled: found 'pti' flag in $g_procfs/cpuinfo"
kpti_enabled=1 kpti_enabled=1
elif cpuinfo_has_flag kaiser; then elif grep ^flags "$g_procfs/cpuinfo" | grep -qw kaiser; then
# kernel line 4.9 sets the 'kaiser' flag in cpuinfo # kernel line 4.9 sets the 'kaiser' flag in cpuinfo
pr_debug "kpti_enabled: found 'kaiser' flag in $g_procfs/cpuinfo" pr_debug "kpti_enabled: found 'kaiser' flag in $g_procfs/cpuinfo"
kpti_enabled=1 kpti_enabled=1
@@ -167,24 +167,14 @@ 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
xen_unknown_container=0 is_xen_dom0 && xen_pv_domo=1
if is_xen && ! is_xen_dom0 && is_running_in_container; then is_xen_domU && xen_pv_domu=1
# 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_unknown_container" = 1 ]; then if [ "$xen_pv_domu" = 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
@@ -197,10 +187,7 @@ 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 [ "$xen_unknown_container" = 1 ]; then if [ "$kpti_enabled" = 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"
+2 -2
View File
@@ -89,7 +89,7 @@ check_CVE_2018_3646_linux() {
pr_info "* Mitigation 2" pr_info "* Mitigation 2"
pr_info_nol " * L1D flush is supported by kernel: " pr_info_nol " * L1D flush is supported by kernel: "
if [ "$g_mode" = live ] && cpuinfo_has_flag flush_l1d; then if [ "$g_mode" = live ] && grep -qw flush_l1d "$g_procfs/cpuinfo"; then
l1d_kernel="found flush_l1d in $g_procfs/cpuinfo" l1d_kernel="found flush_l1d in $g_procfs/cpuinfo"
fi fi
if [ -z "$l1d_kernel" ]; then if [ -z "$l1d_kernel" ]; then
@@ -162,7 +162,7 @@ check_CVE_2018_3646_linux() {
pr_info_nol " * Hardware-backed L1D flush supported: " pr_info_nol " * Hardware-backed L1D flush supported: "
if [ "$g_mode" = live ]; then if [ "$g_mode" = live ]; then
if cpuinfo_has_flag flush_l1d || [ -n "$l1d_xen_hardware" ]; then if grep -qw flush_l1d "$g_procfs/cpuinfo" || [ -n "$l1d_xen_hardware" ]; then
pstatus green YES "performance impact of the mitigation will be greatly reduced" pstatus green YES "performance impact of the mitigation will be greatly reduced"
else else
pstatus blue NO "flush will be done in software, this is slower" pstatus blue NO "flush will be done in software, this is slower"
-5
View File
@@ -86,11 +86,6 @@ 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
+7 -17
View File
@@ -103,23 +103,13 @@ check_CVE_2023_20593_linux() {
fi fi
fi fi
if [ "$zenbleed_print_vuln" = 1 ]; then if [ "$zenbleed_print_vuln" = 1 ]; then
if [ "$g_mode" = live ] && is_running_as_guest; then pvulnstatus "$cve" VULN "Your kernel is too old to mitigate Zenbleed and your CPU microcode doesn't mitigate it either"
# Both Zenbleed mitigations are applied at the host level: an explain "Your CPU vendor may have a new microcode for your CPU model that mitigates this issue (refer to the hardware section above).\n " \
# up-to-date microcode, or the host kernel setting FP_BACKUP_FIX "Otherwise, the Linux kernel is able to mitigate this issue regardless of the microcode version you have, but in this case\n " \
# in DE_CFG. From inside a guest we can't read that MSR and can't "your kernel is too old to support this, your Linux distribution vendor might have a more recent version you should upgrade to.\n " \
# trust the microcode version the hypervisor presents, so we can't "Note that either having an up to date microcode OR an up to date kernel is enough to mitigate this issue.\n " \
# confirm or deny the mitigation -- don't cry VULN (#488). "To manually mitigate the issue right now, you may use the following command: \`wrmsr -a 0xc0011029 \$((\$(rdmsr -c 0xc0011029) | (1<<9)))\`,\n " \
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" "however note that this manual mitigation will only be active until the next reboot."
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