Compare commits

..

14 Commits

Author SHA1 Message Date
Stéphane Lesimple
ef57f070db doc: add CVE-2020-0549 (L1D Eviction Sampling, CacheOut) as unsupported 2026-04-06 03:33:32 +02:00
Stéphane Lesimple
0caabfc220 fix: CVE-2019-11135 (TAA) detect new 0x10F MSR for TSX-disabled CPUs (#414) 2026-04-06 03:23:56 +02:00
Stéphane Lesimple
6106dce8d8 fix: CVE-2024-3635[0,7] don't print lines about TSA CPUID bits under non-AMD 2026-04-06 03:09:18 +02:00
Stéphane Lesimple
b71465ff74 feat: add CVE-2023-20588 (AMD DIV0 bug) (#473) 2026-04-06 02:45:41 +02:00
Stéphane Lesimple
1159d44c78 doc: update dev guidelines 2026-04-06 02:43:34 +02:00
Stéphane Lesimple
954dddaa9d doc: add CVE-2024-2201 (Native BHI) and TLBleed as unsupported 2026-04-06 02:43:34 +02:00
Stéphane Lesimple
c9a6a4f2f0 fix: CVE-2020-0543 (SRBDS): microcode mitigation misdetected (#492) 2026-04-06 02:43:34 +02:00
Stéphane Lesimple
add102e04b enh: detect IPBP return predictor bypass in Inception/SRSO ("PB-Inception") (#500)
AMD Zen 1-3 CPUs don't flush return predictions on IBPB, allowing
cross-process Spectre attacks even with IBPB-on-entry active. The kernel
fix (v6.12+, backported) adds RSB fill after IBPB on affected CPUs.
Detect this gap by checking CPUID IBPB_RET bit and kernel ibpb_no_ret
bug flag, and flag systems relying on IBPB without the RSB fill fix.
2026-04-06 02:43:34 +02:00
Stéphane Lesimple
637af10ca4 fix: don't default to 0x0 ucode when unknown 2026-04-06 02:43:34 +02:00
Stéphane Lesimple
e2eba83ce8 fix: bsd: use proper MSR for AMD in ucode version read fallback 2026-04-06 02:43:34 +02:00
Stéphane Lesimple
96c696e313 enh: MDS FreeBSD: detect software mitigation as OK unless --paranoid (#503) 2026-04-06 02:43:34 +02:00
Stéphane Lesimple
485e2d275b doc: add CVE-2021-26318 (ADM Prefetch) to unsupported list 2026-04-06 02:43:34 +02:00
Stéphane Lesimple
786bc86be8 feat: implement CVE-2023-28746 (RFDS, Register File Data Sampling) 2026-04-06 02:43:34 +02:00
Stéphane Lesimple
9288a8295d feat: add SLS (Straight-Line Speculation) check with --extra option 2026-04-06 02:43:34 +02:00
61 changed files with 1230 additions and 5079 deletions

36
.github/workflows/autoupdate.yml vendored Normal file
View File

@@ -0,0 +1,36 @@
name: autoupdate
on:
workflow_dispatch:
schedule:
- cron: '42 9 * * *'
permissions:
pull-requests: write
jobs:
autoupdate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install prerequisites
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends iucode-tool sqlite3 unzip
- name: Update microcode versions
run: ./spectre-meltdown-checker.sh --update-builtin-fwdb
- name: Check git diff
id: diff
run: |
echo change="$(git diff spectre-meltdown-checker.sh | awk '/MCEDB/ { if(V) { print V" to "$4; exit } else { V=$4 } }')" >> "$GITHUB_OUTPUT"
echo nbdiff="$(git diff spectre-meltdown-checker.sh | grep -cE -- '^\+# [AI],')" >> "$GITHUB_OUTPUT"
git diff
cat "$GITHUB_OUTPUT"
- name: Create Pull Request if needed
if: steps.diff.outputs.nbdiff != '0'
uses: peter-evans/create-pull-request@v7
with:
branch: autoupdate-fwdb
commit-message: "update: fwdb from ${{ steps.diff.outputs.change }}, ${{ steps.diff.outputs.nbdiff }} microcode changes"
title: "[Auto] Update fwdb from ${{ steps.diff.outputs.change }}"
body: |
Automated PR to update fwdb from ${{ steps.diff.outputs.change }}
Detected ${{ steps.diff.outputs.nbdiff }} microcode changes

View File

@@ -25,81 +25,21 @@ jobs:
mv spectre-meltdown-checker.sh dist/
- name: check direct execution
run: |
set -x
expected=$(cat .github/workflows/expected_cve_count)
cd dist
json=$(sudo ./spectre-meltdown-checker.sh --batch json || true)
# Validate JSON is well-formed (and show it if not)
echo "$json" | jq . >/dev/null || {
echo "Invalid JSON produced by spectre-meltdown-checker.sh"
echo "$json"
exit 1
}
# Validate required keys exist
for key in meta system cpu cpu_microcode vulnerabilities; do
echo "$json" | jq -e ".$key" >/dev/null || {
echo "Missing top-level key: $key"
echo "$json" | jq .
exit 1
}
done
# Use -r to get raw scalars (no quotes)
fmtver=$(echo "$json" | jq -r '.meta.format_version // empty')
if [ "$fmtver" != "1" ]; then
echo "Unexpected format_version: $fmtver"
echo "$json" | jq .
exit 1
fi
run_as_root=$(echo "$json" | jq -r '.meta.run_as_root // empty')
if [ "$run_as_root" != "true" ]; then
echo "Expected run_as_root=true, got: $run_as_root"
echo "$json" | jq .
exit 1
fi
mocked=$(echo "$json" | jq -r '.meta.mocked // "false"')
if [ "$mocked" = "true" ]; then
echo "mocked=true must never appear in production"
echo "$json" | jq .
exit 1
fi
# Count CVEs robustly (as a number)
nb=$(echo "$json" | jq -r '[.vulnerabilities[].cve] | length')
nb=$(sudo ./spectre-meltdown-checker.sh --batch json | jq '.[]|.CVE' | wc -l)
if [ "$nb" -ne "$expected" ]; then
echo "Invalid number of CVEs reported: $nb instead of $expected"
echo "$json" | jq '.vulnerabilities[].cve'
exit 1
else
echo "OK $nb CVEs reported"
fi
# Validate json-terse backward compatibility
nb_terse=$(sudo ./spectre-meltdown-checker.sh --batch json-terse | jq -r 'map(.CVE) | length')
if [ "$nb_terse" -ne "$expected" ]; then
echo "json-terse backward compat broken: $nb_terse CVEs instead of $expected"
exit 1
else
echo "OK json-terse backward compat: $nb_terse CVEs"
fi
- name: check docker compose run execution
run: |
expected=$(cat .github/workflows/expected_cve_count)
cd dist
docker compose build
json=$(docker compose run --rm spectre-meltdown-checker --batch json || true)
echo "$json" | jq . > /dev/null
fmtver=$(echo "$json" | jq '.meta.format_version')
if [ "$fmtver" != "1" ]; then
echo "Unexpected format_version: $fmtver"
exit 1
fi
nb=$(echo "$json" | jq '.vulnerabilities[].cve' | wc -l)
nb=$(docker compose run --rm spectre-meltdown-checker --batch json | jq '.[]|.CVE' | wc -l)
if [ "$nb" -ne "$expected" ]; then
echo "Invalid number of CVEs reported: $nb instead of $expected"
exit 1
@@ -111,14 +51,7 @@ jobs:
expected=$(cat .github/workflows/expected_cve_count)
cd dist
docker build -t spectre-meltdown-checker .
json=$(docker run --rm --privileged -v /boot:/boot:ro -v /dev/cpu:/dev/cpu:ro -v /lib/modules:/lib/modules:ro spectre-meltdown-checker --batch json || true)
echo "$json" | jq . > /dev/null
fmtver=$(echo "$json" | jq '.meta.format_version')
if [ "$fmtver" != "1" ]; then
echo "Unexpected format_version: $fmtver"
exit 1
fi
nb=$(echo "$json" | jq '.vulnerabilities[].cve' | wc -l)
nb=$(docker run --rm --privileged -v /boot:/boot:ro -v /dev/cpu:/dev/cpu:ro -v /lib/modules:/lib/modules:ro spectre-meltdown-checker --batch json | jq '.[]|.CVE' | wc -l)
if [ "$nb" -ne "$expected" ]; then
echo "Invalid number of CVEs reported: $nb instead of $expected"
exit 1
@@ -159,19 +92,15 @@ jobs:
fi
- name: create a pull request to ${{ github.ref_name }}-build
run: |
# all the files in dist/* and .github/* must be moved as is to the -build branch root, move them out for now:
tmpdir=$(mktemp -d)
mv ./dist/* .github $tmpdir/
rm -rf ./dist
git fetch origin ${{ github.ref_name }}-build
git checkout -f ${{ github.ref_name }}-build
rm -rf doc/
mv $tmpdir/* .
rm -rf src/ scripts/ img/
rm -rf src/
mkdir -p .github
rsync -vaP --delete $tmpdir/.github/ .github/
git add --all
echo =#=#= DIFF CACHED
git diff --cached

View File

@@ -1 +1 @@
32
28

33
.github/workflows/stale.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: 'Manage stale issues and PRs'
on:
schedule:
- cron: '37 7 * * *'
workflow_dispatch:
inputs:
action:
description: "dry-run"
required: true
default: "dryrun"
type: choice
options:
- dryrun
- apply
permissions:
issues: write
pull-requests: write
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v10
with:
any-of-labels: 'needs-more-info,answered'
labels-to-remove-when-unstale: 'needs-more-info,answered'
days-before-stale: 30
days-before-close: 7
stale-issue-label: stale
remove-stale-when-updated: true
debug-only: ${{ case(inputs.action == 'dryrun', true, false) }}

View File

@@ -19,7 +19,7 @@ Even though the Linux `sysfs` hierarchy (`/sys/devices/system/cpu/vulnerabilitie
- **Independent of kernel knowledge**: A given kernel only understands vulnerabilities known at compile time. This script's detection logic is maintained independently, so it can identify gaps a kernel doesn't yet know about.
- **Detailed prerequisite breakdown**: Mitigating a vulnerability can involve multiple layers (microcode, host kernel, hypervisor, guest kernel, software). The script shows exactly which pieces are in place and which are missing.
- **No-runtime kernel analysis**: The script can inspect a kernel image before it is booted (`--kernel`, `--config`, `--map`), verifying it carries the expected mitigations.
- **Offline kernel analysis**: The script can inspect a kernel image before it is booted (`--kernel`, `--config`, `--map`), verifying it carries the expected mitigations.
- **Backport-aware**: It detects actual capabilities rather than checking version strings, so it works correctly with vendor kernels that silently backport or forward-port patches.
- **Covers gaps in sysfs**: Some vulnerabilities (e.g. Zenbleed) are not reported through `sysfs` at all.
@@ -84,11 +84,8 @@ sudo ./spectre-meltdown-checker.sh --variant l1tf --variant taa
# Run specific tests that we might have just added (CVE name)
sudo ./spectre-meltdown-checker.sh --cve CVE-2018-3640 --cve CVE-2022-40982
# Batch JSON mode (comprehensive output)
sudo ./spectre-meltdown-checker.sh --batch json | python3 -m json.tool
# Batch JSON terse mode (legacy flat array)
sudo ./spectre-meltdown-checker.sh --batch json-terse | python3 -m json.tool
# Batch JSON mode (CI validates exactly 19 CVEs in output)
sudo ./spectre-meltdown-checker.sh --batch json | jq '.[] | .CVE' | wc -l # must be 19
# Update microcode firmware database
sudo ./spectre-meltdown-checker.sh --update-fwdb
@@ -105,30 +102,10 @@ The entire tool is a single bash script with no external script dependencies. Ke
- **Output/logging functions** (~line 253): `pr_warn`, `pr_info`, `pr_verbose`, `pr_debug`, `explain`, `pstatus`, `pvulnstatus` - verbosity-aware output with color support
- **CPU detection** (~line 2171): `parse_cpu_details`, `is_intel`/`is_amd`/`is_hygon`, `read_cpuid`, `read_msr`, `is_cpu_smt_enabled` - hardware identification via CPUID/MSR registers
- **Kernel architecture detection** (`src/libs/365_kernel_arch.sh`): `is_arm_kernel`/`is_x86_kernel` - detects the **target kernel's** architecture (not the host CPU) using kernel artifacts (System.map symbols, kconfig, kernel image), with `cpu_vendor` as a fast path for live mode. Results are cached in `g_kernel_arch`. Use these helpers to guard arch-specific kernel/kconfig/System.map checks and to select the appropriate verdict messages. In no-hw mode, the target kernel may differ from the host CPU architecture.
- **CPU architecture detection** (`src/libs/360_cpu_smt.sh`): `is_x86_cpu`/`is_arm_cpu` - detects the **host CPU's** architecture via `cpu_vendor`. Use these to gate hardware operations (CPUID, MSR, microcode) that require the physical CPU to be present. Always use positive logic: `if is_x86_cpu` (not `if ! is_arm_cpu`). These two sets of helpers are independent — a vuln check may need both, each guarding different lines.
- **Microcode database** (embedded): Intel/AMD microcode version lookup via `read_mcedb`/`read_inteldb`; updated automatically via `.github/workflows/autoupdate.yml`
- **Kernel analysis** (~line 1568): `extract_kernel`, `try_decompress` - extracts and inspects kernel images (handles gzip, bzip2, xz, lz4, zstd compression)
- **Vulnerability checks**: 19 `check_CVE_<year>_<number>()` functions, each with `_linux()` and `_bsd()` variants. Uses whitelist logic (assumes affected unless proven otherwise)
- **Batch output emitters** (`src/libs/250_output_emitters.sh`): `_emit_json_full`, `_emit_json_terse`, `_emit_text`, `_emit_nrpe`, `_emit_prometheus`, plus JSON section builders (`_build_json_meta`, `_build_json_system`, `_build_json_cpu`, `_build_json_cpu_microcode`)
- **Main flow** (~line 6668): Parse options → detect CPU → loop through requested CVEs → output results (text/json/json-terse/nrpe/prometheus) → cleanup
### JSON Batch Output Formats
Two JSON formats are available via `--batch`:
- **`--batch json`** (comprehensive): A top-level object with five sections:
- `meta` — script version, format version, timestamp, `mode` (`live`, `no-runtime`, `no-hw`, `hw-only`), run mode flags (`run_as_root`, `reduced_accuracy`, `mocked`, `paranoid`, `sysfs_only`, `extra`)
- `system` — kernel release/version/arch/cmdline, CPU count, SMT status, hypervisor host detection
- `cpu``arch` discriminator (`x86` or `arm`), vendor, friendly name, then an arch-specific sub-object (`cpu.x86` or `cpu.arm`) with identification fields (family/model/stepping/CPUID/codename for x86; part\_list/arch\_list for ARM) and a `capabilities` sub-object containing hardware flags as booleans/nulls
- `cpu_microcode``installed_version`, `latest_version`, `microcode_up_to_date`, `is_blacklisted`, firmware DB source/info
- `vulnerabilities` — array of per-CVE objects: `cve`, `name`, `aliases`, `cpu_affected`, `status`, `vulnerable`, `info`, `sysfs_status`, `sysfs_message`
- **`--batch json-terse`** (legacy): A flat array of objects with four fields: `NAME`, `CVE`, `VULNERABLE` (bool/null), `INFOS`. This is the original format, preserved for backward compatibility.
The comprehensive format is built in two phases: static sections (`meta`, `system`, `cpu`, `cpu_microcode`) are assembled after `check_cpu()` completes, and per-CVE entries are accumulated during the main CVE loop via `_emit_json_full()`. The sysfs data for each CVE is captured by `sys_interface_check()` into `g_json_cve_sysfs_status`/`g_json_cve_sysfs_msg` globals, which are read by the emitter and reset after each CVE to prevent cross-CVE leakage. CPU affection is determined via the already-cached `is_cpu_affected()`.
When adding new `cap_*` variables (for a new CVE or updated hardware support), they must be added to `_build_json_cpu()` in `src/libs/250_output_emitters.sh`. Per-CVE data is handled automatically.
- **Main flow** (~line 6668): Parse options → detect CPU → loop through requested CVEs → output results (text/json/nrpe/prometheus) → cleanup
## Key Design Principles
@@ -152,54 +129,11 @@ Never look at the microcode version to determine whether it has the proper mitig
**Exception**: When a vulnerability is fixed purely by a microcode update and the fix exposes **no** detectable CPUID bit, MSR bit, or ARCH\_CAP flag, then we must hardcode the known-fixing microcode versions for each affected CPU stepping. In this case, build a `<vuln>_ucode_list` table of `FF-MM-SS/platformid_mask,fixed_ucode_version` tuples (sourced from the Intel affected processor list and the Intel-Linux-Processor-Microcode-Data-Files release notes), match against `cpu_cpuid` + `cpu_platformid` in `is_cpu_affected()`, and store the required version in a `g_<vuln>_fixed_ucode_version` global. The CVE check then compares `cpu_ucode` against this threshold. Because Intel never lists EOL CPUs, the microcode list may be incomplete: keep a model blacklist as a fallback so that affected CPUs without a known fix are still flagged as affected (the CVE check should handle the empty `g_<vuln>_fixed_ucode_version` case by reporting VULN with "no microcode update available"). See Reptar (`g_reptar_fixed_ucode_version`) and BPI (`g_bpi_fixed_ucode_version`) for reference implementations.
### 4. `/proc/cpuinfo` fallback for CPUID reads
The primary way to read CPU capability bits is via `read_cpuid` (which uses `/dev/cpu/N/cpuid`). However, this device may be unavailable — most commonly inside virtual machines where the `cpuid` kernel module cannot be loaded. When `read_cpuid` returns `READ_CPUID_RET_ERR` (could not read at all), we can fall back to checking `/proc/cpuinfo` flags as a secondary source, **in live mode only**.
This works because the kernel always has direct access to CPUID (it doesn't need `/dev/cpu`), and exposes the results as flags in `/proc/cpuinfo`. When a hypervisor virtualizes a CPUID bit for the guest, the guest kernel sees it and reports it in `/proc/cpuinfo`. This is the same information `read_cpuid` would return if the device were available.
**Rules:**
- This is strictly a fallback: `read_cpuid` via `/dev/cpu/N/cpuid` remains the primary method.
- Only use it when `read_cpuid` returned `READ_CPUID_RET_ERR` (device unavailable), **never** when it returned `READ_CPUID_RET_KO` (device available but bit is 0 — meaning the CPU/hypervisor explicitly reports the feature as absent).
- Only in live mode (`$g_mode = live`), since `/proc/cpuinfo` is not available in other modes.
- Only for CPUID bits that the kernel exposes as `/proc/cpuinfo` flags. Not all bits have a corresponding flag — only those listed in the kernel's `capflags.c`. If a bit has no `/proc/cpuinfo` flag, no fallback is possible.
- The fallback depends on the running kernel being recent enough to know about the CPUID bit in question. An older kernel won't expose a flag it doesn't know about, so the fallback will silently not trigger — which is fine (we just stay at UNKNOWN, same as the ERR case without fallback).
**Known mappings** (CPUID bit → `/proc/cpuinfo` flag → script `cap_*` variable):
| CPUID source | `/proc/cpuinfo` flag | `cap_*` variable |
|---|---|---|
| Intel 0x7.0.EDX[26] / AMD 0x80000008.EBX[14] | `ibrs` | `cap_ibrs` |
| AMD 0x80000008.EBX[12] | `ibpb` | `cap_ibpb` |
| Intel 0x7.0.EDX[27] / AMD 0x80000008.EBX[15] | `stibp` | `cap_stibp` |
| Intel 0x7.0.EDX[31] / AMD 0x80000008.EBX[24,25] | `ssbd` / `virt_ssbd` | `cap_ssbd` |
| Intel 0x7.0.EDX[28] | `flush_l1d` | `cap_l1df` |
| Intel 0x7.0.EDX[10] | `md_clear` | `cap_md_clear` |
| Intel 0x7.0.EDX[29] | `arch_capabilities` | `cap_arch_capabilities` |
**Implementation pattern** in `check_cpu()`:
```sh
read_cpuid 0x7 0x0 $EDX 31 1 1
ret=$?
if [ $ret = $READ_CPUID_RET_OK ]; then
cap_ssbd='Intel SSBD'
elif [ $ret = $READ_CPUID_RET_ERR ] && [ "$g_mode" = live ]; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
if grep ^flags "$g_procfs/cpuinfo" | grep -qw ssbd; then
cap_ssbd='Intel SSBD (cpuinfo)'
ret=$READ_CPUID_RET_OK
fi
fi
```
When the fallback sets a `cap_*` variable, append ` (cpuinfo)` to the value string so the output makes it clear the information was derived from `/proc/cpuinfo` rather than read directly from hardware. Update `ret` to `READ_CPUID_RET_OK` so downstream status display logic (`pstatus`) reports YES rather than UNKNOWN.
### 5. Assume affected unless proven otherwise (whitelist approach)
### 4. Assume affected unless proven otherwise (whitelist approach)
When a CPU is not explicitly known to be unaffected by a vulnerability, assume that it is affected. This conservative default has been the right call since the early Spectre/Meltdown days and remains sound.
### 6. No-runtime mode
### 5. Offline mode
The script can analyze a non-running kernel via `--kernel`, `--config`, `--map` flags, allowing verification before deployment.
@@ -233,7 +167,6 @@ Common traps to avoid:
| `xargs` | `-r` (no-op if empty, GNU only) | Guard with a prior `[ -n "..." ]` check, or accept the harmless empty invocation |
| `readlink` | `-f` (canonicalize, GNU only) | Use only in Linux-specific code paths, or reimplement with `cd`/`pwd` |
| `dd` | `iflag=`, `oflag=` (GNU only) | Use only in Linux-specific code paths (e.g. `/dev/cpu/*/msr`) |
| `base64` | `-w N` (set line-wrap width, GNU only; BusyBox doesn't support it) | Pipe through `tr -d '\n'` to remove newlines instead of `-w0` |
When a tool genuinely has no portable equivalent, restrict the non-portable call to a platform-specific code path (i.e. inside a BSD-only or Linux-only branch) and document why.
@@ -291,12 +224,7 @@ Before writing code, verify the CVE meets the inclusion criteria (see "CVE Inclu
### Step 1: Create the Vulnerability File
Create `src/vulns/CVE-YYYY-NNNNN.sh`. When no real CVE applies, two placeholder ranges are reserved:
- **`CVE-0000-NNNN`** — permanent placeholder for supplementary `--extra`-only checks that will never receive a real CVE (e.g. SLS / compile-time hardening).
- **`CVE-9999-NNNN`** — temporary placeholder for real vulnerabilities awaiting CVE assignment. Once the real CVE is issued, rename the file, the registry entry, the `--variant` alias, and the function symbols across the codebase.
The file header must follow this exact format:
Create `src/vulns/CVE-YYYY-NNNNN.sh`. The file header must follow this exact format:
- **Line 1**: vim modeline (`# vim: set ts=4 sw=4 sts=4 et:`)
- **Line 2**: 31 `#` characters (`###############################`)
@@ -343,8 +271,6 @@ When populating the CPU model list, use the **most recent version** of the Linux
**Important**: Do not confuse hardware immunity bits with *mitigation* capability bits. A hardware immunity bit (e.g. `GDS_NO`, `TSA_SQ_NO`) declares that the CPU design is architecturally free of the vulnerability - it belongs here in `is_cpu_affected()`. A mitigation capability bit (e.g. `VERW_CLEAR`, `MD_CLEAR`) indicates that updated microcode provides a mechanism to work around a vulnerability the CPU *does* have - it belongs in the `check_CVE_YYYY_NNNNN_linux()` function (Phase 2), where it is used to determine whether mitigations are in place.
**JSON output**: If the new CVE introduces new `cap_*` variables in `check_cpu()` (whether immunity bits or mitigation bits), these must also be added to the `_build_json_cpu()` function in `src/libs/250_output_emitters.sh`, inside the `capabilities` sub-object. Use the same name as the shell variable without the `cap_` prefix (e.g. `cap_tsa_sq_no` becomes `"tsa_sq_no"` in JSON), and emit it via `_json_cap`. The per-CVE vulnerability data (affection, status, sysfs) is handled automatically by the existing `_emit_json_full()` function and requires no changes when adding a new CVE.
### Step 3: Implement the Linux Check
The `_linux()` function follows a standard algorithm with four phases:
@@ -395,44 +321,18 @@ This is where the real detection lives. Check for mitigations at each layer:
fi
```
Each source may independently be unavailable (no-runtime mode without the file, or stripped kernel), so check all that are present. A match in any one confirms kernel support.
Each source may independently be unavailable (offline mode without the file, or stripped kernel), so check all that are present. A match in any one confirms kernel support.
**Architecture awareness:** Kernel symbols, kconfig options, and kernel-image strings are architecture-specific. An x86 host may be inspecting an ARM kernel (or vice versa) in offline mode, so always use positive-logic arch guards from `src/libs/365_kernel_arch.sh` and `src/libs/360_cpu_smt.sh`. This prevents searching for irrelevant strings (e.g. x86 `spec_store_bypass` in an ARM kernel image) and ensures verdict messages and `explain` text match the target architecture (e.g. "update CPU microcode" for x86 vs "update firmware for SMCCC ARCH_WORKAROUND_2" for ARM).
Use **positive logic** — always `if is_x86_kernel` (not `if ! is_arm_kernel`) and `if is_x86_cpu` (not `if ! is_arm_cpu`). This ensures unknown architectures (MIPS, RISC-V, PowerPC) are handled safely by defaulting to "skip" rather than "execute."
Two sets of helpers serve different purposes — in no-hw mode the host CPU and the kernel being inspected can be different architectures, so the correct guard depends on what is being checked:
- **`is_x86_kernel`/`is_arm_kernel`**: Gate checks that inspect **kernel artifacts** (kernel image strings, kconfig, System.map). These detect the architecture of the target kernel, not the host, so they work correctly in offline/no-hw mode when analyzing a foreign kernel.
- **`is_x86_cpu`/`is_arm_cpu`**: Gate **hardware operations** that require the host CPU to be a given architecture (CPUID, MSR reads, `/proc/cpuinfo` flags, microcode version checks). These always reflect the running host CPU.
- Within a single vuln check, you may need **both** guards independently — e.g. `is_x86_cpu` for the microcode/MSR check and `is_x86_kernel` for the kernel image grep, not one wrapping the other.
Example:
- **Runtime state** (live mode only): Read MSRs, check cpuinfo flags, parse dmesg, inspect debugfs. All runtime-only checks — including `/proc/cpuinfo` flags — must be guarded by `if [ "$opt_live" = 1 ]`, both when collecting the evidence in Phase 2 and when using it in Phase 4. In Phase 4, use explicit live/offline branches so that live-only variables (e.g. cpuinfo flags, MSR values) are never referenced in the offline path.
```sh
# x86-specific kernel image search
if [ -n "$g_kernel" ] && is_x86_kernel; then
mitigation=$("${opt_arch_prefix}strings" "$g_kernel" | grep x86_specific_string)
fi
# ARM-specific System.map search
if [ -n "$opt_map" ] && is_arm_kernel; then
mitigation=$(grep -w arm_mitigation_function "$opt_map")
fi
# x86-specific hardware read
if is_x86_cpu; then
read_cpuid 0x7 0x0 "$EDX" 26 1 1
fi
```
The same applies to Phase 4 verdict messages: when the explanation or remediation advice differs between architectures (e.g. "CPU microcode update" vs "firmware/kernel update"), branch on `is_arm_kernel`/`is_x86_kernel` rather than on `cpu_vendor`, because `cpu_vendor` reflects the host, not the target kernel.
- **Runtime state** (live mode only): Read MSRs, check cpuinfo flags, parse dmesg, inspect debugfs. All runtime-only checks — including `/proc/cpuinfo` flags — must be guarded by `if [ "$g_mode" = live ]`, both when collecting the evidence in Phase 2 and when using it in Phase 4. In Phase 4, use explicit live/non-live branches so that live-only variables (e.g. cpuinfo flags, MSR values) are never referenced in the non-live path.
```sh
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
read_msr 0xADDRESS
ret=$?
if [ "$ret" = "$READ_MSR_RET_OK" ]; then
# check specific bits in ret_read_msr_value_lo / ret_read_msr_value_hi
fi
else
pstatus blue N/A "not testable in non-live mode"
pstatus blue N/A "not testable in offline mode"
fi
```
@@ -523,15 +423,15 @@ four categories of information that the script consumes in different modes:
1. **Sysfs messages** — every version of the string the kernel has ever produced for
`/sys/devices/system/cpu/vulnerabilities/<name>`. Used in live mode to parse the
kernel's own assessment, and in no-runtime mode to grep for known strings in `$g_kernel`.
kernel's own assessment, and in offline mode to grep for known strings in `$g_kernel`.
2. **Kconfig option names** — every `CONFIG_*` symbol that enables or controls the
mitigation. Used in no-runtime mode to check `$opt_config`. Kconfig names change over
mitigation. Used in offline mode to check `$opt_config`. Kconfig names change over
time (e.g. `CONFIG_GDS_FORCE_MITIGATION` → `CONFIG_MITIGATION_GDS_FORCE` →
`CONFIG_MITIGATION_GDS`), and vendor kernels may use their own names, so all variants
must be catalogued.
3. **Kernel function names** — functions introduced specifically for the mitigation (e.g.
`gds_select_mitigation`, `gds_apply_mitigation`, `l1tf_select_mitigation`). Used in
no-runtime mode to check `$opt_map` (System.map): the presence of a mitigation function
offline mode to check `$opt_map` (System.map): the presence of a mitigation function
proves the kernel was compiled with the mitigation code, even if the config file is
unavailable.
4. **CPU affection logic** — the complete algorithm the kernel uses to decide whether a
@@ -804,12 +704,8 @@ CVEs that need VMM context should call `check_has_vmm` early in their `_linux()`
3. **Update `dist/README.md`**: Add the CVE in **both** tables — the "Supported CVEs" reference table at the top (CVE link, description, alias) **and** the "Am I at risk?" matrix (with the correct leak/mitigation indicators per boundary). Also add a detailed description paragraph in the `<details>` section at the bottom.
4. **Build** the monolithic script with `make`.
5. **Test live**: Run the built script and confirm your CVE appears in the output and reports a sensible status.
6. **Test batch JSON**: Run with `--batch json` and pipe through `python3 -m json.tool` to verify:
- The output is valid JSON.
- The new CVE appears in the `vulnerabilities` array with correct `cve`, `name`, `aliases`, `cpu_affected`, `status`, `vulnerable`, `info`, `sysfs_status`, and `sysfs_message` fields.
- If new `cap_*` variables were added in `check_cpu()`, they appear in `cpu.capabilities` (see Step 2 JSON note).
- Run with `--batch json-terse` as well to verify backward-compatible output.
7. **Test no-runtime**: Run with `--kernel`/`--config`/`--map` pointing to a kernel image and verify the no-runtime code path reports correctly.
6. **Test batch JSON**: Run with `--batch json` and verify the CVE appears in the output.
7. **Test offline**: Run with `--kernel`/`--config`/`--map` pointing to a kernel image and verify the offline code path reports correctly.
8. **Test `--variant` and `--cve`**: Run with `--variant <shortname>` and `--cve CVE-YYYY-NNNNN` separately to confirm both selection methods work and produce the same output.
9. **Lint**: Run `shellcheck` on the monolithic script and fix any warnings.
@@ -817,12 +713,10 @@ CVEs that need VMM context should call `check_has_vmm` early in their `_linux()`
- **Never hardcode kernel or microcode versions** - detect capabilities directly (design principles 2 and 3). Exception: when a microcode fix has no detectable indicator, hardcode fixing versions per CPU (see principle 3).
- **Assume affected by default** - only mark a CPU as unaffected when there is positive evidence (design principle 4).
- **Always handle both live and non-live modes** use `$g_mode` to branch (`if [ "$g_mode" = live ]`), and print `N/A "not testable in non-live mode"` for runtime-only checks when not in live mode. Inside CVE checks, `live` is the only mode with runtime access (hw-only skips the CVE loop). Outside CVE checks (e.g. `check_cpu`), use the `has_runtime` helper which returns true for both `live` and `hw-only`.
- **Always handle both live and offline modes** - use `$opt_live` to branch, and print `N/A "not testable in offline mode"` for runtime-only checks when offline.
- **Use `explain()`** when reporting VULN to give actionable remediation advice (see "Cross-Cutting Features" above).
- **Handle `--paranoid` and `--vmm`** when the CVE has stricter mitigation tiers or VMM-specific aspects (see "Cross-Cutting Features" above).
- **Keep JSON output in sync** - when adding new `cap_*` variables, add them to `_build_json_cpu()` in `src/libs/250_output_emitters.sh` (see Step 2 JSON note above). Per-CVE fields are handled automatically.
- **All indentation must use 4 spaces** (CI enforces this via `fmt-check`; the vim modeline `et` enables expandtab).
- **Guard arch-specific checks with positive logic** — use `is_x86_kernel`/`is_arm_kernel` for kernel artifact checks, `is_x86_cpu`/`is_arm_cpu` for hardware operations. Always use positive form (`if is_x86_cpu`, not `if ! is_arm_cpu`) so unknown architectures default to "skip." Never use `cpu_vendor` to branch on architecture in Phase 2/4 — it reflects the host, not the target kernel being inspected.
- **Stay POSIX-compatible** - no bashisms, no GNU-only flags in portable code paths.
## Function documentation headers

View File

@@ -81,7 +81,7 @@ ARM processors may speculatively execute instructions past unconditional control
VUSec researchers demonstrated that the original BHI mitigation (disabling unprivileged eBPF) was insufficient: 1,511 native kernel gadgets exist that allow exploiting Branch History Injection without eBPF, leaking arbitrary kernel memory at ~3.5 kB/sec on Intel CPUs.
**Why out of scope:** CVE-2024-2201 is not a new hardware vulnerability — it is the same BHI hardware bug as CVE-2022-0002, but proves that eBPF restriction alone was never sufficient. The required mitigations are identical: `BHI_DIS_S` hardware control (MSR `IA32_SPEC_CTRL` bit 10), software BHB clearing loop at syscall entry and VM exit, or retpoline with RRSBA disabled. These are all already detected by this tool's CVE-2017-5715 (Spectre V2) checks, which parse the `BHI:` suffix from `/sys/devices/system/cpu/vulnerabilities/spectre_v2` and check for `CONFIG_MITIGATION_SPECTRE_BHI` in no-runtime mode. No new sysfs entry, MSR, kernel config option, or boot parameter was introduced for this CVE.
**Why out of scope:** CVE-2024-2201 is not a new hardware vulnerability — it is the same BHI hardware bug as CVE-2022-0002, but proves that eBPF restriction alone was never sufficient. The required mitigations are identical: `BHI_DIS_S` hardware control (MSR `IA32_SPEC_CTRL` bit 10), software BHB clearing loop at syscall entry and VM exit, or retpoline with RRSBA disabled. These are all already detected by this tool's CVE-2017-5715 (Spectre V2) checks, which parse the `BHI:` suffix from `/sys/devices/system/cpu/vulnerabilities/spectre_v2` and check for `CONFIG_MITIGATION_SPECTRE_BHI` in offline mode. No new sysfs entry, MSR, kernel config option, or boot parameter was introduced for this CVE.
## CVE-2020-0549 — L1D Eviction Sampling (CacheOut)
@@ -124,17 +124,6 @@ A branch predictor initialization issue specific to Intel's Lion Cove microarchi
These CVEs are real vulnerabilities, but no kernel or microcode fix has been issued, the mitigation is delegated to individual software, or the fix is not detectable by this tool.
## CVE-2018-3665 — Lazy FP State Restore (LazyFP)
- **Advisory:** [INTEL-SA-00145](https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/lazy-fp-state-restore.html)
- **Research paper:** [LazyFP: Leaking FPU Register State using Microarchitectural Side-Channels (Stecklina & Prescher, 2018)](https://arxiv.org/abs/1806.07480)
- **Affected CPUs:** Intel Core family (Sandy Bridge through Kaby Lake) when lazy FPU switching is in use
- **CVSS:** 4.3 (Medium)
Intel CPUs using lazy FPU state switching may speculatively expose another process's FPU/SSE/AVX register contents (including AES round keys and other cryptographic material) across context switches. The `#NM` (device-not-available) exception normally used to trigger lazy restore is delivered late enough that dependent instructions can transiently execute against the stale FPU state before the fault squashes them.
**Why out of scope:** The Linux mitigation is to use eager FPU save/restore, which was already the default on Intel CPUs with XSAVEOPT well before disclosure, and was then hard-enforced upstream by the removal of all lazy FPU code in Linux 4.14 (Andy Lutomirski's "x86/fpu: Hard-disable lazy FPU mode" cleanup). There is no `/sys/devices/system/cpu/vulnerabilities/` entry, no CPUID flag, no MSR, and no kernel config option that reflects this mitigation — detection on a running kernel would require hardcoding kernel version ranges, which is against this tool's design principles (same rationale as CVE-2019-15902). In practice, any supported kernel today is eager-FPU-only, and CPUs advertising XSAVEOPT/XSAVES cannot enter the vulnerable lazy-switching mode regardless of kernel configuration.
## CVE-2018-9056 — BranchScope
- **Issue:** [#169](https://github.com/speed47/spectre-meltdown-checker/issues/169)
@@ -166,28 +155,6 @@ AMD CPUs may transiently execute non-canonical loads and stores using only the l
**Why out of scope:** AMD's mitigation guidance is for software vendors to "analyze their code for any potential vulnerabilities" and insert LFENCE or use existing speculation mitigation techniques in their own code. No microcode or kernel-level mitigations have been issued. The responsibility falls on individual software, not on the kernel or firmware, leaving nothing for this script to check.
## CVE-2020-24511 — Domain-Type Confusion (IBRS Scope)
- **Issue:** [#409](https://github.com/speed47/spectre-meltdown-checker/issues/409)
- **Advisory:** [INTEL-SA-00464](https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00464.html)
- **Affected CPUs:** Intel Skylake through Comet Lake (different steppings; see advisory for details)
- **CVSS:** 6.5 (Medium)
Improper isolation of shared resources in some Intel processors allows an authenticated user to potentially enable information disclosure via local access. Specifically, the Indirect Branch Restricted Speculation (IBRS) mitigation may not be fully applied after certain privilege-level transitions, allowing residual branch predictions to cross security boundaries.
**Why out of scope:** The mitigation is exclusively a microcode update (released June 2021) with no corresponding Linux kernel sysfs entry in `/sys/devices/system/cpu/vulnerabilities/`, no new CPUID bit, no new MSR, and no kernel configuration option. The only way to detect the fix would be to maintain a per-CPU-stepping minimum microcode version lookup table, which is brittle and high-maintenance. Additionally, Intel dropped microcode support for Sandy Bridge and Ivy Bridge in the same timeframe, leaving those generations permanently unpatched with no mitigation path available.
## CVE-2020-24512 — Observable Timing Discrepancy (Trivial Data Value)
- **Issue:** [#409](https://github.com/speed47/spectre-meltdown-checker/issues/409)
- **Advisory:** [INTEL-SA-00464](https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00464.html)
- **Affected CPUs:** Intel Skylake through Tiger Lake (broad scope; see advisory for details)
- **CVSS:** 2.8 (Low)
Observable timing discrepancy in some Intel processors allows an authenticated user to potentially enable information disclosure via local access. Certain cache optimizations treat "trivial data value" cache lines (e.g., all-zero lines) differently from non-trivial lines, creating a timing side channel that can distinguish memory content patterns.
**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-26318 — AMD Prefetch Attacks through Power and Time
- **Issue:** [#412](https://github.com/speed47/spectre-meltdown-checker/issues/412)
@@ -226,17 +193,6 @@ A transient execution vulnerability in some AMD processors may allow a user proc
**Why out of scope:** AMD has determined that "leakage of TSC_AUX does not result in leakage of sensitive information" and has marked this CVE as "No fix planned" across all affected product lines. No microcode or kernel mitigations have been issued, leaving nothing for this script to check.
## No CVE — BlindSide (Speculative Probing)
- **Issue:** [#374](https://github.com/speed47/spectre-meltdown-checker/issues/374)
- **Research paper:** [Speculative Probing: Hacking Blind in the Spectre Era (VUSec, ACM CCS 2020)](https://www.vusec.net/projects/blindside/)
- **Red Hat advisory:** [Article 5394291](https://access.redhat.com/articles/5394291)
- **Affected CPUs:** All CPUs vulnerable to Spectre V2 (BTB-based speculative execution)
An attack technique that combines a pre-existing kernel memory corruption bug (e.g., a heap buffer overflow) with speculative execution to perform "Speculative BROP" (Blind Return-Oriented Programming). Instead of crashing the system when probing invalid addresses, BlindSide performs the probing speculatively: faults are suppressed in the speculative domain, and information is leaked via cache timing side channels. This allows an attacker to silently derandomize kernel memory layout and bypass KASLR/FGKASLR without triggering any fault.
**Why out of scope:** BlindSide is an exploitation technique, not a discrete hardware vulnerability: no CVE was assigned. Red Hat explicitly states it is "not a new flaw, but a new attack." It requires a pre-existing kernel memory corruption bug as a prerequisite, and the speculative execution aspect leverages the same BTB behavior as Spectre V2 (CVE-2017-5715). No dedicated microcode update, kernel config, MSR, CPUID bit, or sysfs entry exists for BlindSide. The closest hardware mitigations (IBPB, IBRS, STIBP, Retpoline) are already covered by this tool's Spectre V2 checks.
## No CVE — TLBleed (TLB side-channel)
- **Issue:** [#231](https://github.com/speed47/spectre-meltdown-checker/issues/231)
@@ -254,30 +210,6 @@ A timing side-channel attack exploiting the shared Translation Lookaside Buffer
These are hardware flaws but not side-channel or speculative execution issues. They fall outside the vulnerability class this tool is designed to detect.
## CVE-2019-11157 — Plundervolt (VoltJockey)
- **Issue:** [#335](https://github.com/speed47/spectre-meltdown-checker/issues/335)
- **Advisory:** [INTEL-SA-00289](https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00289.html)
- **Research:** [Plundervolt (plundervolt.com)](https://plundervolt.com/)
- **Affected CPUs:** Intel Core 6th10th gen (Skylake through Comet Lake) with SGX
- **CVSS:** 7.1 (High)
A voltage fault injection attack where a privileged attacker (ring 0) uses the software-accessible voltage scaling interface to undervolt the CPU during SGX enclave computations, inducing predictable bit flips that compromise enclave integrity and confidentiality. Intel's microcode fix locks down the voltage/frequency scaling MSRs to prevent software-initiated undervolting.
**Why out of scope:** Not a transient or speculative execution vulnerability — this is a fault injection attack exploiting voltage manipulation, with no side-channel or speculative execution component. It requires ring 0 access and targets SGX enclaves specifically. While Intel issued a microcode update that locks voltage controls, there is no Linux kernel sysfs entry, no CPUID flag, and no kernel-side mitigation to detect. The fix is purely a microcode-level lockdown of voltage scaling registers, which is not exposed in any standard interface this tool can query.
## CVE-2020-8694 / CVE-2020-8695 — Platypus (RAPL Power Side Channel)
- **Issue:** [#384](https://github.com/speed47/spectre-meltdown-checker/issues/384)
- **Advisory:** [INTEL-SA-00389](https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00389.html)
- **Research:** [PLATYPUS (platypusattack.com)](https://platypusattack.com/)
- **Affected CPUs:** Intel Core (Sandy Bridge+), Intel Xeon (Sandy Bridge-EP+)
- **CVSS:** 5.6 (Medium) / 6.5 (Medium)
A software-based power side-channel attack exploiting Intel's Running Average Power Limit (RAPL) interface. By monitoring energy consumption reported through the `powercap` sysfs interface or the `MSR_RAPL_POWER_UNIT` / `MSR_PKG_ENERGY_STATUS` MSRs, an unprivileged attacker can statistically distinguish instructions and operands, recover AES-NI keys from SGX enclaves, and break kernel ASLR.
**Why out of scope:** Not a transient or speculative execution vulnerability — this is a power analysis side-channel attack with no speculative execution component. The mitigations (microcode update restricting RAPL energy reporting to privileged access, and kernel restricting the `powercap` sysfs interface) are not exposed via `/sys/devices/system/cpu/vulnerabilities/`. There is no dedicated sysfs vulnerability entry, no CPUID flag, and no kernel configuration option for this tool to check.
## CVE-2023-31315 — SinkClose (AMD SMM Lock Bypass)
- **Issue:** [#499](https://github.com/speed47/spectre-meltdown-checker/issues/499)
@@ -307,13 +239,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.
**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.
## 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.

View File

@@ -85,7 +85,7 @@ However I see a few reasons why this script might still be useful to you, and th
- The script can be pointed at a kernel image, and will deep dive into it, telling you if this kernel will mitigate vulnerabilities that might be present on your system. This is a good way to verify before booting a new kernel, that it'll mitigate the vulnerabilities you expect it to, especially if you modified a few config options around these topics.
- The script will also work regardless of the custom patches that might be integrated in the kernel you're running (or you're pointing it to, in no-runtime mode), and completely ignores the advertised kernel version, to tell whether a given kernel mitigates vulnerabilities. This is especially useful for non-vanilla kernel, where patches might be backported, sometimes silently (this has already happened, too).
- The script will also work regardless of the custom patches that might be integrated in the kernel you're running (or you're pointing it to, in offline mode), and completely ignores the advertised kernel version, to tell whether a given kernel mitigates vulnerabilities. This is especially useful for non-vanilla kernel, where patches might be backported, sometimes silently (this has already happened, too).
- Educational purposes: the script gives interesting insights about a vulnerability, and how the different parts of the system work together to mitigate it.

91
dist/README.md vendored
View File

@@ -22,9 +22,6 @@ CVE | Name | Aliases
[CVE-2019-11091](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11091) | Microarchitectural Data Sampling Uncacheable Memory | MDSUM, RIDL
[CVE-2019-11135](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11135) | TSX Asynchronous Abort | TAA, ZombieLoad V2
[CVE-2020-0543](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-0543) | Special Register Buffer Data Sampling | SRBDS, CROSSTalk
[CVE-2022-21123](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-21123) | Shared Buffers Data Read | SBDR, MMIO Stale Data
[CVE-2022-21125](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-21125) | Shared Buffers Data Sampling | SBDS, MMIO Stale Data
[CVE-2022-21166](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-21166) | Device Register Partial Write | DRPW, MMIO Stale Data
[CVE-2022-29900](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-29900) | Arbitrary Speculative Code Execution with Return Instructions | Retbleed (AMD)
[CVE-2022-29901](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-29901) | Arbitrary Speculative Code Execution with Return Instructions | Retbleed (Intel), RSBA
[CVE-2022-40982](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-40982) | Gather Data Sampling | Downfall, GDS
@@ -38,15 +35,6 @@ CVE | Name | Aliases
[CVE-2024-36357](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-36357) | Transient Scheduler Attack, L1 | TSA-L1
[CVE-2025-40300](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2025-40300) | VM-Exit Stale Branch Prediction | VMScape
[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
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?
@@ -70,9 +58,6 @@ CVE-2018-12207 (iTLB Multihit, No eXcuses) | ✅ | ✅ | ☠️ | ✅ | Hypervis
CVE-2019-11091 (MDSUM, RIDL) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
CVE-2019-11135 (TAA, ZombieLoad V2) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
CVE-2020-0543 (SRBDS, CROSSTalk) | 💥 (2) | 💥 (2) | 💥 (2) | 💥 (2) | Microcode + kernel update
CVE-2022-21123 (SBDR, MMIO Stale Data) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
CVE-2022-21125 (SBDS, MMIO Stale Data) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
CVE-2022-21166 (DRPW, MMIO Stale Data) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
CVE-2022-29900 (Retbleed AMD) | 💥 | ✅ | 💥 | ✅ | Kernel update (+ microcode for IBPB)
CVE-2022-29901 (Retbleed Intel, RSBA) | 💥 | ✅ | 💥 | ✅ | Microcode + kernel update (eIBRS or IBRS)
CVE-2022-40982 (Downfall, GDS) | 💥 | 💥 | 💥 | 💥 | Microcode update (or disable AVX)
@@ -86,7 +71,6 @@ CVE-2024-36350 (TSA-SQ) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel
CVE-2024-36357 (TSA-L1) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
CVE-2025-40300 (VMScape) | ✅ | ✅ | 💥 | ✅ | Kernel update (IBPB on VM-exit)
CVE-2024-45332 (BPI) | 💥 | ✅ | 💥 | ✅ | Microcode update
CVE-2025-54505 (FPDSS) | 💥 | 💥 | 💥 | 💥 | Kernel update
> 💥 Data can be leaked across this boundary.
@@ -161,10 +145,6 @@ On CPUs with Intel TSX, a transactional abort can leave data from the line fill
Certain special CPU instructions (RDRAND, RDSEED, EGETKEY) read data through a shared staging buffer that is accessible across all cores via speculative execution. An attacker running code on any core can observe the output of these instructions from a victim on a different core, including extracting cryptographic keys from SGX enclaves (a complete ECDSA key was demonstrated). This is notable as one of the first cross-core speculative execution attacks. Mitigation requires a microcode update that serializes access to the staging buffer, plus a kernel update to manage the mitigation. Performance impact is low, mainly affecting workloads that heavily use RDRAND/RDSEED.
**CVE-2022-21123, CVE-2022-21125, CVE-2022-21166 — Processor MMIO Stale Data (SBDR, SBDS, DRPW)**
A class of MMIO (Memory-Mapped I/O) vulnerabilities where stale data from CPU internal fill buffers can be inferred through side-channel attacks during MMIO operations. Three sub-vulnerabilities are covered: Shared Buffers Data Read (SBDR, CVE-2022-21123), Shared Buffers Data Sampling (SBDS, CVE-2022-21125), and Device Register Partial Write (DRPW, CVE-2022-21166). Affected Intel CPUs include Haswell through Rocket Lake server and client processors, plus Tremont Atom cores. Mitigation requires a microcode update providing the FB_CLEAR capability (VERW instruction clears fill buffers) plus a kernel update (Linux 5.19+) that invokes VERW at kernel/user transitions and VM entry/exit. When SMT is enabled, sibling threads can still exploit the vulnerability even with mitigations active. Performance impact is low, as the VERW mechanism is shared with the existing MDS mitigation.
**CVE-2022-29900 — Arbitrary Speculative Code Execution with Return Instructions (Retbleed AMD)**
On AMD processors from families 0x15 through 0x17 (Bulldozer through Zen 2) and Hygon family 0x18, an attacker can exploit return instructions to redirect speculative execution and leak kernel memory, bypassing retpoline mitigations that were effective against Spectre V2. Unlike Spectre V2 which targets indirect jumps and calls, Retbleed specifically targets return instructions, which were previously considered safe. Mitigation requires a kernel update providing either the untrained return thunk (safe RET) or IBPB-on-entry mechanism, plus a microcode update providing IBPB support on Zen 1/2. On Zen 1/2, SMT should be disabled for full protection when using IBPB-based mitigation. Performance impact is medium.
@@ -217,10 +197,6 @@ After a guest VM exits to the host, stale branch predictions from the guest can
A race condition in the branch predictor update mechanism of Intel processors (Coffee Lake through Raptor Lake, plus some server and Atom parts) allows user-space branch predictions to briefly influence kernel-space speculative execution, undermining eIBRS and IBPB protections. This means systems relying solely on eIBRS for Spectre V2 mitigation may not be fully protected without the microcode fix. Mitigation requires a microcode update (intel-microcode 20250512+) that fixes the asynchronous branch predictor update timing so that eIBRS and IBPB work as originally intended. No kernel changes are required. Performance impact is negligible.
**CVE-2025-54505 — AMD Zen1 Floating-Point Divider Stale Data Leak (FPDSS)**
On AMD Zen1 and Zen+ processors (EPYC 7001, EPYC Embedded 3000, Athlon 3000 with Radeon, Ryzen 3000 with Radeon, Ryzen PRO 3000 with Radeon Vega), the hardware floating-point divider can retain partial quotient data from previous operations. Under certain circumstances, those results can be leaked to another thread sharing the same divider, crossing any privilege boundary. This was assigned CVE-2025-54505 and published by AMD as AMD-SB-7053 on 2026-04-17. Mitigation requires a kernel update (mainline commit e55d98e77561, "x86/CPU: Fix FPDSS on Zen1", Linux 7.1) that sets bit 9 (ZEN1_DENORM_FIX_BIT) of MSR 0xc0011028 (MSR_AMD64_FP_CFG) unconditionally on every Zen1 CPU at boot, disabling the hardware optimization responsible for the leak. No microcode update is required: the chicken bit is present in Zen1 silicon from the factory and is independent of microcode revision. Performance impact is limited to a small reduction in floating-point divide throughput, which is why AMD does not enable the bit by default in hardware.
</details>
## Unsupported CVEs
@@ -228,17 +204,17 @@ On AMD Zen1 and Zen+ processors (EPYC 7001, EPYC Embedded 3000, Athlon 3000 with
Several transient execution CVEs are not covered by this tool, for various reasons (duplicates, only
affecting non-supported hardware or OS, theoretical with no known exploitation, etc.).
The complete list along with the reason for each exclusion is available in the
[UNSUPPORTED_CVE_LIST.md](doc/UNSUPPORTED_CVE_LIST.md) file.
[UNSUPPORTED_CVE_LIST.md](https://github.com/speed47/spectre-meltdown-checker/blob/source/UNSUPPORTED_CVE_LIST.md) file.
## Scope
Supported operating systems:
- Linux (all versions, flavors and distros)
- FreeBSD, NetBSD, DragonFlyBSD and derivatives (others BSDs are [not supported](doc/FAQ.md#which-bsd-oses-are-supported))
- FreeBSD, NetBSD, DragonFlyBSD and derivatives (others BSDs are [not supported](FAQ.md#which-bsd-oses-are-supported))
For Linux systems, the tool will detect mitigations, including backported non-vanilla patches, regardless of the advertised kernel version number and the distribution (such as Debian, Ubuntu, CentOS, RHEL, Fedora, openSUSE, Arch, ...), it also works if you've compiled your own kernel. More information [here](doc/FAQ.md#how-does-this-script-work).
For Linux systems, the tool will detect mitigations, including backported non-vanilla patches, regardless of the advertised kernel version number and the distribution (such as Debian, Ubuntu, CentOS, RHEL, Fedora, openSUSE, Arch, ...), it also works if you've compiled your own kernel. More information [here](FAQ.md#how-does-this-script-work).
Other operating systems such as MacOS, Windows, ESXi, etc. [will never be supported](doc/FAQ.md#why-is-my-os-not-supported).
Other operating systems such as MacOS, Windows, ESXi, etc. [will never be supported](FAQ.md#why-is-my-os-not-supported).
Supported architectures:
- `x86` (32 bits)
@@ -250,29 +226,7 @@ Supported architectures:
What is the purpose of this tool? Why was it written? How can it be useful to me? How does it work? What can I expect from it?
All these questions (and more) have detailed answers in the [FAQ](doc/FAQ.md), please have a look!
## Operating modes
The script supports four operating modes, depending on whether you want to inspect the running kernel, a kernel image, the CPU hardware, or a combination.
| Mode | Flag | CPU hardware | Running kernel | Kernel image | Use case |
|------|------|:---:|:---:|:---:|----------|
| **Live** *(default)* | *(none)* | Yes | Yes | auto-detect | Day-to-day auditing of the current system |
| **No-runtime** | `--no-runtime` | Yes | No | required | Check a different kernel against this CPU (e.g. pre-deployment) |
| **No-hardware** | `--no-hw` | No | No | required | Pure static analysis of a kernel image for another system or architecture |
| **Hardware-only** | `--hw-only` | Yes | No | No | Quickly check CPU affectedness without inspecting any kernel |
In **Live** mode (the default), the script inspects both the CPU and the running kernel.
You can optionally pass `--kernel`, `--config`, or `--map` to point the script at files it couldn't auto-detect.
In **No-runtime** mode, the script still reads the local CPU (CPUID, MSRs, microcode) but skips all running-kernel artifacts (`/sys`, `/proc`, `dmesg`).
Use this when you have a kernel image from another system but want to evaluate it against the current CPU.
In **No-hardware** mode, both CPU inspection and running-kernel artifacts are skipped entirely.
This is useful for cross-architecture analysis, for example inspecting an ARM kernel image on an x86 workstation.
In **Hardware-only** mode, the script only reports CPU information and per-CVE hardware affectedness, without inspecting any kernel.
All these questions (and more) have detailed answers in the [FAQ](FAQ.md), please have a look!
## Running the script
@@ -280,23 +234,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`
```bash
curl -L https://meltdown.ovh -o spectre-meltdown-checker.sh
wget https://meltdown.ovh -O spectre-meltdown-checker.sh
```
```bash
curl -L 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?
```bash
vim spectre-meltdown-checker.sh
```
```bash
vim spectre-meltdown-checker.sh
```
- When you're ready, run the script as root
```bash
chmod +x spectre-meltdown-checker.sh
sudo ./spectre-meltdown-checker.sh
```
```bash
chmod +x spectre-meltdown-checker.sh
sudo ./spectre-meltdown-checker.sh
```
### Using a docker container
@@ -324,6 +278,15 @@ docker run --rm --privileged -v /boot:/boot:ro -v /dev/cpu:/dev/cpu:ro -v /lib/m
## Example of script output
- AMD EPYC-Milan running under Debian Trixie
- Intel Haswell CPU running under Ubuntu 16.04 LTS
![haswell](https://user-images.githubusercontent.com/218502/108764885-6dcfc380-7553-11eb-81ac-4d19060a3acf.png)
- AMD Ryzen running under OpenSUSE Tumbleweed
![ryzen](https://user-images.githubusercontent.com/218502/108764896-70321d80-7553-11eb-9dd2-fad2a0a1a737.png)
- Batch mode (JSON flavor)
![batch](https://user-images.githubusercontent.com/218502/108764902-71634a80-7553-11eb-9678-fd304995fa64.png)
![alt text](https://raw.githubusercontent.com/speed47/spectre-meltdown-checker/refs/heads/test/img/smc_amd_epyc_milan.jpg)

393
dist/doc/batch_json.md vendored
View File

@@ -1,393 +0,0 @@
# JSON Output Format
`--batch json` emits a single, self-contained JSON object that describes the
scan environment and the result of every CVE check. You can feed it to your
monitoring system, to a SIEM, to a time-series database, you name it.
```sh
sudo ./spectre-meltdown-checker.sh --batch json | jq .
```
## Top-level schema
```
{
"meta": { ... }, // Run metadata and flags
"system": { ... }, // Kernel and host context
"cpu": { ... }, // CPU hardware identification
"cpu_microcode": { ... }, // Microcode version and status
"vulnerabilities": [ ... ] // One object per checked CVE
}
```
`format_version` in `meta` is an integer that will be incremented on
backward-incompatible schema changes. The current value is **1**.
## Section reference
### `meta`
Run metadata. Always present.
| Field | Type | Values | Meaning |
|---|---|---|---|
| `script_version` | string | e.g. `"25.30.0250400123"` | Script version |
| `format_version` | integer | `1` | JSON schema version; incremented on breaking changes |
| `timestamp` | string | ISO 8601 UTC, e.g. `"2025-04-07T12:00:00Z"` | When the scan started |
| `os` | string | e.g. `"Linux"`, `"FreeBSD"` | Output of `uname -s` |
| `mode` | string | `"live"` / `"no-runtime"` / `"no-hw"` / `"hw-only"` | Operating mode (see [modes](README.md#operating-modes)) |
| `run_as_root` | boolean | | Whether the script ran as root. Non-root scans skip MSR reads and may miss mitigations |
| `reduced_accuracy` | boolean | | Kernel image, config, or System.map was missing; some checks fall back to weaker heuristics |
| `paranoid` | boolean | | `--paranoid` mode: stricter criteria (e.g. requires SMT disabled, IBPB always-on) |
| `sysfs_only` | boolean | | `--sysfs-only`: only the kernel's own sysfs report was used, not independent detection |
| `extra` | boolean | | `--extra`: additional experimental checks were enabled |
| `mocked` | boolean | | One or more CPU values were overridden for testing. Results do **not** reflect the real system |
**Example:**
```json
"meta": {
"script_version": "25.30.025040123",
"format_version": 1,
"timestamp": "2025-04-07T12:00:00Z",
"os": "Linux",
"mode": "live",
"run_as_root": true,
"reduced_accuracy": false,
"paranoid": false,
"sysfs_only": false,
"extra": false,
"mocked": false
}
```
**Important flags for fleet operators:**
- `run_as_root: false` means the scan was incomplete. Treat results as lower
confidence. Alert separately: results may be missing or wrong.
- `sysfs_only: true` means the script trusted the kernel's self-report without
independent verification. Some older kernels misreport their mitigation
status. Do not use `--sysfs-only` for production fleet monitoring.
- `paranoid: true` raises the bar: only compare `vulnerable` counts across
hosts with the same `paranoid` value.
- `mocked: true` must never appear on a production host. If it does, every
downstream result is fabricated.
---
### `system`
Kernel and host environment. Always present.
| Field | Type | Values | Meaning |
|---|---|---|---|
| `kernel_release` | string \| null | e.g. `"6.1.0-21-amd64"` | Output of `uname -r` (null in no-runtime, no-hw, and hw-only modes) |
| `kernel_version` | string \| null | e.g. `"#1 SMP Debian …"` | Output of `uname -v` (null in no-runtime, no-hw, and hw-only modes) |
| `kernel_arch` | string \| null | e.g. `"x86_64"` | Output of `uname -m` (null in no-runtime, no-hw, and hw-only modes) |
| `kernel_image` | string \| null | e.g. `"/boot/vmlinuz-6.1.0-21-amd64"` | Path passed via `--kernel`, or null if not specified |
| `kernel_config` | string \| null | | Path passed via `--config`, or null |
| `kernel_version_string` | string \| null | | Kernel version banner extracted from the image |
| `kernel_cmdline` | string \| null | | Kernel command line from `/proc/cmdline` (live mode) or the image |
| `cpu_count` | integer \| null | | Number of logical CPUs detected |
| `smt_enabled` | boolean \| null | | Whether SMT (HyperThreading) is currently active; null if undeterminable |
| `hypervisor_host` | boolean \| null | | Whether this machine is detected as a VM host (running KVM, Xen, VMware, etc.) |
| `hypervisor_host_reason` | string \| null | | Human-readable explanation of why `hypervisor_host` was set |
**`hypervisor_host`** materially changes the risk profile of several CVEs.
L1TF (CVE-2018-3646) and MDS (CVE-2018-12126/12130/12127) are significantly
more severe on hypervisor hosts because they can be exploited across VM
boundaries by a malicious guest. Prioritise remediation where
`hypervisor_host: true`.
---
### `cpu`
CPU hardware identification. `null` when `--no-hw` is active, or when
`--arch-prefix` is set (host CPU info is then suppressed to avoid mixing
with a different-arch target kernel).
The object uses `arch` as a discriminator: `"x86"` for Intel/AMD/Hygon CPUs,
`"arm"` for ARM/Cavium/Phytium. Arch-specific fields live under a matching
sub-object (`cpu.x86` or `cpu.arm`), so consumers never see irrelevant null
fields from the other architecture.
#### Common fields
| Field | Type | Values | Meaning |
|---|---|---|---|
| `arch` | string | `"x86"` / `"arm"` | CPU architecture family; determines which sub-object is present |
| `vendor` | string \| null | e.g. `"GenuineIntel"`, `"ARM"` | CPU vendor string |
| `friendly_name` | string \| null | e.g. `"Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz"` | Human-readable CPU model |
#### `cpu.x86` (present when `arch == "x86"`)
| Field | Type | Values | Meaning |
|---|---|---|---|
| `family` | integer \| null | | CPU family number |
| `model` | integer \| null | | CPU model number |
| `stepping` | integer \| null | | CPU stepping number |
| `cpuid` | string \| null | hex, e.g. `"0x000906ed"` | Full CPUID leaf 1 EAX value |
| `platform_id` | integer \| null | | Intel platform ID (from MSR 0x17); null on AMD |
| `hybrid` | boolean \| null | | Whether this is a hybrid CPU (P-cores + E-cores, e.g. Alder Lake) |
| `codename` | string \| null | e.g. `"Coffee Lake"` | Intel CPU codename; null on AMD |
| `capabilities` | object | | CPU feature flags (see below) |
#### `cpu.arm` (present when `arch == "arm"`)
| Field | Type | Values | Meaning |
|---|---|---|---|
| `part_list` | string \| null | e.g. `"0xd0b 0xd05"` | Space-separated ARM part numbers across cores (big.LITTLE may have several) |
| `arch_list` | string \| null | e.g. `"8 8"` | Space-separated ARM architecture levels across cores |
| `capabilities` | object | | ARM-specific capability flags (currently empty; reserved for future use) |
#### `cpu.x86.capabilities`
Every capability is a **tri-state**: `true` (present), `false` (absent), or
`null` (not applicable or could not be read, e.g. when not root or on AMD for
Intel-specific features).
| Capability | Meaning |
|---|---|
| `spec_ctrl` | SPEC_CTRL MSR (Intel: ibrs + ibpb via WRMSR; required for many mitigations) |
| `ibrs` | Indirect Branch Restricted Speculation |
| `ibpb` | Indirect Branch Prediction Barrier |
| `ibpb_ret` | IBPB on return (enhanced form) |
| `stibp` | Single Thread Indirect Branch Predictors |
| `ssbd` | Speculative Store Bypass Disable |
| `l1d_flush` | L1D cache flush instruction |
| `md_clear` | VERW clears CPU buffers (MDS mitigation) |
| `arch_capabilities` | IA32_ARCH_CAPABILITIES MSR is present |
| `rdcl_no` | Not susceptible to RDCL (Meltdown-like attacks) |
| `ibrs_all` | Enhanced IBRS always-on mode supported |
| `rsba` | RSB may use return predictions from outside the RSB |
| `l1dflush_no` | Not susceptible to L1D flush side-channel |
| `ssb_no` | Not susceptible to Speculative Store Bypass |
| `mds_no` | Not susceptible to MDS |
| `taa_no` | Not susceptible to TSX Asynchronous Abort |
| `pschange_msc_no` | Page-size-change MSC not susceptible |
| `tsx_ctrl_msr` | TSX_CTRL MSR is present |
| `tsx_ctrl_rtm_disable` | RTM disabled via TSX_CTRL |
| `tsx_ctrl_cpuid_clear` | CPUID HLE/RTM bits cleared via TSX_CTRL |
| `gds_ctrl` | GDS_CTRL MSR present (GDS mitigation control) |
| `gds_no` | Not susceptible to Gather Data Sampling |
| `gds_mitg_dis` | GDS mitigation disabled |
| `gds_mitg_lock` | GDS mitigation locked |
| `rfds_no` | Not susceptible to Register File Data Sampling |
| `rfds_clear` | VERW clears register file stale data |
| `its_no` | Not susceptible to Indirect Target Selection |
| `sbdr_ssdp_no` | Not susceptible to SBDR/SSDP |
| `fbsdp_no` | Not susceptible to FBSDP |
| `psdp_no` | Not susceptible to PSDP |
| `fb_clear` | Fill buffer cleared on idle/C6 |
| `rtm` | Restricted Transactional Memory (TSX RTM) present |
| `tsx_force_abort` | TSX_FORCE_ABORT MSR present |
| `tsx_force_abort_rtm_disable` | RTM disabled via TSX_FORCE_ABORT |
| `tsx_force_abort_cpuid_clear` | CPUID RTM cleared via TSX_FORCE_ABORT |
| `sgx` | Software Guard Extensions present |
| `srbds` | SRBDS affected |
| `srbds_on` | SRBDS mitigation active |
| `amd_ssb_no` | AMD: not susceptible to Speculative Store Bypass |
| `hygon_ssb_no` | Hygon: not susceptible to Speculative Store Bypass |
| `ipred` | Indirect Predictor Barrier support |
| `rrsba` | Restricted RSB Alternate (Intel Retbleed mitigation) |
| `bhi` | Branch History Injection mitigation support |
| `tsa_sq_no` | Not susceptible to TSA-SQ |
| `tsa_l1_no` | Not susceptible to TSA-L1 |
| `verw_clear` | VERW clears CPU buffers |
| `autoibrs` | AMD AutoIBRS (equivalent to enhanced IBRS on Intel) |
| `sbpb` | Selective Branch Predictor Barrier (AMD Inception mitigation) |
| `avx2` | AVX2 supported (relevant to Downfall / GDS) |
| `avx512` | AVX-512 supported (relevant to Downfall / GDS) |
---
### `cpu_microcode`
Microcode version and status. `null` under the same conditions as `cpu`.
| Field | Type | Values | Meaning |
|---|---|---|---|
| `installed_version` | string \| null | hex, e.g. `"0xf4"` | Currently running microcode revision |
| `latest_version` | string \| null | hex | Latest known-good version in the firmware database; null if CPU is not in the database |
| `microcode_up_to_date` | boolean \| null | | Whether `installed_version == latest_version`; null if either is unavailable |
| `is_blacklisted` | boolean | | Whether the installed microcode is known to cause instability and must be rolled back |
| `message` | string \| null | | Human-readable note from the firmware database (e.g. changelog excerpt) |
| `db_source` | string \| null | | Which database was used (e.g. `"Intel-SA"`, `"MCExtractor"`) |
| `db_info` | string \| null | | Database revision or date |
**`is_blacklisted: true`** means the installed microcode is known to cause
system instability or incorrect behaviour. Treat this as a P1 incident: roll
back to the previous microcode immediately.
**`microcode_up_to_date: false`** means a newer microcode is available. This
does not necessarily mean the system is vulnerable (the current microcode may
still include all required mitigations), but warrants investigation.
---
### `vulnerabilities`
Array of CVE check results. One object per checked CVE, in check order.
Empty array (`[]`) if no CVEs were checked (unusual; would require `--cve`
with an unknown CVE ID).
| Field | Type | Values | Meaning |
|---|---|---|---|
| `cve` | string | e.g. `"CVE-2017-5753"` | CVE identifier |
| `name` | string | e.g. `"SPECTRE VARIANT 1"` | Short key name used in batch formats |
| `aliases` | string \| null | e.g. `"Spectre Variant 1, bounds check bypass"` | Full name including all known aliases |
| `cpu_affected` | boolean | | Whether this CPU's hardware design is affected by this CVE |
| `status` | string | `"OK"` / `"VULN"` / `"UNK"` | Check outcome (see below) |
| `vulnerable` | boolean \| null | `false` / `true` / `null` | `false`=OK, `true`=VULN, `null`=UNK |
| `info` | string | | Human-readable description of the specific mitigation state or reason |
| `sysfs_status` | string \| null | `"OK"` / `"VULN"` / `"UNK"` / null | Status as reported by the kernel via `/sys/devices/system/cpu/vulnerabilities/`; null if sysfs was not consulted for this CVE, or if the CVE's check read sysfs in silent/quiet mode (raw message is still captured in `sysfs_message`) |
| `sysfs_message` | string \| null | | Raw text from the sysfs file (e.g. `"Mitigation: PTI"`); null if sysfs was not consulted |
#### Status values
| `status` | `vulnerable` | Meaning |
|---|---|---|
| `"OK"` | `false` | CPU is unaffected by design, or all required mitigations are in place |
| `"VULN"` | `true` | CPU is affected and mitigations are missing or insufficient |
| `"UNK"` | `null` | The script could not determine the status (missing kernel info, insufficient privileges, or no detection logic for this platform) |
#### `cpu_affected` explained
`cpu_affected: false` with `status: "OK"` means the CPU hardware is
architecturally immune, no patch was ever needed.
`cpu_affected: true` with `status: "OK"` means the hardware has the weakness
but all required mitigations (kernel, microcode, or both) are in place.
This distinction matters for fleet auditing: filter on `cpu_affected: true` to
see only systems where mitigation effort was actually required and confirmed.
#### `sysfs_status` vs `status`
`sysfs_status` is the raw kernel self-report. `status` is the script's
independent assessment, which may differ:
- The script may **upgrade** a sysfs `"VULN"` to `"OK"` when it detects a
silent backport that the kernel doesn't know about.
- The script may **downgrade** a sysfs `"OK"` to `"VULN"` when it detects an
incomplete mitigation the kernel doesn't flag (e.g. L1TF on a hypervisor
host with SMT still enabled, or TSA in `user` mode on a VMM host).
- `sysfs_status` is `null` when the kernel has no sysfs entry for this CVE
(older kernels, or CVEs not yet tracked by the kernel).
Always use `status` / `vulnerable` for alerting. Use `sysfs_status` for
diagnostics and audit trails.
**Example:**
```json
{
"cve": "CVE-2017-5715",
"name": "SPECTRE VARIANT 2",
"aliases": "Spectre Variant 2, branch target injection",
"cpu_affected": true,
"status": "OK",
"vulnerable": false,
"info": "Full generic retpoline is mitigating the vulnerability",
"sysfs_status": "OK",
"sysfs_message": "Mitigation: Retpolines; IBPB: conditional; IBRS_FW; STIBP: conditional; RSB filling; PBRSB-eIBRS: Not affected; BHI: Not affected"
}
```
---
## Exit codes
The script exits with:
| Code | Meaning |
|---|---|
| `0` | All checked CVEs are `OK` |
| `2` | At least one CVE is `VULN` |
| `3` | No CVEs are `VULN`, but at least one is `UNK` |
These exit codes are the same in all batch modes and in interactive mode.
Use them in combination with the JSON body for reliable alerting.
---
## Caveats and edge cases
**No-runtime mode (`--no-runtime`)**
`system.kernel_release`, `kernel_version`, and `kernel_arch` are null (those
come from `uname`, which reports the running kernel, not the inspected one).
`meta.mode: "no-runtime"` signals this. `system.kernel_image` and
`system.kernel_version_string` carry the inspected image path and banner
instead.
**No-hardware mode (`--no-hw`)**
`cpu` and `cpu_microcode` are null. CVE checks that rely on hardware
capability detection (`cap_*` flags, MSR reads) will report `status: "UNK"`.
`cpu_affected` will be `false` for all CVEs (cannot determine affection without
hardware info). `meta.mode: "no-hw"` signals this.
**Hardware-only mode (`--hw-only`)**
Only CPU information and per-CVE affectedness are reported. No kernel
inspection is performed, so vulnerability mitigations are not checked.
`meta.mode: "hw-only"` signals this.
**`--sysfs-only`**
The script trusts the kernel's sysfs report without running independent
detection. `meta.sysfs_only: true` flags this. Some older kernels misreport
their status. Do not use for production fleet monitoring.
**`--paranoid`**
Enables defense-in-depth checks beyond the security community consensus.
A `status: "OK"` under `paranoid: true` means a higher bar was met. Do not
compare results across hosts with different `paranoid` values.
**`reduced_accuracy`**
Set when the kernel image, config file, or System.map could not be read.
Some checks fall back to weaker heuristics and may report `"UNK"` for CVEs
that are actually mitigated.
**Non-x86 architectures (ARM, ARM64)**
On ARM, `cpu.arch` is `"arm"` and the `cpu.arm` sub-object carries `part_list`
and `arch_list`. The x86-specific sub-object is absent (no null noise).
`cpu.arm.capabilities` is currently empty; ARM-specific flags will be added
there as needed.
**`mocked: true`**
Must never appear on a production host. If it does, the results are
fabricated and every downstream alert is unreliable.
---
## Schema stability
`meta.format_version` is incremented on backward-incompatible changes (field
removal or type change). Additive changes (new fields) do not increment the
version; consumers must tolerate unknown fields.
Recommended practice: check `format_version == 1` at parse time and reject
or alert on any other value until you have tested compatibility with the new
version.
---
## Migration from `json-terse`
The legacy `--batch json-terse` format emits a flat array of objects:
```json
[
{"NAME": "SPECTRE VARIANT 1", "CVE": "CVE-2017-5753", "VULNERABLE": false, "INFOS": "..."},
...
]
```
It carries no system, CPU, or microcode context. It has no sysfs data. It
uses uppercase field names.
To migrate:
1. Replace `--batch json-terse` with `--batch json`.
2. The equivalent of the old `VULNERABLE` field is `vulnerabilities[].vulnerable`.
3. The equivalent of the old `INFOS` field is `vulnerabilities[].info`.
4. The equivalent of the old `NAME` field is `vulnerabilities[].name`.
5. The old format is still available as `--batch json-terse` for transition
periods.

View File

@@ -1,382 +0,0 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://github.com/speed47/spectre-meltdown-checker/dist/batch_json.schema.json",
"title": "spectre-meltdown-checker --batch json output",
"description": "Schema for the comprehensive JSON output produced by spectre-meltdown-checker.sh --batch json. format_version 1.",
"type": "object",
"required": ["meta", "system", "cpu", "cpu_microcode", "vulnerabilities"],
"additionalProperties": false,
"properties": {
"meta": {
"description": "Run metadata and option flags.",
"type": "object",
"required": [
"script_version", "format_version", "timestamp", "os", "mode",
"run_as_root", "reduced_accuracy", "paranoid", "sysfs_only",
"extra", "mocked"
],
"additionalProperties": false,
"properties": {
"script_version": {
"description": "Script version string, e.g. '25.30.0250400123'.",
"type": ["string", "null"]
},
"format_version": {
"description": "JSON schema version. Incremented on backward-incompatible changes. Current value: 1.",
"type": "integer",
"const": 1
},
"timestamp": {
"description": "ISO 8601 UTC timestamp of when the scan started, e.g. '2025-04-07T12:00:00Z'.",
"type": ["string", "null"]
},
"os": {
"description": "Operating system name from uname -s, e.g. 'Linux', 'FreeBSD'.",
"type": ["string", "null"]
},
"mode": {
"description": "Operating mode: 'live' (default), 'no-runtime' (--no-runtime), 'no-hw' (--no-hw), or 'hw-only' (--hw-only).",
"type": "string",
"enum": ["live", "no-runtime", "no-hw", "hw-only"]
},
"run_as_root": {
"description": "Whether the script ran as root. Non-root scans skip MSR reads and may produce incomplete or inaccurate results.",
"type": "boolean"
},
"reduced_accuracy": {
"description": "True when the kernel image, config, or System.map was missing. Some checks fall back to weaker heuristics.",
"type": ["boolean", "null"]
},
"paranoid": {
"description": "True when --paranoid was set: stricter criteria (e.g. requires SMT disabled, IBPB always-on).",
"type": "boolean"
},
"sysfs_only": {
"description": "True when --sysfs-only was set: the script trusted the kernel's own sysfs report without independent detection.",
"type": "boolean"
},
"extra": {
"description": "True when --extra was set: additional experimental checks were enabled.",
"type": "boolean"
},
"mocked": {
"description": "True when one or more CPU values were overridden for testing. Results do NOT reflect the real system.",
"type": ["boolean", "null"]
}
}
},
"system": {
"description": "Kernel and host environment context.",
"type": ["object", "null"],
"required": [
"kernel_release", "kernel_version", "kernel_arch",
"kernel_image", "kernel_config", "kernel_version_string",
"kernel_cmdline", "cpu_count", "smt_enabled",
"hypervisor_host", "hypervisor_host_reason"
],
"additionalProperties": false,
"properties": {
"kernel_release": {
"description": "Output of uname -r (live mode only), e.g. '6.1.0-21-amd64'. Null in other modes.",
"type": ["string", "null"]
},
"kernel_version": {
"description": "Output of uname -v (live mode only), e.g. '#1 SMP Debian …'. Null in other modes.",
"type": ["string", "null"]
},
"kernel_arch": {
"description": "Output of uname -m (live mode only), e.g. 'x86_64'. Null in other modes.",
"type": ["string", "null"]
},
"kernel_image": {
"description": "Path to the kernel image passed via --kernel. Null in live mode.",
"type": ["string", "null"]
},
"kernel_config": {
"description": "Path to the kernel config passed via --config. Null if not provided.",
"type": ["string", "null"]
},
"kernel_version_string": {
"description": "Kernel version banner extracted from the image. Null if unavailable.",
"type": ["string", "null"]
},
"kernel_cmdline": {
"description": "Kernel command line from /proc/cmdline (live mode) or the image. Null if unavailable.",
"type": ["string", "null"]
},
"cpu_count": {
"description": "Number of logical CPUs detected (max core ID + 1). Null if undeterminable.",
"type": ["integer", "null"],
"minimum": 1
},
"smt_enabled": {
"description": "Whether SMT (HyperThreading) is currently enabled. Null if the script could not determine the state.",
"type": ["boolean", "null"]
},
"hypervisor_host": {
"description": "Whether this machine is detected as a VM host (running KVM, Xen, VMware, etc.). Null if undeterminable.",
"type": ["boolean", "null"]
},
"hypervisor_host_reason": {
"description": "Human-readable explanation of why hypervisor_host was set. Null if hypervisor_host is false or null.",
"type": ["string", "null"]
}
}
},
"cpu": {
"description": "CPU hardware identification. Null when --no-hw is active or when --arch-prefix is set (host CPU info is then suppressed to avoid mixing with a different-arch target kernel). Contains an 'arch' discriminator ('x86' or 'arm') and a matching arch-specific sub-object with identification fields and capabilities.",
"oneOf": [
{ "type": "null" },
{
"type": "object",
"description": "x86 CPU (Intel, AMD, Hygon).",
"required": ["arch", "vendor", "friendly_name", "x86"],
"additionalProperties": false,
"properties": {
"arch": { "type": "string", "const": "x86" },
"vendor": {
"description": "CPU vendor string: 'GenuineIntel', 'AuthenticAMD', or 'HygonGenuine'.",
"type": ["string", "null"]
},
"friendly_name": {
"description": "Human-readable CPU model from /proc/cpuinfo, e.g. 'Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz'.",
"type": ["string", "null"]
},
"x86": {
"type": "object",
"required": ["family", "model", "stepping", "cpuid", "platform_id", "hybrid", "codename", "capabilities"],
"additionalProperties": false,
"properties": {
"family": {
"description": "CPU family number.",
"type": ["integer", "null"]
},
"model": {
"description": "CPU model number.",
"type": ["integer", "null"]
},
"stepping": {
"description": "CPU stepping number.",
"type": ["integer", "null"]
},
"cpuid": {
"description": "Full CPUID leaf 1 EAX value as a hex string, e.g. '0x000906ed'.",
"type": ["string", "null"],
"pattern": "^0x[0-9a-f]+$"
},
"platform_id": {
"description": "Intel platform ID from MSR 0x17. Null on AMD.",
"type": ["integer", "null"]
},
"hybrid": {
"description": "Whether this is a hybrid CPU (P-cores + E-cores, e.g. Alder Lake). Null if undeterminable.",
"type": ["boolean", "null"]
},
"codename": {
"description": "Intel CPU codename, e.g. 'Coffee Lake'. Null on AMD.",
"type": ["string", "null"]
},
"capabilities": {
"description": "CPU feature flags detected via CPUID and MSR reads. Every value is tri-state: true=present, false=absent, null=not applicable or unreadable.",
"type": "object",
"additionalProperties": false,
"properties": {
"spec_ctrl": { "type": ["boolean", "null"], "description": "SPEC_CTRL MSR present (Intel; enables IBRS + IBPB via WRMSR)" },
"ibrs": { "type": ["boolean", "null"], "description": "IBRS supported (via SPEC_CTRL, IBRS_SUPPORT, or cpuinfo fallback)" },
"ibpb": { "type": ["boolean", "null"], "description": "IBPB supported (via SPEC_CTRL, IBPB_SUPPORT, or cpuinfo fallback)" },
"ibpb_ret": { "type": ["boolean", "null"], "description": "IBPB on return (enhanced form)" },
"stibp": { "type": ["boolean", "null"], "description": "STIBP supported (Intel/AMD/HYGON or cpuinfo fallback)" },
"ssbd": { "type": ["boolean", "null"], "description": "SSBD supported (SPEC_CTRL, VIRT_SPEC_CTRL, non-architectural MSR, or cpuinfo fallback)" },
"l1d_flush": { "type": ["boolean", "null"], "description": "L1D cache flush instruction" },
"md_clear": { "type": ["boolean", "null"], "description": "VERW clears CPU buffers (MDS mitigation)" },
"arch_capabilities": { "type": ["boolean", "null"], "description": "IA32_ARCH_CAPABILITIES MSR is present" },
"rdcl_no": { "type": ["boolean", "null"], "description": "Not susceptible to RDCL (Meltdown-like attacks)" },
"ibrs_all": { "type": ["boolean", "null"], "description": "Enhanced IBRS always-on mode supported" },
"rsba": { "type": ["boolean", "null"], "description": "RSB may use return predictions from outside the RSB" },
"l1dflush_no": { "type": ["boolean", "null"], "description": "Not susceptible to L1D flush side-channel" },
"ssb_no": { "type": ["boolean", "null"], "description": "Not susceptible to Speculative Store Bypass" },
"mds_no": { "type": ["boolean", "null"], "description": "Not susceptible to MDS" },
"taa_no": { "type": ["boolean", "null"], "description": "Not susceptible to TSX Asynchronous Abort" },
"pschange_msc_no": { "type": ["boolean", "null"], "description": "Page-size-change MSC not susceptible" },
"tsx_ctrl_msr": { "type": ["boolean", "null"], "description": "TSX_CTRL MSR is present" },
"tsx_ctrl_rtm_disable": { "type": ["boolean", "null"], "description": "RTM disabled via TSX_CTRL" },
"tsx_ctrl_cpuid_clear": { "type": ["boolean", "null"], "description": "CPUID HLE/RTM bits cleared via TSX_CTRL" },
"gds_ctrl": { "type": ["boolean", "null"], "description": "GDS_CTRL MSR present" },
"gds_no": { "type": ["boolean", "null"], "description": "Not susceptible to Gather Data Sampling" },
"gds_mitg_dis": { "type": ["boolean", "null"], "description": "GDS mitigation disabled" },
"gds_mitg_lock": { "type": ["boolean", "null"], "description": "GDS mitigation locked" },
"rfds_no": { "type": ["boolean", "null"], "description": "Not susceptible to Register File Data Sampling" },
"rfds_clear": { "type": ["boolean", "null"], "description": "VERW clears register file stale data" },
"its_no": { "type": ["boolean", "null"], "description": "Not susceptible to Indirect Target Selection" },
"sbdr_ssdp_no": { "type": ["boolean", "null"], "description": "Not susceptible to SBDR/SSDP" },
"fbsdp_no": { "type": ["boolean", "null"], "description": "Not susceptible to FBSDP" },
"psdp_no": { "type": ["boolean", "null"], "description": "Not susceptible to PSDP" },
"fb_clear": { "type": ["boolean", "null"], "description": "Fill buffer cleared on idle/C6" },
"rtm": { "type": ["boolean", "null"], "description": "Restricted Transactional Memory (TSX RTM) present" },
"tsx_force_abort": { "type": ["boolean", "null"], "description": "TSX_FORCE_ABORT MSR present" },
"tsx_force_abort_rtm_disable": { "type": ["boolean", "null"], "description": "RTM disabled via TSX_FORCE_ABORT" },
"tsx_force_abort_cpuid_clear": { "type": ["boolean", "null"], "description": "CPUID RTM cleared via TSX_FORCE_ABORT" },
"sgx": { "type": ["boolean", "null"], "description": "Software Guard Extensions present" },
"srbds": { "type": ["boolean", "null"], "description": "SRBDS affected" },
"srbds_on": { "type": ["boolean", "null"], "description": "SRBDS mitigation active" },
"amd_ssb_no": { "type": ["boolean", "null"], "description": "AMD: not susceptible to Speculative Store Bypass" },
"hygon_ssb_no": { "type": ["boolean", "null"], "description": "Hygon: not susceptible to Speculative Store Bypass" },
"ipred": { "type": ["boolean", "null"], "description": "Indirect Predictor Barrier support" },
"rrsba": { "type": ["boolean", "null"], "description": "Restricted RSB Alternate (Intel Retbleed mitigation)" },
"bhi": { "type": ["boolean", "null"], "description": "Branch History Injection mitigation support" },
"tsa_sq_no": { "type": ["boolean", "null"], "description": "Not susceptible to TSA-SQ" },
"tsa_l1_no": { "type": ["boolean", "null"], "description": "Not susceptible to TSA-L1" },
"verw_clear": { "type": ["boolean", "null"], "description": "VERW clears CPU buffers" },
"autoibrs": { "type": ["boolean", "null"], "description": "AMD AutoIBRS (equivalent to enhanced IBRS on Intel)" },
"sbpb": { "type": ["boolean", "null"], "description": "Selective Branch Predictor Barrier (AMD Inception mitigation): true if PRED_CMD MSR SBPB bit write succeeded; false if write failed; null if not verifiable (non-root, CPUID error, or CPU does not report SBPB support)" },
"avx2": { "type": ["boolean", "null"], "description": "AVX2 supported (relevant to Downfall / GDS)" },
"avx512": { "type": ["boolean", "null"], "description": "AVX-512 supported (relevant to Downfall / GDS)" }
}
}
}
}
}
},
{
"type": "object",
"description": "ARM CPU (ARM, Cavium, Phytium).",
"required": ["arch", "vendor", "friendly_name", "arm"],
"additionalProperties": false,
"properties": {
"arch": { "type": "string", "const": "arm" },
"vendor": {
"description": "CPU vendor string: 'ARM', 'CAVIUM', or 'PHYTIUM'.",
"type": ["string", "null"]
},
"friendly_name": {
"description": "Human-readable CPU model, e.g. 'ARM v8 model 0xd0b'.",
"type": ["string", "null"]
},
"arm": {
"type": "object",
"required": ["part_list", "arch_list", "capabilities"],
"additionalProperties": false,
"properties": {
"part_list": {
"description": "Space-separated list of ARM part numbers detected across cores, e.g. '0xd0b 0xd05' (big.LITTLE).",
"type": ["string", "null"]
},
"arch_list": {
"description": "Space-separated list of ARM architecture levels detected across cores, e.g. '8 8'.",
"type": ["string", "null"]
},
"capabilities": {
"description": "ARM-specific CPU capability flags. Currently empty; reserved for future use.",
"type": "object",
"additionalProperties": false,
"properties": {}
}
}
}
}
}
]
},
"cpu_microcode": {
"description": "Microcode version and firmware database status. Null under the same conditions as cpu.",
"type": ["object", "null"],
"required": [
"installed_version", "latest_version", "microcode_up_to_date",
"is_blacklisted", "message", "db_source", "db_info"
],
"additionalProperties": false,
"properties": {
"installed_version": {
"description": "Currently running microcode revision as a hex string, e.g. '0xf4'. Null if unreadable.",
"type": ["string", "null"],
"pattern": "^0x[0-9a-f]+$"
},
"latest_version": {
"description": "Latest known-good microcode version from the firmware database, as a hex string. Null if the CPU is not in the database.",
"type": ["string", "null"],
"pattern": "^0x[0-9a-f]+$"
},
"microcode_up_to_date": {
"description": "True when installed_version equals latest_version. Null if either is unavailable.",
"type": ["boolean", "null"]
},
"is_blacklisted": {
"description": "True when the installed microcode is known to cause instability and must be rolled back immediately.",
"type": "boolean"
},
"message": {
"description": "Human-readable note from the firmware database (e.g. changelog excerpt). Null if absent.",
"type": ["string", "null"]
},
"db_source": {
"description": "Which firmware database was used, e.g. 'Intel-SA', 'MCExtractor'. Null if unavailable.",
"type": ["string", "null"]
},
"db_info": {
"description": "Firmware database revision or date string. Null if unavailable.",
"type": ["string", "null"]
}
}
},
"vulnerabilities": {
"description": "Array of CVE check results, one per checked CVE, in check order.",
"type": "array",
"items": {
"type": "object",
"required": [
"cve", "name", "aliases", "cpu_affected",
"status", "vulnerable", "info",
"sysfs_status", "sysfs_message"
],
"additionalProperties": false,
"properties": {
"cve": {
"description": "CVE identifier, e.g. 'CVE-2017-5753'. May be 'CVE-0000-0001' for non-CVE checks such as SLS.",
"type": "string",
"pattern": "^CVE-[0-9]{4}-[0-9]+$"
},
"name": {
"description": "Short key name used across batch formats, e.g. 'SPECTRE VARIANT 1'.",
"type": "string"
},
"aliases": {
"description": "Full name including all known aliases, e.g. 'Spectre Variant 1, bounds check bypass'. Null if not in the registry.",
"type": ["string", "null"]
},
"cpu_affected": {
"description": "Whether this CPU's hardware design is affected by this CVE. False when hardware is architecturally immune.",
"type": "boolean"
},
"status": {
"description": "Check outcome: 'OK'=not vulnerable or unaffected, 'VULN'=vulnerable, 'UNK'=could not determine.",
"type": "string",
"enum": ["OK", "VULN", "UNK"]
},
"vulnerable": {
"description": "Boolean encoding of status: false=OK, true=VULN, null=UNK.",
"type": ["boolean", "null"]
},
"info": {
"description": "Human-readable description of the specific mitigation state or reason for the verdict.",
"type": "string"
},
"sysfs_status": {
"description": "Status as reported by the kernel via /sys/devices/system/cpu/vulnerabilities/. Null if sysfs was not consulted for this CVE (older kernels, or CVE not tracked by the kernel).",
"type": ["string", "null"],
"enum": ["OK", "VULN", "UNK", null]
},
"sysfs_message": {
"description": "Raw text from the sysfs vulnerability file, e.g. 'Mitigation: PTI'. Null if sysfs was not consulted.",
"type": ["string", "null"]
}
}
}
}
}
}

154
dist/doc/batch_nrpe.md vendored
View File

@@ -1,154 +0,0 @@
# NRPE Output Format
`--batch nrpe` produces output that conforms to the
[Nagios Plugin Development Guidelines](https://nagios-plugins.org/doc/guidelines.html),
making it directly consumable by Nagios, Icinga, Zabbix (via NRPE), and
compatible monitoring stacks.
```sh
sudo ./spectre-meltdown-checker.sh --batch nrpe
```
## Output structure
The plugin emits one mandatory status line followed by optional long output:
```
STATUS: summary | checked=N vulnerable=N unknown=N
NOTE: ... ← context notes (when applicable)
[CRITICAL] CVE-XXXX-YYYY (NAME): description
[UNKNOWN] CVE-XXXX-YYYY (NAME): description
```
### Line 1 (status line)
Always present. Parsed by every Nagios-compatible monitoring system.
```
STATUS: summary | perfdata
```
| Field | Values | Meaning |
|---|---|---|
| `STATUS` | `OK` / `CRITICAL` / `UNKNOWN` | Overall check outcome (see below) |
| `summary` | human-readable string | Count and CVE IDs of affected checks |
| `perfdata` | `checked=N vulnerable=N unknown=N` | Machine-readable counters for graphing |
#### Status values
| Status | Exit code | Condition |
|---|---|---|
| `OK` | `0` | All CVE checks passed |
| `CRITICAL` | `2` | At least one CVE is vulnerable |
| `UNKNOWN` | `3` | No VULN found, but at least one check is inconclusive **or** the script was not run as root and found apparent vulnerabilities (see below) |
#### Summary format
| Condition | Summary |
|---|---|
| All OK | `All N CVE checks passed` |
| VULN only | `N/T CVE(s) vulnerable: CVE-A CVE-B ...` |
| VULN + UNK | `N/T CVE(s) vulnerable: CVE-A CVE-B ..., M inconclusive` |
| UNK only | `N/T CVE checks inconclusive` |
| Non-root + VULN | `N/T CVE(s) appear vulnerable (unconfirmed, not root): CVE-A ...` |
| Non-root + VULN + UNK | `N/T CVE(s) appear vulnerable (unconfirmed, not root): CVE-A ..., M inconclusive` |
### Lines 2+ (long output)
Shown in the detail/extended info view of most monitoring frontends.
Never parsed by the monitoring core; safe to add or reorder.
#### Context notes
Printed before per-CVE details when applicable. Notes are emitted in this
order when more than one applies:
| Note | Condition |
|---|---|
| `NOTE: paranoid mode active, stricter mitigation requirements applied` | `--paranoid` was used |
| `NOTE: hypervisor host detected (reason); L1TF/MDS severity is elevated` | System is detected as a VM host (KVM, Xen, VMware…) |
| `NOTE: not a hypervisor host` | System is confirmed not a VM host |
| `NOTE: not running as root; MSR reads skipped, results may be incomplete` | Script ran without root privileges |
When VMM detection did not run (e.g. `--no-hw`), neither the
`hypervisor host detected` nor the `not a hypervisor host` note is printed.
#### Per-CVE detail lines
One line per non-OK CVE. VULN entries (`[CRITICAL]`) appear before UNK
entries (`[UNKNOWN]`); within each group the order follows the CVE registry.
```
[CRITICAL] CVE-XXXX-YYYY (SHORT NAME): mitigation status description
[UNKNOWN] CVE-XXXX-YYYY (SHORT NAME): reason check was inconclusive
```
## Exit codes
| Code | Nagios meaning | Condition |
|---|---|---|
| `0` | OK | All checked CVEs are mitigated or hardware-unaffected |
| `2` | CRITICAL | At least one CVE is vulnerable (script ran as root) |
| `3` | UNKNOWN | At least one check inconclusive, or apparent VULN found without root |
| `255` | - | Script error (bad arguments, unsupported platform) |
Exit code `1` (WARNING) is not used; there is no "degraded but acceptable"
state for CPU vulnerability mitigations.
## Non-root behaviour
Running without root privileges skips MSR reads and limits access to some
kernel interfaces. When the script finds apparent vulnerabilities without root:
- The status word becomes `UNKNOWN` instead of `CRITICAL`
- The exit code is `3` instead of `2`
- The summary says `appear vulnerable (unconfirmed, not root)`
- A `NOTE: not running as root` line is added to the long output
**Recommendation:** always run with `sudo` for authoritative results. A
`CRITICAL` from a root-run scan is a confirmed vulnerability; an `UNKNOWN`
from a non-root scan is a signal to investigate further.
## Hypervisor hosts
When `NOTE: hypervisor host detected` is present, L1TF (CVE-2018-3646) and
MDS (CVE-2018-12126/12130/12127) carry significantly higher risk because
they can be exploited across VM boundaries by a malicious guest. Prioritise
remediation on these hosts.
## Examples
**All mitigated (root):**
```
OK: All 31 CVE checks passed | checked=31 vulnerable=0 unknown=0
NOTE: not a hypervisor host
```
Exit: `0`
**Two CVEs vulnerable (root):**
```
CRITICAL: 2/31 CVE(s) vulnerable: CVE-2018-3615 CVE-2019-11135 | checked=31 vulnerable=2 unknown=0
NOTE: not a hypervisor host
[CRITICAL] CVE-2018-3615 (L1TF SGX): your CPU supports SGX and the microcode is not up to date
[CRITICAL] CVE-2019-11135 (TAA): Your kernel doesn't support TAA mitigation, update it
```
Exit: `2`
**Apparent vulnerabilities, non-root scan:**
```
UNKNOWN: 2/31 CVE(s) appear vulnerable (unconfirmed, not root): CVE-2018-3615 CVE-2019-11135 | checked=31 vulnerable=2 unknown=0
NOTE: not a hypervisor host
NOTE: not running as root; MSR reads skipped, results may be incomplete
[CRITICAL] CVE-2018-3615 (L1TF SGX): your CPU supports SGX and the microcode is not up to date
[CRITICAL] CVE-2019-11135 (TAA): Your kernel doesn't support TAA mitigation, update it
```
Exit: `3`
**Inconclusive checks, paranoid mode, VMM host:**
```
UNKNOWN: 3/31 CVE checks inconclusive | checked=31 vulnerable=0 unknown=3
NOTE: paranoid mode active, stricter mitigation requirements applied
NOTE: hypervisor host detected (kvm); L1TF/MDS severity is elevated
[UNKNOWN] CVE-2018-3646 (L1TF VMM): SMT is enabled on a hypervisor host, not mitigated under paranoid mode
```
Exit: `3`

View File

@@ -1,413 +0,0 @@
# Prometheus Batch Mode
`--batch prometheus` emits Prometheus text-format metrics that can be fed into any
Prometheus-compatible monitoring stack. It is designed for **fleet-scale security
monitoring**: run the script periodically on every host, push the output to a
Prometheus Pushgateway (or drop it into a node_exporter textfile directory), then
alert and dashboard from Prometheus/Grafana like any other infrastructure metric.
---
## Quick start
### Pushgateway (recommended for cron/batch fleet scans)
```sh
#!/bin/sh
PUSHGATEWAY="http://pushgateway.internal:9091"
INSTANCE=$(hostname -f)
spectre-meltdown-checker.sh --batch prometheus \
| curl --silent --show-error --data-binary @- \
"${PUSHGATEWAY}/metrics/job/smc/instance/${INSTANCE}"
```
Run this as root via cron or a systemd timer on every host. The Pushgateway
retains the last pushed value, so Prometheus scrapes it on its own schedule.
A stale-data alert (`smc_last_scan_timestamp_seconds`) catches hosts that stopped
reporting.
### node_exporter textfile collector
```sh
#!/bin/sh
TEXTFILE_DIR="/var/lib/node_exporter/textfile_collector"
TMP="${TEXTFILE_DIR}/smc.prom.$$"
spectre-meltdown-checker.sh --batch prometheus > "$TMP"
mv "$TMP" "${TEXTFILE_DIR}/smc.prom"
```
The atomic `mv` prevents node_exporter from reading a partially written file.
node_exporter must be started with `--collector.textfile.directory` pointing at
`TEXTFILE_DIR`.
---
## Metric reference
All metric names are prefixed `smc_` (spectre-meltdown-checker). All metrics
are **gauges**: they represent the state at the time of the scan, not a running
counter.
---
### `smc_build_info`
Script metadata. Always value `1`; all data is in labels.
| Label | Values | Meaning |
|---|---|---|
| `version` | string | Script version (e.g. `25.30.0250400123`) |
| `mode` | `live` / `no-runtime` / `no-hw` / `hw-only` | Operating mode (see below) |
| `run_as_root` | `true` / `false` | Whether the script ran as root. Non-root scans skip MSR reads and may miss mitigations |
| `paranoid` | `true` / `false` | `--paranoid` mode: stricter criteria (e.g. requires SMT disabled) |
| `sysfs_only` | `true` / `false` | `--sysfs-only` mode: only the kernel's own sysfs report was used, not independent detection |
| `reduced_accuracy` | `true` / `false` | Kernel information was incomplete (no kernel image, config, or map); some checks may be less precise |
| `mocked` | `true` / `false` | Debug/test mode: CPU values were overridden. Results do **not** reflect the real system |
**Example:**
```
smc_build_info{version="25.30.0250400123",mode="live",run_as_root="true",paranoid="false",sysfs_only="false",reduced_accuracy="false",mocked="false"} 1
```
**Important labels for fleet operators:**
- `run_as_root="false"` means the scan was incomplete. Treat those results as
lower confidence and alert separately.
- `sysfs_only="true"` means the script trusted the kernel's self-report without
independent verification. The kernel may be wrong about its own mitigation
status (known to happen on older kernels).
- `paranoid="true"` raises the bar: a host with `paranoid="true"` and
`vulnerable_count=0` is held to a higher standard than one with `paranoid="false"`.
Do not compare counts across hosts with different `paranoid` values.
- `mocked="true"` must never appear on a production host; if it does, the results
are fabricated and every downstream alert is unreliable.
---
### `smc_system_info`
Operating system and kernel metadata. Always value `1`.
Absent entirely when none of `kernel_release`, `kernel_arch`, or
`hypervisor_host` can be determined (e.g. non-live mode with no VMM detection).
Each label is emitted only when its value is known; missing labels are
omitted rather than set to an empty string.
| Label | Values | Meaning |
|---|---|---|
| `kernel_release` | string | Output of `uname -r`; emitted only in live mode |
| `kernel_arch` | string | Output of `uname -m`; emitted only in live mode |
| `hypervisor_host` | `true` / `false` | Whether this machine is detected as a hypervisor host (running KVM, Xen, VMware, etc.); absent when VMM detection did not run (e.g. `--no-hw`) |
**Example:**
```
smc_system_info{kernel_release="5.15.0-100-generic",kernel_arch="x86_64",hypervisor_host="false"} 1
```
**`hypervisor_host`** materially changes the risk profile of several CVEs.
L1TF (CVE-2018-3646) and MDS (CVE-2018-12126/12130/12127) are significantly more
severe on hypervisor hosts because they can be exploited across VM boundaries by
a malicious guest. Always prioritise remediation on hosts where
`hypervisor_host="true"`.
---
### `smc_cpu_info`
CPU hardware and microcode metadata. Always value `1`. Absent when `--no-hw`
is used or when `--arch-prefix` is set (host CPU info is suppressed to avoid
mixing with a different-arch target kernel).
Common labels (always emitted when the data is available):
| Label | Values | Meaning |
|---|---|---|
| `vendor` | string | CPU vendor (e.g. `GenuineIntel`, `AuthenticAMD`, `HygonGenuine`, `ARM`) |
| `model` | string | CPU friendly name from `/proc/cpuinfo` |
| `arch` | `x86` / `arm` | Architecture family; determines which arch-specific labels follow |
| `smt` | `true` / `false` | Whether SMT (HyperThreading) is currently enabled; absent if undeterminable |
| `microcode` | hex string | Installed microcode version (e.g. `0xf4`); absent if unreadable |
| `microcode_latest` | hex string | Latest known-good microcode version from the firmware database; absent if the CPU is not in the database |
| `microcode_up_to_date` | `true` / `false` | Whether `microcode == microcode_latest`; absent if either is unavailable |
| `microcode_blacklisted` | `true` / `false` | Whether the installed microcode is known to cause problems and should be rolled back; emitted whenever `microcode` is emitted |
x86-only labels (emitted when `arch="x86"`):
| Label | Values | Meaning |
|---|---|---|
| `family` | integer string | CPU family number |
| `model_id` | integer string | CPU model number |
| `stepping` | integer string | CPU stepping number |
| `cpuid` | hex string | Full CPUID value (e.g. `0x000906ed`) |
| `codename` | string | Intel CPU codename (e.g. `Coffee Lake`); absent on AMD/Hygon |
ARM-only labels (emitted when `arch="arm"`):
| Label | Values | Meaning |
|---|---|---|
| `part_list` | string | Space-separated list of ARM part numbers across cores (e.g. `0xd0b 0xd05` on big.LITTLE) |
| `arch_list` | string | Space-separated list of ARM architecture levels across cores (e.g. `8 8`) |
**x86 example:**
```
smc_cpu_info{vendor="GenuineIntel",model="Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz",arch="x86",family="6",model_id="158",stepping="13",cpuid="0x000906ed",codename="Coffee Lake",smt="true",microcode="0xf4",microcode_latest="0xf4",microcode_up_to_date="true",microcode_blacklisted="false"} 1
```
**ARM example:**
```
smc_cpu_info{vendor="ARM",model="ARM v8 model 0xd0b",arch="arm",part_list="0xd0b 0xd05",arch_list="8 8",smt="false"} 1
```
**Microcode labels:**
- `microcode_up_to_date="false"` means a newer microcode is available in the
firmware database. This does not necessarily mean the system is vulnerable
(the current microcode may still provide all required mitigations), but it
warrants investigation.
- `microcode_blacklisted="true"` means the installed microcode is known to
cause system instability or incorrect behaviour and must be rolled back
immediately. Treat this as a P1 incident.
- `microcode_latest` may be absent if the CPU is not in the firmware database
(very new, very old, or exotic CPUs).
**`smt`** affects the risk level of several CVEs (MDS, L1TF). For those CVEs,
full mitigation requires disabling SMT in addition to kernel and microcode updates.
The script accounts for this in its status assessment; use this label to audit
which hosts still have SMT enabled.
---
### `smc_vulnerability_status`
One time series per CVE. The **numeric value** encodes the check result:
| Value | Meaning |
|---|---|
| `0` | Not vulnerable (CPU is unaffected by design, or all required mitigations are in place) |
| `1` | Vulnerable (mitigations are missing or insufficient) |
| `2` | Unknown (the script could not determine the status, e.g. due to missing kernel info or insufficient privileges) |
| Label | Values | Meaning |
|---|---|---|
| `cve` | CVE ID string | The CVE identifier (e.g. `CVE-2017-5753`) |
| `name` | string | Human-readable CVE name and aliases (e.g. `Spectre Variant 1, bounds check bypass`) |
| `cpu_affected` | `true` / `false` | Whether this CPU's hardware design is concerned by this CVE |
**Example:**
```
smc_vulnerability_status{cve="CVE-2017-5753",name="Spectre Variant 1, bounds check bypass",cpu_affected="true"} 0
smc_vulnerability_status{cve="CVE-2017-5715",name="Spectre Variant 2, branch target injection",cpu_affected="true"} 1
smc_vulnerability_status{cve="CVE-2022-29900",name="Retbleed, arbitrary speculative code execution with return instructions (AMD)",cpu_affected="false"} 0
```
**`cpu_affected` explained:**
A value of `0` with `cpu_affected="false"` means the CPU hardware is architecturally
immune to this CVE, no patch was needed or applied.
A value of `0` with `cpu_affected="true"` means the CPU has the hardware weakness
but all required mitigations (kernel, microcode, or both) are in place.
This distinction is important when auditing a fleet: if you need to verify that
all at-risk systems are patched, filter on `cpu_affected="true"` to exclude
hardware-immune systems from the analysis.
---
### `smc_vulnerable_count`
Number of CVEs with status `1` (vulnerable) in this scan. Value is `0` when
no CVEs are vulnerable.
---
### `smc_unknown_count`
Number of CVEs with status `2` (unknown) in this scan. A non-zero value
typically means the scan lacked sufficient privileges or kernel information.
Treat unknown the same as vulnerable for alerting purposes.
---
### `smc_last_scan_timestamp_seconds`
Unix timestamp (seconds since epoch) when the scan completed. Use this to
detect hosts that have stopped reporting.
---
## Alerting rules
```yaml
groups:
- name: spectre_meltdown_checker
rules:
# Fire when any CVE is confirmed vulnerable
- alert: SMCVulnerable
expr: smc_vulnerable_count > 0
for: 0m
labels:
severity: critical
annotations:
summary: "{{ $labels.instance }} has {{ $value }} vulnerable CVE(s)"
description: >
Run spectre-meltdown-checker.sh interactively on {{ $labels.instance }}
for remediation guidance.
# Fire when status is unknown (usually means scan ran without root)
- alert: SMCUnknown
expr: smc_unknown_count > 0
for: 0m
labels:
severity: warning
annotations:
summary: "{{ $labels.instance }} has {{ $value }} CVE(s) with unknown status"
description: >
Ensure the checker runs as root on {{ $labels.instance }}.
# Fire when a host stops reporting (scan not run in 8 days)
- alert: SMCScanStale
expr: time() - smc_last_scan_timestamp_seconds > 8 * 86400
for: 0m
labels:
severity: warning
annotations:
summary: "{{ $labels.instance }} has not reported scan results in 8 days"
# Fire when installed microcode is known-bad
- alert: SMCMicrocodeBlacklisted
expr: smc_cpu_info{microcode_blacklisted="true"} == 1
for: 0m
labels:
severity: critical
annotations:
summary: "{{ $labels.instance }} is running blacklisted microcode"
description: >
The installed microcode ({{ $labels.microcode }}) is known to cause
instability. Roll back to the previous version immediately.
# Fire when scan ran without root (results may be incomplete)
- alert: SMCScanNotRoot
expr: smc_build_info{run_as_root="false"} == 1
for: 0m
labels:
severity: warning
annotations:
summary: "{{ $labels.instance }} scan ran without root privileges"
# Fire when mocked data is detected on a production host
- alert: SMCScanMocked
expr: smc_build_info{mocked="true"} == 1
for: 0m
labels:
severity: critical
annotations:
summary: "{{ $labels.instance }} scan results are mocked and unreliable"
```
---
## Useful PromQL queries
```promql
# All vulnerable CVEs across the fleet
smc_vulnerability_status == 1
# Vulnerable CVEs on hosts that are also hypervisor hosts (highest priority)
smc_vulnerability_status == 1
* on(instance) group_left(hypervisor_host)
smc_system_info{hypervisor_host="true"}
# Vulnerable CVEs on affected CPUs only (excludes hardware-immune systems)
smc_vulnerability_status{cpu_affected="true"} == 1
# Fleet-wide: how many hosts are vulnerable to each CVE
count by (cve, name) (smc_vulnerability_status == 1)
# Hosts with outdated microcode, with CPU model context
smc_cpu_info{microcode_up_to_date="false"}
# Hosts with SMT still enabled (relevant for MDS/L1TF remediation)
smc_cpu_info{smt="true"}
# For a specific CVE: hosts affected by hardware but fully mitigated
smc_vulnerability_status{cve="CVE-2018-3646", cpu_affected="true"} == 0
# Proportion of fleet that is fully clean (no vulnerable, no unknown)
(
count(smc_vulnerable_count == 0 and smc_unknown_count == 0)
/
count(smc_vulnerable_count >= 0)
)
# Hosts where scan ran without root, results less reliable
smc_build_info{run_as_root="false"}
# Hosts with sysfs_only mode, independent detection was skipped
smc_build_info{sysfs_only="true"}
# Vulnerable CVEs joined with kernel release for patch tracking
smc_vulnerability_status == 1
* on(instance) group_left(kernel_release)
smc_system_info
# Vulnerable CVEs joined with CPU model and microcode version
smc_vulnerability_status == 1
* on(instance) group_left(vendor, model, microcode, microcode_up_to_date)
smc_cpu_info
```
---
## Caveats and edge cases
**No-runtime mode (`--no-runtime`)**
`smc_system_info` will have no `kernel_release` or `kernel_arch` labels (those
come from `uname`, which reports the running kernel, not the inspected one).
`mode="no-runtime"` in `smc_build_info` signals this. No-runtime mode is
primarily useful for pre-deployment auditing, not fleet runtime monitoring.
**No-hardware mode (`--no-hw`)**
`smc_cpu_info` is not emitted. CPU and microcode labels are absent from all
queries. CVE checks that rely on hardware capability detection (`cap_*` flags,
MSR reads) will report `unknown` status. `mode="no-hw"` in `smc_build_info`
signals this.
**Cross-arch inspection (`--arch-prefix`)**
When a cross-arch toolchain prefix is passed, the script suppresses the host
CPU metadata so it does not get mixed with data from a different-arch target
kernel: `smc_cpu_info` is not emitted, the same as under `--no-hw`.
**Hardware-only mode (`--hw-only`)**
Only hardware detection is performed; CVE checks are skipped. `smc_cpu_info`
is emitted but no `smc_vulnerability_status` metrics appear (and
`smc_vulnerable_count` / `smc_unknown_count` are `0`). `mode="hw-only"` in
`smc_build_info` signals this.
**`--sysfs-only`**
The script trusts the kernel's sysfs report (`/sys/devices/system/cpu/vulnerabilities/`)
without running its own independent detection. Some older kernels are known to
misreport their mitigation status. `sysfs_only="true"` in `smc_build_info`
flags this condition. Do not use `--sysfs-only` for production fleet monitoring.
**`--paranoid`**
Enables defense-in-depth checks beyond the security community consensus (e.g.
requires SMT to be disabled, IBPB always-on). A host is only `vulnerable_count=0`
under `paranoid` if it meets this higher bar. Do not compare `vulnerable_count`
across hosts with different `paranoid` values.
**`reduced_accuracy`**
Set when the kernel image, config file, or System.map could not be read. Some
checks fall back to weaker heuristics and may report `unknown` for CVEs that are
actually mitigated. This typically happens when the script runs without root or
on a kernel with an inaccessible image.
**Label stability**
Prometheus identifies time series by their full label set. If a script upgrade
adds or renames a label (e.g. a new `smc_cpu_info` label is added for a new CVE),
Prometheus will create a new time series and the old one will become stale. Plan
for this in long-retention dashboards by using `group_left` joins rather than
hardcoding label matchers.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

View File

@@ -1,9 +1,11 @@
# %%% ENDOFINTELDB
# vim: set ts=4 sw=4 sts=4 et:
# Merged INTELDB: HTML (authoritative) + CSV history (supplementary) + XLSX (legacy/stale)
# HTML source: https://www.intel.com/content/www/us/en/developer/topic-technology/software-security-guidance/processors-affected-consolidated-product-cpu-model.html
# CSV source: https://github.com/intel/Intel-affected-processor-list
# XSLX source: https://software.intel.com/content/dam/www/public/us/en/documents/affected-processors-transient-execution-attacks-by-cpu-aug02.xlsx
# Dump from Intel affected CPU page:
# - https://www.intel.com/content/www/us/en/developer/topic-technology/software-security-guidance/processors-affected-consolidated-product-cpu-model.html
# Only currently-supported CPUs are listed, so only rely on it if the current CPU happens to be in the list.
# We merge it with info from the following file:
# - https://software.intel.com/content/dam/www/public/us/en/documents/affected-processors-transient-execution-attacks-by-cpu-aug02.xlsx
# As it contains some information from older processors, however when information is contradictory between the two sources, the HTML takes precedence as
# it is expected to be updated, whereas the xslx seems to be frozen.
#
# N: Not affected
# S: Affected, software fix
@@ -11,20 +13,9 @@
# M: Affected, MCU update needed
# B: Affected, BIOS update needed
# X: Affected, no planned mitigation
# Y: Affected (no details available)
# MS: Affected, MCU + software fix
# HS: Affected, hardware + software fix
# HM: Affected, hardware + MCU fix
#
# Entries may have an optional hybrid qualifier after the CPUID:
# 0xCPUID,H=1,... matches only hybrid CPUs (CPUID.0x7.EDX[15]=1)
# 0xCPUID,H=0,... matches only non-hybrid CPUs (CPUID.0x7.EDX[15]=0)
# 0xCPUID,... matches any CPU (no qualifier = fallback)
# Y: Affected (this is from the xlsx, no details are available)
#
# %%% INTELDB
#
# XSLX
#
# 0x000206A7,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=N,2020-0543=N,
# 0x000206D6,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=N,2020-0543=N,
# 0x000206D7,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=N,2020-0543=N,
@@ -36,6 +27,8 @@
# 0x000306D4,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=Y,2020-0543=Y,
# 0x000306E4,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=N,2020-0543=N,
# 0x000306E7,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=N,2020-0543=N,
# 0x000306F2,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000306F4,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=N,2022-40982=N,
# 0x00040651,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=N,2020-0543=Y,
# 0x00040661,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=N,2020-0543=Y,
# 0x00040671,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=Y,2020-0543=Y,
@@ -44,110 +37,82 @@
# 0x000406C4,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=N,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x000406D8,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=N,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x000406E3,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=MS,
# 0x000406F1,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=N,2022-40982=N,
# 0x00050653,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=N,2022-40982=M,
# 0x00050654,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=N,2022-40982=M,
# 0x00050656,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=MS,2020-0543=N,2022-40982=M,
# 0x00050657,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=MS,2020-0543=N,2022-40982=M,
# 0x0005065A,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x0005065B,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x00050662,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=Y,2018-12130=Y,2018-12207=Y,2018-3615=Y,2018-3620=Y,2018-3639=Y,2018-3640=Y,2018-3646=Y,2019-11135=Y,2020-0543=N,
# 0x00050663,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=N,2022-40982=N,
# 0x00050664,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=N,2022-40982=N,
# 0x00050665,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=N,2022-40982=N,
# 0x000506A0,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=N,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x000506C9,2017-5715=MS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000506CA,2017-5715=MS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000506D0,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=N,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x000506E3,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=MS,2022-40982=N,
# 0x000506F1,2017-5715=MS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00060650,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=N,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x000606A0,2017-5715=Y,2017-5753=Y,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=Y,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x000606A4,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000606A5,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000606A6,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000606C1,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000606E1,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=N,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x0007065A,2017-5715=Y,2017-5753=Y,2017-5754=Y,2018-12126=Y,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=N,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x000706A1,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000706A8,2017-5715=MS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000706E5,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=HM,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x00080660,2017-5715=Y,2017-5753=Y,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=Y,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,
# 0x00080664,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00080665,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00080667,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000806A0,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=HM,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000806A1,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=HM,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000806C0,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000806C1,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000806C2,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000806D0,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000806D1,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000806E9,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=M,2022-40982=M,
# 0x000806EA,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=MS,2022-40982=M,
# 0x000806EB,2017-5715=MS,2017-5753=S,2017-5754=N,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=M,2018-3646=N,2019-11135=MS,2020-0543=MS,2022-40982=M,
# 0x000806EC,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=MS,2020-0543=MS,2022-40982=M,
# 0x000806F7,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000806F8,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00090660,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00090661,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00090670,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00090671,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00090672,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00090673,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00090674,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x00090675,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000906A0,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000906A2,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000906A3,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000906A4,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=MS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000906C0,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000906E9,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=MS,2022-40982=M,
# 0x000906EA,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=MS,2022-40982=M,
# 0x000906EB,2017-5715=MS,2017-5753=S,2017-5754=S,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=MS,2018-3620=MS,2018-3639=MS,2018-3640=M,2018-3646=MS,2019-11135=MS,2020-0543=MS,2022-40982=M,
# 0x000906EC,2017-5715=MS,2017-5753=S,2017-5754=N,2018-12126=MS,2018-12127=MS,2018-12130=MS,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=M,2018-3646=N,2019-11135=MS,2020-0543=MS,2022-40982=M,
# 0x000906ED,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=M,2018-3646=N,2019-11135=MS,2020-0543=MS,2022-40982=M,
# 0x000A0650,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=M,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000A0651,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=M,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000A0652,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=M,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000A0653,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=M,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000A0655,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=M,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000A0660,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=M,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000A0661,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=S,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=M,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000A0670,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000A0671,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=M,
# 0x000A0680,2017-5715=Y,2017-5753=Y,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=Y,2018-3615=N,2018-3620=N,2018-3639=Y,2018-3640=Y,2018-3646=N,2019-11135=N,2020-0543=N,
#
# HTML/CSV
#
# 0x000306F2,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=N,2022-29901=N,2022-28693=N,2022-21166=MS,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=N,2022-0002=N,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=X,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=X,2020-0551_zero=X,2020-0551_stale=X,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=S,2019-11135=N,2019-1125=S,2018-12127=MS,2018-12126=MS,2018-12130=MS,2018-3615=MS,2018-3620=MS,2018-3646=MS,2018-3639=MS,2018-3640=M,2017-5754=S,2017-5715=MS,2017-5753=S,
# 0x000306F4,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=N,2022-29901=N,2022-28693=N,2022-21166=MS,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=N,2022-0002=N,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=X,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=X,2020-0551_zero=X,2020-0551_stale=X,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=S,2019-11135=MS,2019-1125=S,2018-12127=MS,2018-12126=MS,2018-12130=MS,2018-3615=MS,2018-3620=MS,2018-3646=MS,2018-3639=MS,2018-3640=M,2017-5754=S,2017-5715=MS,2017-5753=S,
# 0x000406F1,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=N,2022-29901=N,2022-28693=N,2022-21166=MS,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=N,2022-0002=N,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=X,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=X,2020-0551_zero=X,2020-0551_stale=X,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=S,2019-11135=MS,2019-1125=S,2018-12127=MS,2018-12126=MS,2018-12130=MS,2018-3615=MS,2018-3620=MS,2018-3646=MS,2018-3639=MS,2018-3640=M,2017-5754=S,2017-5715=MS,2017-5753=S,
# 0x00050653,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=N,2022-29901=S,2022-28693=N,2022-21166=MS,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=N,2022-0002=N,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=X,2020-0551_stale=X,2020-0549=M,2020-8696=MS,2020-0548=MS,2018-12207=S,2019-11135=MS,2019-1125=S,2018-12127=MS,2018-12126=MS,2018-12130=MS,2018-3615=MS,2018-3620=MS,2018-3646=MS,2018-3639=MS,2018-3640=M,2017-5754=S,2017-5715=MS,2017-5753=S,
# 0x00050654,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=M,2022-26373=N,2022-21233=N,2022-29901=S,2022-28693=N,2022-21166=MS,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=N,2022-0002=N,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=X,2020-0551_stale=X,2020-0549=M,2020-8696=MS,2020-0548=MS,2018-12207=S,2019-11135=MS,2019-1125=S,2018-12127=MS,2018-12126=MS,2018-12130=MS,2018-3615=MS,2018-3620=MS,2018-3646=MS,2018-3639=MS,2018-3640=M,2017-5754=S,2017-5715=MS,2017-5753=S,
# 0x00050656,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=M,2022-26373=S,2022-21233=N,2022-38090=N,2022-29901=N,2022-28693=S,2022-21166=MS,2022-21125=N,2022-21123=N,2022-2118=N,2022-0001=S,2022-0002=S,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=M,2020-24512=N,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=X,2020-0551_stale=X,2020-0549=M,2020-8696=MS,2020-0548=MS,2018-12207=S,2019-11135=MS,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x00050657,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=M,2022-26373=S,2022-21233=N,2022-38090=N,2022-29901=N,2022-28693=S,2022-21166=MS,2022-21125=N,2022-21123=N,2022-2118=N,2022-0001=S,2022-0002=S,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=M,2020-24512=N,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=X,2020-0551_stale=X,2020-0549=M,2020-8696=MS,2020-0548=MS,2018-12207=S,2019-11135=MS,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x0005065B,2024-45332=M,2024-28956_IBPB=M,2024-28956_GH=S,2024-28956_cBPF=S,2024-31068=M,2024-36242=N,2024-23984=M,2024-25939=M,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=M,2022-26373=S,2022-21233=N,2022-29901=N,2022-28693=S,2022-21166=MS,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=S,2022-0002=S,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=M,2020-24512=N,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=X,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=S,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x00050663,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=N,2022-29901=N,2022-28693=N,2022-21166=MS,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=N,2022-0002=N,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=X,2020-0543=N,2022-21127=N,2020-0550=X,2020-0551_zero=X,2020-0551_stale=X,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=S,2019-11135=MS,2019-1125=S,2018-12127=MS,2018-12126=MS,2018-12130=MS,2018-3615=MS,2018-3620=MS,2018-3646=MS,2018-3639=MS,2018-3640=M,2017-5754=S,2017-5715=MS,2017-5753=S,
# 0x00050664,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=N,2022-29901=N,2022-28693=N,2022-21166=MS,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=N,2022-0002=N,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=X,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=X,2020-0551_zero=X,2020-0551_stale=X,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=S,2019-11135=MS,2019-1125=S,2018-12127=MS,2018-12126=MS,2018-12130=MS,2018-3615=MS,2018-3620=MS,2018-3646=MS,2018-3639=MS,2018-3640=M,2017-5754=S,2017-5715=MS,2017-5753=S,
# 0x00050665,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=N,2022-29901=N,2022-28693=N,2022-21166=MS,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=N,2022-0002=N,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=X,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=X,2020-0551_zero=X,2020-0551_stale=X,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=S,2019-11135=MS,2019-1125=S,2018-12127=MS,2018-12126=MS,2018-12130=MS,2018-3615=MS,2018-3620=MS,2018-3646=MS,2018-3639=MS,2018-3640=M,2017-5754=S,2017-5715=MS,2017-5753=S,
# 0x000506CA,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=MS,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=S,2022-29901=N,2022-28693=N,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=N,2022-0002=S,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=M,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=MS,2018-3640=N,2017-5754=N,2017-5715=MS,2017-5753=S,
# 0x000506E3,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=M,2022-26373=N,2022-21233=N,2022-29901=S,2022-28693=N,2022-21166=MS,2022-21125=MS,2022-21123=MS,2022-21180=MS,2022-0001=N,2022-0002=N,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=M,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=MS,2022-21127=MS,2020-0550=N,2020-0551_zero=S,2020-0551_stale=S,2020-0549=M,2020-8696=MS,2020-0548=MS,2018-12207=S,2019-11135=MS,2019-1125=S,2018-12127=MS,2018-12126=MS,2018-12130=MS,2018-3615=MS,2018-3620=MS,2018-3646=MS,2018-3639=MS,2018-3640=M,2017-5754=S,2017-5715=MS,2017-5753=S,
# 0x000506F1,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=MS,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=S,2022-29901=N,2022-28693=N,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=N,2022-0002=S,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=M,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=MS,2018-3640=N,2017-5754=N,2017-5715=MS,2017-5753=S,
# 0x000606A6,2024-45332=M,2024-28956_IBPB=M,2024-28956_GH=N,2024-28956_cBPF=S,2024-31068=N,2024-36242=S,2024-23984=M,2024-25939=N,2023-28746=N,2023-22655=MB,2023-38575=N,2023-39368=N,2023-23583=M,2022-40982=M,2022-26373=S,2022-21233=MS,2022-29901=N,2022-28693=N,2022-21166=MS,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=S,2022-0002=S,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000606C1,2024-45332=M,2024-28956_IBPB=M,2024-28956_GH=N,2024-28956_cBPF=S,2024-31068=N,2024-36242=S,2024-23984=M,2024-25939=N,2023-28746=N,2023-22655=MB,2023-38575=N,2023-39368=N,2023-23583=M,2022-40982=M,2022-26373=S,2022-21233=MS,2022-29901=N,2022-28693=N,2022-21166=MS,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=S,2022-0002=S,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000706A1,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=MBS,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=S,2022-38090=S,2022-29901=N,2022-28693=N,2022-21166=N,2022-21125=N,2022-21123=N,2022-2118=N,2022-0001=S,2022-0002=S,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=M,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=MS,2018-3640=N,2017-5754=S,2017-5715=MS,2017-5753=S,
# 0x000706A8,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=MBS,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=S,2022-29901=N,2022-28693=N,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=S,2022-0002=S,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=M,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=MS,2017-5753=S,
# 0x000706E5,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=S,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=M,2022-40982=M,2022-26373=S,2022-21233=S,2022-29901=N,2022-28693=S,2022-21166=MS,2022-21125=MS,2022-21123=MS,2022-21180=N,2022-0001=S,2022-0002=S,2021-0145=M,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=M,2020-24512=M,2020-24513=N,2020-8695=M,2020-8698=M,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=HM,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=S,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=HM,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x00080665,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=X,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=S,2022-29901=N,2022-28693=N,2022-21166=MS,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=S,2022-0002=S,2021-0145=N,2021-33120=M,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=M,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x00080667,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=MS,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=S,2022-29901=N,2022-28693=N,2022-21166=MS,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=S,2022-0002=S,2021-0145=N,2021-33120=M,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=MS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000806C1,2024-45332=M,2024-28956_IBPB=M,2024-28956_GH=N,2024-28956_cBPF=S,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=M,2022-40982=M,2022-26373=S,2022-21233=S,2022-29901=N,2022-28693=N,2022-21166=MB,2022-21125=MB,2022-21123=MB,2022-21180=N,2022-0001=S,2022-0002=S,2021-0145=M,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=M,2020-24513=N,2020-8695=M,2020-8698=M,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000806C2,2024-45332=M,2024-28956_IBPB=M,2024-28956_GH=N,2024-28956_cBPF=S,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=M,2022-40982=M,2022-26373=S,2022-21233=S,2022-29901=N,2022-28693=N,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=S,2022-0002=S,2021-0145=M,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=M,2020-24513=N,2020-8695=N,2020-8698=M,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000806D1,2024-45332=M,2024-28956_IBPB=M,2024-28956_GH=N,2024-28956_cBPF=S,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=M,2022-40982=M,2022-26373=S,2022-21233=S,2022-29901=N,2022-28693=N,2022-21166=MB,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=S,2022-0002=S,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000806E9,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=M,2022-26373=N,2022-21233=N,2022-29901=S,2022-28693=N,2022-21166=MS,2022-21125=MS,2022-21123=MS,2022-21180=S,2022-0001=N,2022-0002=N,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=M,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=M,2022-21127=M,2020-0550=N,2020-0551_zero=S,2020-0551_stale=S,2020-0549=M,2020-8696=MS,2020-0548=MS,2018-12207=S,2019-11135=MS,2019-1125=S,2018-12127=MS,2018-12126=MS,2018-12130=MS,2018-3615=MS,2018-3620=MS,2018-3646=MS,2018-3639=MS,2018-3640=M,2017-5754=S,2017-5715=MS,2017-5753=S,
# 0x000806EA,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=M,2022-26373=N,2022-21233=N,2022-29901=S,2022-28693=N,2022-21166=MS,2022-21125=MS,2022-21123=MS,2022-21180=S,2022-0001=N,2022-0002=N,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=M,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=MS,2022-21127=MS,2020-0550=N,2020-0551_zero=S,2020-0551_stale=S,2020-0549=M,2020-8696=MS,2020-0548=MS,2018-12207=S,2019-11135=MS,2019-1125=S,2018-12127=MS,2018-12126=MS,2018-12130=MS,2018-3615=MS,2018-3620=MS,2018-3646=MS,2018-3639=MS,2018-3640=M,2017-5754=S,2017-5715=MS,2017-5753=S,
# 0x000806EB,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=M,2022-26373=N,2022-21233=N,2022-29901=S,2022-28693=N,2022-21166=MS,2022-21125=MS,2022-21123=MS,2022-21180=S,2022-0001=N,2022-0002=N,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=M,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=MS,2022-21127=MS,2020-0550=N,2020-0551_zero=S,2020-0551_stale=S,2020-0549=M,2020-8696=MS,2020-0548=MS,2018-12207=S,2019-11135=MS,2019-1125=S,2018-12127=MS,2018-12126=MS,2018-12130=MS,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=MS,2018-3640=M,2017-5754=N,2017-5715=MS,2017-5753=S,
# 0x000806EC,2024-45332=M,2024-28956_IBPB=M,2024-28956_GH=S,2024-28956_cBPF=S,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=M,2022-26373=S,2022-21233=N,2022-29901=N,2022-28693=S,2022-21166=MS,2022-21125=MS,2022-21123=MS,2022-21180=S,2022-0001=S,2022-0002=S,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=M,2020-24512=M,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=MS,2022-21127=MS,2020-0550=N,2020-0551_zero=S,2020-0551_stale=S,2020-0549=M,2020-8696=MS,2020-0548=MS,2018-12207=S,2019-11135=MS,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000806F5,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=M,2024-36242=S,2024-23984=M,2024-25939=N,2023-28746=N,2023-22655=MB,2023-38575=M,2023-39368=M,2023-23583=M,2022-40982=N,2022-26373=S,2022-21233=HS,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000806F6,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=M,2024-36242=S,2024-23984=M,2024-25939=N,2023-28746=N,2023-22655=MB,2023-38575=M,2023-39368=M,2023-23583=M,2022-40982=N,2022-26373=S,2022-21233=HS,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000806F7,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=M,2024-36242=S,2024-23984=M,2024-25939=N,2023-28746=N,2023-22655=MB,2023-38575=M,2023-39368=M,2023-23583=M,2022-40982=N,2022-26373=S,2022-21233=HS,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000806F8,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=M,2024-36242=S,2024-23984=M,2024-25939=N,2023-28746=N,2023-22655=MB,2023-38575=M,2023-39368=M,2023-23583=M,2022-40982=N,2022-26373=S,2022-21233=HS,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x00090660,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=MS,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=S,2022-29901=N,2022-28693=N,2022-21166=MS,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=S,2022-0002=S,2021-0145=N,2021-33120=M,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=M,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x00090661,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=MS,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=S,2022-29901=N,2022-28693=N,2022-21166=MS,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=S,2022-0002=S,2021-0145=N,2021-33120=M,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=M,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x00090672,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=M,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=MS,2023-22655=N,2023-38575=M,2023-39368=M,2023-23583=M,2022-40982=N,2022-26373=S,2022-21233=S,2022-29901=N,2022-28693=MS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=MS,2022-0002=MS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x00090675,H=0,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=M,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=M,2023-39368=M,2023-23583=M,2022-40982=N,2022-26373=S,2022-21233=S,2022-29901=N,2022-28693=N,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=MS,2022-0002=MS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=MS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x00090675,H=1,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=M,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=MS,2023-22655=N,2023-38575=M,2023-39368=M,2023-23583=M,2022-40982=N,2022-26373=S,2022-21233=S,2022-29901=N,2022-28693=N,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=MS,2022-0002=MS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=MS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000906A3,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=M,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=MS,2023-22655=N,2023-38575=M,2023-39368=M,2023-23583=M,2022-40982=N,2022-26373=S,2022-21233=S,2022-29901=N,2022-28693=N,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=MS,2022-0002=MS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=MS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000906A4,H=0,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=MS,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=N,2022-29901=N,2022-28693=N,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000906A4,H=1,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=M,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=MS,2023-22655=N,2023-38575=M,2023-39368=M,2023-23583=M,2022-40982=N,2022-26373=S,2022-21233=S,2022-29901=N,2022-28693=N,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=MS,2022-0002=MS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=MS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000906C0,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=M,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000906E9,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=M,2022-26373=N,2022-21233=N,2022-29901=S,2022-28693=N,2022-21166=MS,2022-21125=MS,2022-21123=MS,2022-21180=S,2022-0001=N,2022-0002=N,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=M,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=MS,2022-21127=MS,2020-0550=N,2020-0551_zero=S,2020-0551_stale=S,2020-0549=M,2020-8696=MS,2020-0548=MS,2018-12207=S,2019-11135=MS,2019-1125=S,2018-12127=MS,2018-12126=MS,2018-12130=MS,2018-3615=MS,2018-3620=MS,2018-3646=MS,2018-3639=MS,2018-3640=M,2017-5754=S,2017-5715=MS,2017-5753=S,
# 0x000906EA,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=M,2022-26373=N,2022-21233=N,2022-29901=S,2022-28693=N,2022-21166=MS,2022-21125=MS,2022-21123=MS,2022-21180=S,2022-0001=N,2022-0002=N,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=M,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=MS,2022-21127=MS,2020-0550=N,2020-0551_zero=S,2020-0551_stale=S,2020-0549=M,2020-8696=MS,2020-0548=MS,2018-12207=S,2019-11135=MS,2019-1125=S,2018-12127=MS,2018-12126=MS,2018-12130=MS,2018-3615=MS,2018-3620=MS,2018-3646=MS,2018-3639=MS,2018-3640=M,2017-5754=S,2017-5715=MS,2017-5753=S,
# 0x000906EB,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=M,2022-26373=N,2022-21233=N,2022-38090=N,2022-29901=S,2022-28693=N,2022-21166=MS,2022-21125=MS,2022-21123=MS,2022-2118=S,2022-0001=N,2022-0002=N,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=M,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=MS,2022-21127=MS,2020-0550=N,2020-0551_zero=S,2020-0551_stale=S,2020-0549=M,2020-8696=MS,2020-0548=MS,2018-12207=S,2019-11135=MS,2019-1125=S,2018-12127=MS,2018-12126=MS,2018-12130=MS,2018-3615=MS,2018-3620=MS,2018-3646=MS,2018-3639=MS,2018-3640=M,2017-5754=S,2017-5715=MS,2017-5753=S,
# 0x000906EC,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=M,2022-26373=S,2022-21233=N,2022-29901=S,2022-28693=N,2022-21166=MS,2022-21125=MS,2022-21123=MS,2022-21180=S,2022-0001=N,2022-0002=N,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=M,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=MS,2022-21127=MS,2020-0550=N,2020-0551_zero=S,2020-0551_stale=S,2020-0549=M,2020-8696=MS,2020-0548=MS,2018-12207=S,2019-11135=MS,2019-1125=S,2018-12127=MS,2018-12126=MS,2018-12130=MS,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=M,2017-5754=N,2017-5715=MS,2017-5753=S,
# 0x000906ED,2024-45332=M,2024-28956_IBPB=M,2024-28956_GH=S,2024-28956_cBPF=S,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=M,2022-26373=S,2022-21233=N,2022-29901=N,2022-28693=S,2022-21166=MS,2022-21125=MS,2022-21123=MS,2022-21180=S,2022-0001=S,2022-0002=S,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=M,2020-24512=M,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=MS,2022-21127=MS,2020-0550=N,2020-0551_zero=S,2020-0551_stale=S,2020-0549=M,2020-8696=MS,2020-0548=MS,2018-12207=S,2019-11135=MS,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=M,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000A0652,2024-45332=M,2024-28956_IBPB=M,2024-28956_GH=S,2024-28956_cBPF=S,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=M,2022-26373=S,2022-21233=N,2022-29901=N,2022-28693=S,2022-21166=MS,2022-21125=MS,2022-21123=MS,2022-21180=S,2022-0001=S,2022-0002=S,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=M,2020-24512=M,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=S,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=S,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=M,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000A0653,2024-45332=M,2024-28956_IBPB=M,2024-28956_GH=S,2024-28956_cBPF=S,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=M,2022-26373=S,2022-21233=N,2022-29901=N,2022-28693=S,2022-21166=MS,2022-21125=MS,2022-21123=MS,2022-21180=S,2022-0001=S,2022-0002=S,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=M,2020-24512=M,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=S,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=S,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=M,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000A0655,2024-45332=M,2024-28956_IBPB=M,2024-28956_GH=S,2024-28956_cBPF=S,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=M,2022-26373=S,2022-21233=N,2022-29901=N,2022-28693=S,2022-21166=MS,2022-21125=MS,2022-21123=MS,2022-21180=S,2022-0001=S,2022-0002=S,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=M,2020-24512=M,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=S,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=S,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=M,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000A0660,2024-45332=M,2024-28956_IBPB=M,2024-28956_GH=S,2024-28956_cBPF=S,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=M,2022-26373=S,2022-21233=N,2022-29901=N,2022-28693=S,2022-21166=MS,2022-21125=MS,2022-21123=MS,2022-21180=S,2022-0001=S,2022-0002=S,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=M,2020-24512=M,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=S,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=S,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=M,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000A0661,2024-45332=M,2024-28956_IBPB=M,2024-28956_GH=S,2024-28956_cBPF=S,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=M,2022-26373=S,2022-21233=N,2022-29901=N,2022-28693=S,2022-21166=MS,2022-21125=MS,2022-21123=MS,2022-21180=S,2022-0001=S,2022-0002=S,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=M,2020-24512=M,2020-24513=N,2020-8695=M,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=S,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=S,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=M,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000A0671,2024-45332=M,2024-28956_IBPB=M,2024-28956_GH=N,2024-28956_cBPF=S,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=M,2022-40982=M,2022-26373=S,2022-21233=S,2022-29901=N,2022-28693=N,2022-21166=MS,2022-21125=N,2022-21123=N,2022-21180=S,2022-0001=S,2022-0002=S,2021-0145=M,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=S,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000A06A4,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=M,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=N,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000A06D0,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=N,2022-38090=N,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-2118=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000A06D1,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=N,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000A06E1,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=S,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=N,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000A06F2,2024-31068=N,2024-36242=S,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=N,2022-38090=N,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-2118=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000A06F3,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=S,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=N,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000B0650,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=N,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000B0664,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=S,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=N,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000B0671,H=0,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=M,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=M,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=S,2022-21233=S,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000B0671,H=1,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=M,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=MS,2023-22655=N,2023-38575=M,2023-39368=M,2023-23583=N,2022-40982=N,2022-26373=S,2022-21233=S,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000B06A2,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=M,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=MS,2023-22655=N,2023-38575=M,2023-39368=N,2023-23583=M,2022-40982=N,2022-26373=S,2022-21233=S,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000B06A3,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=M,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=MS,2023-22655=N,2023-38575=M,2023-39368=N,2023-23583=M,2022-40982=N,2022-26373=S,2022-21233=S,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000B06A8,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=M,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=MS,2023-22655=N,2023-38575=M,2023-39368=N,2023-23583=M,2022-40982=N,2022-26373=S,2022-21233=S,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000B06D1,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=M,2022-40982=N,2022-26373=S,2022-21233=S,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000B06E0,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=MS,2023-22655=N,2023-38575=N,2023-39368=M,2023-23583=N,2022-40982=N,2022-26373=N,2022-21233=N,2022-29901=N,2022-28693=N,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000B06F2,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=M,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=MS,2023-22655=N,2023-38575=M,2023-39368=M,2023-23583=M,2022-40982=N,2022-26373=S,2022-21233=S,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000B06F5,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=M,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=MS,2023-22655=N,2023-38575=M,2023-39368=M,2023-23583=M,2022-40982=N,2022-26373=S,2022-21233=S,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000C0652,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=S,2022-21233=S,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000C0662,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=S,2022-21233=S,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000C0664,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=N,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=S,2022-21233=S,2022-38090=S,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-2118=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000C06C2,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=S,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=S,2022-21233=N,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000C06C3,2024-45332=N,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=N,2024-36242=S,2024-23984=N,2024-25939=N,2023-28746=N,2023-22655=N,2023-38575=N,2023-39368=N,2023-23583=N,2022-40982=N,2022-26373=S,2022-21233=N,2022-29901=N,2022-28693=HS,2022-21166=N,2022-21125=N,2022-21123=N,2022-21180=N,2022-0001=HS,2022-0002=HS,2021-0145=N,2021-33120=N,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
# 0x000C06F2,2024-45332=M,2024-28956_IBPB=N,2024-28956_GH=N,2024-28956_cBPF=N,2024-31068=M,2021-0089=S,2021-0086=S,2020-24511=N,2020-24512=N,2020-24513=N,2020-8695=N,2020-8698=N,2020-0543=N,2022-21127=N,2020-0550=N,2020-0551_zero=N,2020-0551_stale=N,2020-0549=N,2020-8696=N,2020-0548=N,2018-12207=N,2019-11135=N,2019-1125=S,2018-12127=N,2018-12126=N,2018-12130=N,2018-3615=N,2018-3620=N,2018-3646=N,2018-3639=HS,2018-3640=N,2017-5754=N,2017-5715=HS,2017-5753=S,
#
# 0x000B0671,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000B06A2,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000B06A3,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000B06F2,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# 0x000B06F5,2017-5715=HS,2017-5753=S,2017-5754=N,2018-12126=N,2018-12127=N,2018-12130=N,2018-12207=N,2018-3615=N,2018-3620=N,2018-3639=HS,2018-3640=N,2018-3646=N,2019-11135=N,2020-0543=N,2022-40982=N,
# %%% ENDOFINTELDB

View File

@@ -17,8 +17,7 @@ VERSION='1.0.0'
# --- Common paths and basedirs ---
readonly VULN_SYSFS_BASE="/sys/devices/system/cpu/vulnerabilities"
readonly SYSKERNEL_BASE="/sys/kernel"
readonly DEBUGFS_BASE="$SYSKERNEL_BASE/debug"
readonly DEBUGFS_BASE="/sys/kernel/debug"
readonly SYS_MODULE_BASE="/sys/module"
readonly CPU_DEV_BASE="/dev/cpu"
readonly BSD_CPUCTL_DEV_BASE="/dev/cpuctl"
@@ -27,7 +26,8 @@ trap 'exit_cleanup' EXIT
trap 'pr_warn "interrupted, cleaning up..."; exit_cleanup; exit 1' INT
# Clean up temporary files and undo module/mount side effects on exit
exit_cleanup() {
local saved_ret=$?
local saved_ret
saved_ret=$?
# cleanup the temp decompressed config & kernel image
[ -n "${g_dumped_config:-}" ] && [ -f "$g_dumped_config" ] && rm -f "$g_dumped_config"
[ -n "${g_kerneltmp:-}" ] && [ -f "$g_kerneltmp" ] && rm -f "$g_kerneltmp"

View File

@@ -3,63 +3,64 @@
show_usage() {
# shellcheck disable=SC2086
cat <<EOF
Usage:
Live mode (auto): $(basename $0) [options]
Live mode (manual): $(basename $0) [options] <[--kernel <kimage>] [--config <kconfig>] [--map <mapfile>]> --live
Offline mode: $(basename $0) [options] <[--kernel <kimage>] [--config <kconfig>] [--map <mapfile>]>
Modes:
* Live mode: $(basename $0) [options] [--kernel <kimage>] [--config <kconfig>] [--map <mapfile>]
Inspect the currently running kernel within the context of the CPU it's running on.
You can optionally specify --kernel, --config, or --map to help the script locate files it couldn't auto-detect
Two modes are available.
* No-runtime mode: $(basename $0) [options] --no-runtime <--kernel <kimage>> [--config <kconfig>] [--map <mapfile>]
Inspect the CPU hardware, but skips all running-kernel artifacts (/sys, /proc, dmesg).
Use this when you have a kernel image different from the kernel you're running but want to check it against this CPU.
First mode is the "live" mode (default), it does its best to find information about the currently running kernel.
To run under this mode, just start the script without any option (you can also use --live explicitly)
* No-hardware mode: $(basename $0) [options] --no-hw <--kernel <kimage>> [--config <kconfig>] [--map <mapfile>]
Ignore both CPU hardware and running-kernel artifacts. Use this for pure static analysis of a kernel image,
for example when inspecting a kernel targeted for another system or CPU.
Second mode is the "offline" mode, where you can inspect a non-running kernel.
This mode is automatically enabled when you specify the location of the kernel file, config and System.map files:
* Hardware-only mode: $(basename $0) [options] --hw-only
Only inspect the CPU hardware, and report information and affectedness per vulnerability.
--kernel kernel_file specify a (possibly compressed) Linux or BSD kernel file
--config kernel_config specify a kernel config file (Linux only)
--map kernel_map_file specify a kernel System.map file (Linux only)
Vulnerability selection:
--variant VARIANT specify which variant you'd like to check, by default all variants are checked.
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
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).
If you want to use live mode while specifying the location of the kernel, config or map file yourself,
you can add --live to the above options, to tell the script to run in live mode instead of the offline mode,
which is enabled by default when at least one file is specified on the command line.
Check scope:
--no-sysfs don't use the /sys interface even if present [Linux]
--sysfs-only only use the /sys interface, don't run our own checks [Linux]
Strictness:
Options:
--no-color don't use color codes
--verbose, -v increase verbosity level, possibly several times
--explain produce an additional human-readable explanation of actions to take to mitigate a vulnerability
--paranoid require all mitigations to be enabled to the fullest extent, including those that
are not strictly necessary but provide defense in depth (e.g. SMT disabled, IBPB
always-on); without this flag, the script follows the security community consensus
--extra run additional checks for issues that don't have a CVE but are still security-relevant,
such as compile-time mitigations not enabled by default (e.g. Straight-Line Speculation)
Hardware and platform:
--cpu [#,all] interact with CPUID and MSR of CPU core number #, or all (default: CPU core 0)
--vmm [auto,yes,no] override the detection of the presence of a hypervisor, default: auto
--allow-msr-write allow probing for write-only MSRs, this might produce kernel logs or be blocked by your system
--arch-prefix PREFIX specify a prefix for cross-inspecting a kernel of a different arch, for example "aarch64-linux-gnu-",
so that invoked tools will be prefixed with this (i.e. aarch64-linux-gnu-objdump)
--no-sysfs don't use the /sys interface even if present [Linux]
--sysfs-only only use the /sys interface, don't run our own checks [Linux]
--coreos special mode for CoreOS (use an ephemeral toolbox to inspect kernel) [Linux]
Output:
--batch FORMAT produce machine readable output; FORMAT is one of:
text (default), short, json, json-terse, nrpe, prometheus
--no-color don't use color codes
--verbose, -v increase verbosity level, possibly several times
--explain produce an additional human-readable explanation of actions to take to mitigate a vulnerability
--arch-prefix PREFIX specify a prefix for cross-inspecting a kernel of a different arch, for example "aarch64-linux-gnu-",
so that invoked tools will be prefixed with this (i.e. aarch64-linux-gnu-objdump)
--batch text produce machine readable output, this is the default if --batch is specified alone
--batch short produce only one line with the vulnerabilities separated by spaces
--batch json produce JSON output formatted for Puppet, Ansible, Chef...
--batch nrpe produce machine readable output formatted for NRPE
--batch prometheus produce output for consumption by prometheus-node-exporter
Firmware database:
--variant VARIANT specify which variant you'd like to check, by default all variants are checked.
can be used multiple times (e.g. --variant 3a --variant l1tf)
for a list of supported VARIANT parameters, use --variant help
--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)
--hw-only only check for CPU information, don't check for any variant
--no-hw skip CPU information and checks, if you're inspecting a kernel not to be run on this host
--vmm [auto,yes,no] override the detection of the presence of a hypervisor, default: auto
--no-intel-db don't use the builtin Intel DB of affected processors
--allow-msr-write allow probing for write-only MSRs, this might produce kernel logs or be blocked by your system
--cpu [#,all] interact with CPUID and MSR of CPU core number #, or all (default: CPU core 0)
--update-fwdb update our local copy of the CPU microcodes versions database (using the awesome
MCExtractor project and the Intel firmwares GitHub repository)
--update-builtin-fwdb same as --update-fwdb but update builtin DB inside the script itself
Debug:
--dump-mock-data used to mimick a CPU on an other system, mainly used to help debugging this script
Return codes:
@@ -111,7 +112,7 @@ g_os=$(uname -s)
opt_kernel=''
opt_config=''
opt_map=''
opt_runtime=1
opt_live=-1
opt_no_color=0
opt_batch=0
opt_batch_format='text'
@@ -128,88 +129,47 @@ opt_vmm=-1
opt_allow_msr_write=0
opt_cpu=0
opt_explain=0
# Canonical run mode, set at the end of option parsing.
# Values: live, no-runtime, no-hw, hw-only
g_mode='live'
# Return 0 (true) if runtime state is accessible (procfs, sysfs, dmesg, debugfs).
# True in live and hw-only modes; false in no-runtime and no-hw modes.
has_runtime() { [ "$g_mode" = live ] || [ "$g_mode" = hw-only ]; }
opt_paranoid=0
opt_extra=0
opt_mock=0
opt_intel_db=1
g_critical=0
g_unknown=0
g_nrpe_total=0
g_nrpe_vuln_count=0
g_nrpe_unk_count=0
g_nrpe_vuln_ids=''
g_nrpe_vuln_details=''
g_nrpe_unk_details=''
g_smc_vuln_output=''
g_smc_ok_count=0
g_smc_vuln_count=0
g_smc_unk_count=0
g_smc_system_info_line=''
g_smc_cpu_info_line=''
g_nrpe_vuln=''
# CVE Registry: single source of truth for all CVE metadata.
# Fields: cve_id|json_key_name|affected_var_suffix|complete_name_and_aliases|arch
#
# The optional `arch` field gates whether the check is run at all, based on the
# 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)
# 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
# assignment. Rename across the codebase once the real CVE is issued.
# Fields: cve_id|json_key_name|affected_var_suffix|complete_name_and_aliases
readonly CVE_REGISTRY='
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-5754|MELTDOWN|variant3|Variant 3, Meltdown, rogue data cache load|
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-3615|L1TF SGX|variantl1tf_sgx|Foreshadow (SGX), L1 terminal fault|x86
CVE-2018-3620|L1TF OS|variantl1tf|Foreshadow-NG (OS), L1 terminal fault|x86
CVE-2018-3646|L1TF VMM|variantl1tf|Foreshadow-NG (VMM), L1 terminal fault|x86
CVE-2018-12126|MSBDS|msbds|Fallout, microarchitectural store buffer data sampling (MSBDS)|x86
CVE-2018-12130|MFBDS|mfbds|ZombieLoad, microarchitectural fill buffer data sampling (MFBDS)|x86
CVE-2018-12127|MLPDS|mlpds|RIDL, microarchitectural load port data sampling (MLPDS)|x86
CVE-2019-11091|MDSUM|mdsum|RIDL, microarchitectural data sampling uncacheable memory (MDSUM)|x86
CVE-2019-11135|TAA|taa|ZombieLoad V2, TSX Asynchronous Abort (TAA)|x86
CVE-2018-12207|ITLBMH|itlbmh|No eXcuses, iTLB Multihit, machine check exception on page size changes (MCEPSC)|x86
CVE-2020-0543|SRBDS|srbds|Special Register Buffer Data Sampling (SRBDS)|x86
CVE-2022-21123|SBDR|mmio|Shared Buffers Data Read (SBDR), MMIO Stale Data|x86
CVE-2022-21125|SBDS|mmio|Shared Buffers Data Sampling (SBDS), MMIO Stale Data|x86
CVE-2022-21166|DRPW|mmio|Device Register Partial Write (DRPW), MMIO Stale Data|x86
CVE-2023-20588|DIV0|div0|Division by Zero, AMD Zen1 speculative data leak|x86
CVE-2023-20593|ZENBLEED|zenbleed|Zenbleed, cross-process information leak|x86
CVE-2022-40982|DOWNFALL|downfall|Downfall, gather data sampling (GDS)|x86
CVE-2022-29900|RETBLEED AMD|retbleed|Retbleed, arbitrary speculative code execution with return instructions (AMD)|x86
CVE-2022-29901|RETBLEED INTEL|retbleed|Retbleed, arbitrary speculative code execution with return instructions (Intel)|x86
CVE-2023-20569|INCEPTION|inception|Inception, return address security (RAS)|x86
CVE-2023-23583|REPTAR|reptar|Reptar, redundant prefix issue|x86
CVE-2024-36350|TSA_SQ|tsa|Transient Scheduler Attack - Store Queue (TSA-SQ)|x86
CVE-2024-36357|TSA_L1|tsa|Transient Scheduler Attack - L1 (TSA-L1)|x86
CVE-2024-28956|ITS|its|Indirect Target Selection (ITS)|x86
CVE-2025-40300|VMSCAPE|vmscape|VMScape, VM-exit stale branch prediction|x86
CVE-2023-28746|RFDS|rfds|Register File Data Sampling (RFDS)|x86
CVE-2024-45332|BPI|bpi|Branch Privilege Injection (BPI)|x86
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-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
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-5754|MELTDOWN|variant3|Variant 3, Meltdown, rogue data cache load
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-3615|L1TF SGX|variantl1tf_sgx|Foreshadow (SGX), L1 terminal fault
CVE-2018-3620|L1TF OS|variantl1tf|Foreshadow-NG (OS), L1 terminal fault
CVE-2018-3646|L1TF VMM|variantl1tf|Foreshadow-NG (VMM), L1 terminal fault
CVE-2018-12126|MSBDS|msbds|Fallout, microarchitectural store buffer data sampling (MSBDS)
CVE-2018-12130|MFBDS|mfbds|ZombieLoad, microarchitectural fill buffer data sampling (MFBDS)
CVE-2018-12127|MLPDS|mlpds|RIDL, microarchitectural load port data sampling (MLPDS)
CVE-2019-11091|MDSUM|mdsum|RIDL, microarchitectural data sampling uncacheable memory (MDSUM)
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)
CVE-2020-0543|SRBDS|srbds|Special Register Buffer Data Sampling (SRBDS)
CVE-2023-20588|DIV0|div0|Division by Zero, AMD Zen1 speculative data leak
CVE-2023-20593|ZENBLEED|zenbleed|Zenbleed, cross-process information leak
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)
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)
CVE-2023-23583|REPTAR|reptar|Reptar, redundant prefix issue
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)
CVE-2024-28956|ITS|its|Indirect Target Selection (ITS)
CVE-2025-40300|VMSCAPE|vmscape|VMScape, VM-exit stale branch prediction
CVE-2023-28746|RFDS|rfds|Register File Data Sampling (RFDS)
CVE-2024-45332|BPI|bpi|Branch Privilege Injection (BPI)
CVE-0000-0001|SLS|sls|Straight-Line Speculation (SLS)
'
# Derive the supported CVE list from the registry

View File

@@ -1,127 +0,0 @@
# vim: set ts=4 sw=4 sts=4 et:
# Human-friendly codename lookup for Intel CPUs.
# Depends on constants from 003_intel_models.sh being set.
# Print the human-friendly codename for the current Intel CPU, or nothing if unknown.
# Reads: cpu_family, cpu_model (set by parse_cpu_details)
get_intel_codename() {
case "$cpu_family" in
5)
case "$cpu_model" in
"$INTEL_FAM5_PENTIUM_75") echo "Pentium 75 (P54C)" ;;
"$INTEL_FAM5_PENTIUM_MMX") echo "Pentium MMX (P55C)" ;;
"$INTEL_FAM5_QUARK_X1000") echo "Quark X1000" ;;
esac
;;
6)
case "$cpu_model" in
"$INTEL_FAM6_PENTIUM_PRO") echo "Pentium Pro" ;;
"$INTEL_FAM6_PENTIUM_II_KLAMATH") echo "Pentium II (Klamath)" ;;
"$INTEL_FAM6_PENTIUM_III_DESCHUTES") echo "Pentium III (Deschutes)" ;;
"$INTEL_FAM6_PENTIUM_III_TUALATIN") echo "Pentium III (Tualatin)" ;;
"$INTEL_FAM6_PENTIUM_M_DOTHAN") echo "Pentium M (Dothan)" ;;
"$INTEL_FAM6_CORE_YONAH") echo "Core (Yonah)" ;;
"$INTEL_FAM6_CORE2_MEROM") echo "Core 2 (Merom)" ;;
"$INTEL_FAM6_CORE2_MEROM_L") echo "Core 2 (Merom-L)" ;;
"$INTEL_FAM6_CORE2_PENRYN") echo "Core 2 (Penryn)" ;;
"$INTEL_FAM6_CORE2_DUNNINGTON") echo "Core 2 (Dunnington)" ;;
"$INTEL_FAM6_NEHALEM") echo "Nehalem" ;;
"$INTEL_FAM6_NEHALEM_G") echo "Nehalem (Auburndale / Havendale)" ;;
"$INTEL_FAM6_NEHALEM_EP") echo "Nehalem EP" ;;
"$INTEL_FAM6_NEHALEM_EX") echo "Nehalem EX" ;;
"$INTEL_FAM6_WESTMERE") echo "Westmere" ;;
"$INTEL_FAM6_WESTMERE_EP") echo "Westmere EP" ;;
"$INTEL_FAM6_WESTMERE_EX") echo "Westmere EX" ;;
"$INTEL_FAM6_SANDYBRIDGE") echo "Sandy Bridge" ;;
"$INTEL_FAM6_SANDYBRIDGE_X") echo "Sandy Bridge-E" ;;
"$INTEL_FAM6_IVYBRIDGE") echo "Ivy Bridge" ;;
"$INTEL_FAM6_IVYBRIDGE_X") echo "Ivy Bridge-E" ;;
"$INTEL_FAM6_HASWELL") echo "Haswell" ;;
"$INTEL_FAM6_HASWELL_X") echo "Haswell-E" ;;
"$INTEL_FAM6_HASWELL_L") echo "Haswell (low power)" ;;
"$INTEL_FAM6_HASWELL_G") echo "Haswell (GT3e)" ;;
"$INTEL_FAM6_BROADWELL") echo "Broadwell" ;;
"$INTEL_FAM6_BROADWELL_G") echo "Broadwell (GT3e)" ;;
"$INTEL_FAM6_BROADWELL_X") echo "Broadwell-E" ;;
"$INTEL_FAM6_BROADWELL_D") echo "Broadwell-DE" ;;
"$INTEL_FAM6_SKYLAKE_L") echo "Skylake (mobile)" ;;
"$INTEL_FAM6_SKYLAKE") echo "Skylake (desktop)" ;;
"$INTEL_FAM6_SKYLAKE_X") echo "Skylake-X / Cascade Lake / Cooper Lake" ;;
"$INTEL_FAM6_KABYLAKE_L") echo "Kaby Lake (mobile) / Sky Lake" ;;
"$INTEL_FAM6_KABYLAKE") echo "Kaby Lake / Coffee Lake / Sky Lake" ;;
"$INTEL_FAM6_COMETLAKE") echo "Comet Lake / Sky Lake" ;;
"$INTEL_FAM6_COMETLAKE_L") echo "Comet Lake (mobile) / Sky Lake" ;;
"$INTEL_FAM6_CANNONLAKE_L") echo "Cannon Lake (Palm Cove)" ;;
"$INTEL_FAM6_ICELAKE_X") echo "Ice Lake-X (Sunny Cove)" ;;
"$INTEL_FAM6_ICELAKE_D") echo "Ice Lake-D (Sunny Cove)" ;;
"$INTEL_FAM6_ICELAKE") echo "Ice Lake (Sunny Cove)" ;;
"$INTEL_FAM6_ICELAKE_L") echo "Ice Lake-L (Sunny Cove)" ;;
"$INTEL_FAM6_ICELAKE_NNPI") echo "Ice Lake NNPI (Sunny Cove)" ;;
"$INTEL_FAM6_ROCKETLAKE") echo "Rocket Lake (Cypress Cove)" ;;
"$INTEL_FAM6_TIGERLAKE_L") echo "Tiger Lake-L (Willow Cove)" ;;
"$INTEL_FAM6_TIGERLAKE") echo "Tiger Lake (Willow Cove)" ;;
"$INTEL_FAM6_SAPPHIRERAPIDS_X") echo "Sapphire Rapids-X (Golden Cove)" ;;
"$INTEL_FAM6_EMERALDRAPIDS_X") echo "Emerald Rapids-X (Raptor Cove)" ;;
"$INTEL_FAM6_GRANITERAPIDS_X") echo "Granite Rapids-X (Redwood Cove)" ;;
"$INTEL_FAM6_GRANITERAPIDS_D") echo "Granite Rapids-D (Redwood Cove)" ;;
"$INTEL_FAM6_BARTLETTLAKE") echo "Bartlett Lake (Raptor Cove)" ;;
"$INTEL_FAM6_LAKEFIELD") echo "Lakefield (Sunny Cove + Tremont)" ;;
"$INTEL_FAM6_ALDERLAKE") echo "Alder Lake (Golden Cove + Gracemont)" ;;
"$INTEL_FAM6_ALDERLAKE_L") echo "Alder Lake-L (Golden Cove + Gracemont)" ;;
"$INTEL_FAM6_RAPTORLAKE") echo "Raptor Lake (Raptor Cove + Enhanced Gracemont)" ;;
"$INTEL_FAM6_RAPTORLAKE_P") echo "Raptor Lake-P (Raptor Cove + Enhanced Gracemont)" ;;
"$INTEL_FAM6_RAPTORLAKE_S") echo "Raptor Lake-S (Raptor Cove + Enhanced Gracemont)" ;;
"$INTEL_FAM6_METEORLAKE") echo "Meteor Lake (Redwood Cove + Crestmont)" ;;
"$INTEL_FAM6_METEORLAKE_L") echo "Meteor Lake-L (Redwood Cove + Crestmont)" ;;
"$INTEL_FAM6_ARROWLAKE_H") echo "Arrow Lake-H (Lion Cove + Skymont)" ;;
"$INTEL_FAM6_ARROWLAKE") echo "Arrow Lake (Lion Cove + Skymont)" ;;
"$INTEL_FAM6_ARROWLAKE_U") echo "Arrow Lake-U (Lion Cove + Skymont)" ;;
"$INTEL_FAM6_LUNARLAKE_M") echo "Lunar Lake-M (Lion Cove + Skymont)" ;;
"$INTEL_FAM6_PANTHERLAKE_L") echo "Panther Lake-L (Cougar Cove + Darkmont)" ;;
"$INTEL_FAM6_WILDCATLAKE_L") echo "Wildcat Lake-L" ;;
"$INTEL_FAM6_ATOM_BONNELL") echo "Atom Bonnell (Diamondville / Pineview)" ;;
"$INTEL_FAM6_ATOM_BONNELL_MID") echo "Atom Bonnell (Silverthorne / Lincroft)" ;;
"$INTEL_FAM6_ATOM_SALTWELL") echo "Atom Saltwell (Cedarview)" ;;
"$INTEL_FAM6_ATOM_SALTWELL_MID") echo "Atom Saltwell (Penwell)" ;;
"$INTEL_FAM6_ATOM_SALTWELL_TABLET") echo "Atom Saltwell (Cloverview)" ;;
"$INTEL_FAM6_ATOM_SILVERMONT") echo "Atom Silvermont (Bay Trail)" ;;
"$INTEL_FAM6_ATOM_SILVERMONT_D") echo "Atom Silvermont-D (Avaton / Rangely)" ;;
"$INTEL_FAM6_ATOM_SILVERMONT_MID") echo "Atom Silvermont (Merriefield)" ;;
"$INTEL_FAM6_ATOM_SILVERMONT_MID2") echo "Atom Silvermont (Anniedale)" ;;
"$INTEL_FAM6_ATOM_AIRMONT") echo "Atom Airmont (Cherry Trail / Braswell)" ;;
"$INTEL_FAM6_ATOM_AIRMONT_NP") echo "Atom Airmont (Lightning Mountain)" ;;
"$INTEL_FAM6_ATOM_GOLDMONT") echo "Atom Goldmont (Apollo Lake)" ;;
"$INTEL_FAM6_ATOM_GOLDMONT_D") echo "Atom Goldmont-D (Denverton)" ;;
"$INTEL_FAM6_ATOM_GOLDMONT_PLUS") echo "Atom Goldmont Plus (Gemini Lake)" ;;
"$INTEL_FAM6_ATOM_TREMONT_D") echo "Atom Tremont-D (Jacobsville)" ;;
"$INTEL_FAM6_ATOM_TREMONT") echo "Atom Tremont (Elkhart Lake)" ;;
"$INTEL_FAM6_ATOM_TREMONT_L") echo "Atom Tremont-L (Jasper Lake)" ;;
"$INTEL_FAM6_ATOM_GRACEMONT") echo "Atom Gracemont (Alder Lake-N)" ;;
"$INTEL_FAM6_ATOM_CRESTMONT_X") echo "Atom Crestmont-X (Sierra Forest)" ;;
"$INTEL_FAM6_ATOM_CRESTMONT") echo "Atom Crestmont (Grand Ridge)" ;;
"$INTEL_FAM6_ATOM_DARKMONT_X") echo "Atom Darkmont-X (Clearwater Forest)" ;;
"$INTEL_FAM6_XEON_PHI_KNL") echo "Xeon Phi (Knights Landing)" ;;
"$INTEL_FAM6_XEON_PHI_KNM") echo "Xeon Phi (Knights Mill)" ;;
esac
;;
15)
case "$cpu_model" in
"$INTEL_FAM15_P4_WILLAMETTE") echo "Pentium 4 (Willamette)" ;;
"$INTEL_FAM15_P4_PRESCOTT") echo "Pentium 4 (Prescott)" ;;
"$INTEL_FAM15_P4_PRESCOTT_2M") echo "Pentium 4 (Prescott 2M)" ;;
"$INTEL_FAM15_P4_CEDARMILL") echo "Pentium 4 (Cedarmill)" ;;
esac
;;
18)
case "$cpu_model" in
"$INTEL_FAM18_NOVALAKE") echo "Nova Lake (Coyote Cove)" ;;
"$INTEL_FAM18_NOVALAKE_L") echo "Nova Lake-L (Coyote Cove)" ;;
esac
;;
19)
case "$cpu_model" in
"$INTEL_FAM19_DIAMONDRAPIDS_X") echo "Diamond Rapids-X (Panther Cove)" ;;
esac
;;
esac
}

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).
_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
# Args: $1=cve_id
# Returns: 0 if affected, 1 if not affected
@@ -80,12 +50,7 @@ is_cpu_affected() {
if [ "${g_intel_line:-}" = "no" ]; then
pr_debug "is_cpu_affected: $cpuid_hex not in Intel database (cached)"
elif [ -z "$g_intel_line" ]; then
# Try hybrid-specific entry first (H=0 or H=1), fall back to unqualified entry
g_intel_line=$(read_inteldb | grep -F "$cpuid_hex,H=$cpu_hybrid," | head -n1)
if [ -z "$g_intel_line" ]; then
# No hybrid-specific entry, try unqualified (no H= field)
g_intel_line=$(read_inteldb | grep -F "$cpuid_hex," | grep -v ',H=' | head -n1)
fi
g_intel_line=$(read_inteldb | grep -F "$cpuid_hex," | head -n1)
if [ -z "$g_intel_line" ]; then
g_intel_line=no
pr_debug "is_cpu_affected: $cpuid_hex not in Intel database"
@@ -134,15 +99,9 @@ is_cpu_affected() {
affected_taa=''
affected_itlbmh=''
affected_srbds=''
affected_mmio=''
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, Zenbleed and Inception are all AMD specific, look for "is_amd" below:
_set_immune div0
_set_immune fpdss
_set_immune zenbleed
_set_immune inception
# TSA is AMD specific (Zen 3/4), look for "is_amd" below:
@@ -164,11 +123,6 @@ is_cpu_affected() {
_infer_immune mlpds
_infer_immune mdsum
pr_debug "is_cpu_affected: cpu not affected by Microarchitectural Data Sampling"
elif is_cpu_msbds_only; then
_infer_immune mfbds
_infer_immune mlpds
_infer_immune mdsum
pr_debug "is_cpu_affected: cpu only affected by MSBDS, not MFBDS/MLPDS/MDSUM"
fi
if is_cpu_taa_free; then
@@ -181,11 +135,6 @@ is_cpu_affected() {
pr_debug "is_cpu_affected: cpu not affected by Special Register Buffer Data Sampling"
fi
if is_cpu_mmio_free; then
_infer_immune mmio
pr_debug "is_cpu_affected: cpu not affected by MMIO Stale Data"
fi
# NO_SPECTRE_V2: Centaur family 7 and Zhaoxin family 7 are immune to Spectre V2
# kernel commit 1e41a766c98b (v5.6-rc1): added NO_SPECTRE_V2 exemption
# Zhaoxin vendor_id is " Shanghai " in cpuinfo (parsed as "Shanghai" by awk)
@@ -207,7 +156,6 @@ is_cpu_affected() {
_set_immune mdsum
_set_immune taa
_set_immune srbds
_set_immune mmio
elif is_intel; then
# Intel
# https://github.com/crozone/SpectrePoC/issues/1 ^F E5200 => spectre 2 not affected
@@ -640,23 +588,13 @@ is_cpu_affected() {
fi
_set_immune variantl1tf
# DIV0 (Zen1/Zen+)
# DIV0 (Zen1 only)
# 77245f1c3c64 (v6.5, initial model list): family 0x17 models 0x00-0x2f, 0x50-0x5f
# bfff3c6692ce (v6.8): moved to init_amd_zen1(), unconditional for all ZEN1-flagged CPUs
# The kernel's X86_FEATURE_ZEN1 covers family 0x17 models 0x00-0x2f and 0x50-0x5f,
# which spans both Zen1 (Summit Ridge, Naples, Raven Ridge, Snowy Owl) and Zen+
# (Pinnacle Ridge, Picasso, Dali, Colfax) products -- all using the same divider silicon.
# bfff3c6692ce (v6.8): moved to init_amd_zen1(), unconditional for all Zen1
# All Zen1 CPUs are family 0x17, models 0x00-0x2f and 0x50-0x5f
amd_legacy_erratum "$(amd_model_range 0x17 0x00 0x0 0x2f 0xf)" && _set_vuln div0
amd_legacy_erratum "$(amd_model_range 0x17 0x50 0x0 0x5f 0xf)" && _set_vuln div0
# FPDSS: same Zen1/Zen+ cohort as DIV0 (both applied unconditionally in init_amd_zen1()).
# e55d98e77561 (v7.1): unconditional in init_amd_zen1(); CVE-2025-54505 / AMD-SB-7053.
# AMD-SB-7053 only enumerates a subset (EPYC 7001, EPYC Embedded 3000, Athlon/Ryzen 3000
# with Radeon, Ryzen PRO 3000 with Radeon Vega), but the kernel mitigates the full
# ZEN1 cohort, so we flag all of it to match the kernel's behavior.
# shellcheck disable=SC2154
[ "$affected_div0" = 0 ] && _set_vuln fpdss
# Zenbleed
amd_legacy_erratum "$(amd_model_range 0x17 0x30 0x0 0x4f 0xf)" && _set_vuln zenbleed
amd_legacy_erratum "$(amd_model_range 0x17 0x60 0x0 0x7f 0xf)" && _set_vuln zenbleed
@@ -861,85 +799,13 @@ is_cpu_affected() {
_infer_immune sls
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
{
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: variant4=$affected_variant4 variantl1tf=$affected_variantl1tf msbds=$affected_msbds mfbds=$affected_mfbds"
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: 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"
pr_debug "is_cpu_affected: final results: div0=$affected_div0 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"
}
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

View File

@@ -85,37 +85,6 @@ is_cpu_mds_free() {
return 1
}
# Check whether the CPU is known to be affected by MSBDS only (not MFBDS/MLPDS/MDSUM)
# These CPUs have a different microarchitecture that is only susceptible to
# Microarchitectural Store Buffer Data Sampling, not the other MDS variants.
# Returns: 0 if MSBDS-only, 1 otherwise
is_cpu_msbds_only() {
# source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c
#VULNWL_INTEL(ATOM_SILVERMONT, MSBDS_ONLY),
#VULNWL_INTEL(ATOM_SILVERMONT_D, MSBDS_ONLY),
#VULNWL_INTEL(ATOM_SILVERMONT_MID, MSBDS_ONLY),
#VULNWL_INTEL(ATOM_SILVERMONT_MID2, MSBDS_ONLY),
#VULNWL_INTEL(ATOM_AIRMONT, MSBDS_ONLY),
#VULNWL_INTEL(XEON_PHI_KNL, MSBDS_ONLY),
#VULNWL_INTEL(XEON_PHI_KNM, MSBDS_ONLY),
parse_cpu_details
if is_intel; then
if [ "$cpu_family" = 6 ]; then
if [ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_MID" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_MID2" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNL" ] ||
[ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNM" ]; then
return 0
fi
fi
fi
return 1
}
# Check whether the CPU is known to be unaffected by TSX Asynchronous Abort (TAA)
# Returns: 0 if TAA-free, 1 if affected or unknown
is_cpu_taa_free() {
@@ -187,79 +156,6 @@ 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 ]
}
# 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
is_cpu_mmio_free() {
parse_cpu_details
is_arch_cap_mmio_immune && return 0
# Non-Intel x86 vendors the kernel unconditionally whitelists (AMD/Hygon all
# families; Centaur/Zhaoxin fam 7 only).
if is_amd || is_hygon; then
return 0
fi
if { [ "$cpu_vendor" = "CentaurHauls" ] || [ "$cpu_vendor" = "Shanghai" ]; } && [ "$cpu_family" = 7 ]; then
return 0
fi
# Intel NO_MMIO whitelist
if is_intel && [ "$cpu_family" = 6 ]; then
if [ "$cpu_model" = "$INTEL_FAM6_TIGERLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_TIGERLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ALDERLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ALDERLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_PLUS" ]; then
return 0
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
}
# Check whether the CPU is known to be unaffected by Speculative Store Bypass (SSB)
# Returns: 0 if SSB-free, 1 if affected or unknown
is_cpu_ssb_free() {

View File

@@ -47,7 +47,7 @@ while [ -n "${1:-}" ]; do
opt_arch_prefix="$2"
shift 2
elif [ "$1" = "--live" ]; then
# deprecated, kept for backward compatibility (live is now the default)
opt_live=1
shift
elif [ "$1" = "--no-color" ]; then
opt_no_color=1
@@ -74,16 +74,15 @@ while [ -n "${1:-}" ]; do
elif [ "$1" = "--hw-only" ]; then
opt_hw_only=1
shift
elif [ "$1" = "--no-runtime" ]; then
opt_runtime=0
shift
elif [ "$1" = "--no-hw" ]; then
opt_no_hw=1
opt_runtime=0
shift
elif [ "$1" = "--allow-msr-write" ]; then
opt_allow_msr_write=1
shift
elif [ "$1" = "--no-intel-db" ]; then
opt_intel_db=0
shift
elif [ "$1" = "--cpu" ]; then
opt_cpu=$2
if [ "$opt_cpu" != all ]; then
@@ -117,7 +116,7 @@ while [ -n "${1:-}" ]; do
opt_no_color=1
shift
case "$1" in
text | short | nrpe | json | json-terse | prometheus)
text | short | nrpe | json | prometheus)
opt_batch_format="$1"
shift
;;
@@ -125,7 +124,7 @@ while [ -n "${1:-}" ]; do
'') ;; # allow nothing at all
*)
echo "$0: error: unknown batch format '$1'" >&2
echo "$0: error: --batch expects a format from: text, short, nrpe, json, json-terse, prometheus" >&2
echo "$0: error: --batch expects a format from: text, nrpe, json" >&2
exit 255
;;
esac
@@ -170,7 +169,7 @@ while [ -n "${1:-}" ]; do
case "$2" in
help)
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, div0, zenbleed, downfall, retbleed, inception, reptar, rfds, tsa, tsa-sq, tsa-l1, its, vmscape, bpi, sls"
exit 0
;;
1)
@@ -225,30 +224,10 @@ while [ -n "${1:-}" ]; do
opt_cve_list="$opt_cve_list CVE-2020-0543"
opt_cve_all=0
;;
mmio)
opt_cve_list="$opt_cve_list CVE-2022-21123 CVE-2022-21125 CVE-2022-21166"
opt_cve_all=0
;;
sbdr)
opt_cve_list="$opt_cve_list CVE-2022-21123"
opt_cve_all=0
;;
sbds)
opt_cve_list="$opt_cve_list CVE-2022-21125"
opt_cve_all=0
;;
drpw)
opt_cve_list="$opt_cve_list CVE-2022-21166"
opt_cve_all=0
;;
div0)
opt_cve_list="$opt_cve_list CVE-2023-20588"
opt_cve_all=0
;;
fpdss)
opt_cve_list="$opt_cve_list CVE-2025-54505"
opt_cve_all=0
;;
zenbleed)
opt_cve_list="$opt_cve_list CVE-2023-20593"
opt_cve_all=0
@@ -301,60 +280,12 @@ while [ -n "${1:-}" ]; do
opt_cve_list="$opt_cve_list CVE-0000-0001"
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
exit 255
;;
esac
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
show_header
show_usage
@@ -387,25 +318,11 @@ if [ "$opt_no_hw" = 1 ] && [ "$opt_hw_only" = 1 ]; then
exit 255
fi
if [ "$opt_runtime" = 0 ] && [ "$opt_sysfs_only" = 1 ]; then
pr_warn "Incompatible options specified (--no-runtime and --sysfs-only), aborting"
exit 255
fi
if [ "$opt_runtime" = 0 ] && [ -z "$opt_kernel" ] && [ -z "$opt_config" ] && [ -z "$opt_map" ]; then
pr_warn "Option --no-runtime requires at least one of --kernel, --config, or --map"
exit 255
fi
# Derive the canonical run mode from the option flags.
# Modes: live (default), no-runtime (--no-runtime), no-hw (--no-hw), hw-only (--hw-only)
# shellcheck disable=SC2034
if [ "$opt_hw_only" = 1 ]; then
g_mode='hw-only'
elif [ "$opt_no_hw" = 1 ]; then
g_mode='no-hw'
elif [ "$opt_runtime" = 0 ]; then
g_mode='no-runtime'
else
g_mode='live'
if [ "$opt_live" = -1 ]; then
if [ -n "$opt_kernel" ] || [ -n "$opt_config" ] || [ -n "$opt_map" ]; then
# no --live specified and we have a least one of the kernel/config/map files on the cmdline: offline mode
opt_live=0
else
opt_live=1
fi
fi

View File

@@ -1,277 +1,4 @@
# vim: set ts=4 sw=4 sts=4 et:
# --- JSON helper functions ---
# Escape a string for use in a JSON value (handles backslashes, double quotes, newlines, tabs)
# Args: $1=string
# Prints: escaped string (without surrounding quotes)
_json_escape() {
printf '%s' "$1" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/ /\\t/g' | tr '\n' ' '
}
# Escape a string for use as a Prometheus label value (handles backslashes, double quotes, newlines)
# Args: $1=string
# Prints: escaped string (without surrounding quotes)
_prom_escape() {
printf '%s' "$1" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' | tr '\n' ' '
}
# Convert a shell capability value to a JSON boolean token
# Args: $1=value (1=true, 0=false, -1/empty=null, any other non-empty string=true)
# Prints: JSON token (true/false/null)
# Note: capability variables can be set to arbitrary strings internally to carry
# detection-path context (e.g. cap_ssbd='Intel SSBD'); for the JSON output those
# are normalized to true so consumers see a clean boolean | null type.
_json_cap() {
case "${1:-}" in
0) printf 'false' ;;
-1 | '') printf 'null' ;;
*) printf 'true' ;;
esac
}
# Emit a JSON string value or null
# Args: $1=string (empty=null)
# Prints: JSON token ("escaped string" or null)
_json_str() {
if [ -n "${1:-}" ]; then
printf '"%s"' "$(_json_escape "$1")"
else
printf 'null'
fi
}
# Emit a JSON number value or null
# Args: $1=number (empty=null)
# Prints: JSON token
_json_num() {
if [ -n "${1:-}" ]; then
printf '%s' "$1"
else
printf 'null'
fi
}
# Emit a JSON boolean value or null
# Args: $1=value (1/0/empty)
# Prints: JSON token
_json_bool() {
case "${1:-}" in
1) printf 'true' ;;
0) printf 'false' ;;
*) printf 'null' ;;
esac
}
# --- JSON section builders (comprehensive format) ---
# Build the "meta" section of the comprehensive JSON output
# Sets: g_json_meta
# shellcheck disable=SC2034
_build_json_meta() {
local timestamp
timestamp=$(date -u '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || echo "unknown")
local run_as_root
if [ "$(id -u)" -eq 0 ]; then
run_as_root='true'
else
run_as_root='false'
fi
g_json_meta=$(printf '{"script_version":%s,"format_version":1,"timestamp":%s,"os":%s,"mode":"%s","run_as_root":%s,"reduced_accuracy":%s,"paranoid":%s,"sysfs_only":%s,"extra":%s}' \
"$(_json_str "$VERSION")" \
"$(_json_str "$timestamp")" \
"$(_json_str "$g_os")" \
"$g_mode" \
"$run_as_root" \
"$(_json_bool "${g_bad_accuracy:-0}")" \
"$(_json_bool "$opt_paranoid")" \
"$(_json_bool "$opt_sysfs_only")" \
"$(_json_bool "$opt_extra")")
}
# Build the "system" section of the comprehensive JSON output
# Sets: g_json_system
# shellcheck disable=SC2034
_build_json_system() {
local kernel_release kernel_version kernel_arch smt_val
if [ "$g_mode" = live ]; then
kernel_release=$(uname -r)
kernel_version=$(uname -v)
kernel_arch=$(uname -m)
else
kernel_release=''
kernel_version=''
kernel_arch=''
fi
# SMT detection
is_cpu_smt_enabled
smt_val=$?
case $smt_val in
0) smt_val='true' ;;
1) smt_val='false' ;;
*) smt_val='null' ;;
esac
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}' \
"$(_json_str "$kernel_release")" \
"$(_json_str "$kernel_version")" \
"$(_json_str "$kernel_arch")" \
"$(_json_str "${opt_kernel:-}")" \
"$(_json_str "${opt_config:-}")" \
"$(_json_str "${g_kernel_version:-}")" \
"$(_json_str "${g_kernel_cmdline:-}")" \
"$(_json_num "${g_max_core_id:+$((g_max_core_id + 1))}")" \
"$smt_val" \
"$(_json_bool "${g_has_vmm:-}")" \
"$(_json_str "${g_has_vmm_reason:-}")")
}
# Build the "cpu" section of the comprehensive JSON output
# Sets: g_json_cpu
# shellcheck disable=SC2034
_build_json_cpu() {
local cpuid_hex codename caps arch_sub arch_type sbpb_norm
if [ -n "${cpu_cpuid:-}" ]; then
cpuid_hex=$(printf '0x%08x' "$cpu_cpuid")
else
cpuid_hex=''
fi
codename=''
if is_intel; then
codename=$(get_intel_codename 2>/dev/null || true)
fi
# cap_sbpb uses non-standard encoding (1=YES, 2=NO, 3=UNKNOWN) because the
# CVE-2023-20569 check distinguishes the unknown case. Normalize for JSON.
case "${cap_sbpb:-}" in
1) sbpb_norm=1 ;;
2) sbpb_norm=0 ;;
3) sbpb_norm=-1 ;;
*) sbpb_norm='' ;;
esac
# Determine architecture type and build the arch-specific sub-object
case "${cpu_vendor:-}" in
GenuineIntel | AuthenticAMD | HygonGenuine)
arch_type='x86'
# Build x86 capabilities sub-object
caps=$(printf '{"spec_ctrl":%s,"ibrs":%s,"ibpb":%s,"ibpb_ret":%s,"stibp":%s,"ssbd":%s,"l1d_flush":%s,"md_clear":%s,"arch_capabilities":%s,"rdcl_no":%s,"ibrs_all":%s,"rsba":%s,"l1dflush_no":%s,"ssb_no":%s,"mds_no":%s,"taa_no":%s,"pschange_msc_no":%s,"tsx_ctrl_msr":%s,"tsx_ctrl_rtm_disable":%s,"tsx_ctrl_cpuid_clear":%s,"gds_ctrl":%s,"gds_no":%s,"gds_mitg_dis":%s,"gds_mitg_lock":%s,"rfds_no":%s,"rfds_clear":%s,"its_no":%s,"sbdr_ssdp_no":%s,"fbsdp_no":%s,"psdp_no":%s,"fb_clear":%s,"rtm":%s,"tsx_force_abort":%s,"tsx_force_abort_rtm_disable":%s,"tsx_force_abort_cpuid_clear":%s,"sgx":%s,"srbds":%s,"srbds_on":%s,"amd_ssb_no":%s,"hygon_ssb_no":%s,"ipred":%s,"rrsba":%s,"bhi":%s,"tsa_sq_no":%s,"tsa_l1_no":%s,"verw_clear":%s,"autoibrs":%s,"sbpb":%s,"avx2":%s,"avx512":%s}' \
"$(_json_cap "${cap_spec_ctrl:-}")" \
"$(_json_cap "${cap_ibrs:-}")" \
"$(_json_cap "${cap_ibpb:-}")" \
"$(_json_cap "${cap_ibpb_ret:-}")" \
"$(_json_cap "${cap_stibp:-}")" \
"$(_json_cap "${cap_ssbd:-}")" \
"$(_json_cap "${cap_l1df:-}")" \
"$(_json_cap "${cap_md_clear:-}")" \
"$(_json_cap "${cap_arch_capabilities:-}")" \
"$(_json_cap "${cap_rdcl_no:-}")" \
"$(_json_cap "${cap_ibrs_all:-}")" \
"$(_json_cap "${cap_rsba:-}")" \
"$(_json_cap "${cap_l1dflush_no:-}")" \
"$(_json_cap "${cap_ssb_no:-}")" \
"$(_json_cap "${cap_mds_no:-}")" \
"$(_json_cap "${cap_taa_no:-}")" \
"$(_json_cap "${cap_pschange_msc_no:-}")" \
"$(_json_cap "${cap_tsx_ctrl_msr:-}")" \
"$(_json_cap "${cap_tsx_ctrl_rtm_disable:-}")" \
"$(_json_cap "${cap_tsx_ctrl_cpuid_clear:-}")" \
"$(_json_cap "${cap_gds_ctrl:-}")" \
"$(_json_cap "${cap_gds_no:-}")" \
"$(_json_cap "${cap_gds_mitg_dis:-}")" \
"$(_json_cap "${cap_gds_mitg_lock:-}")" \
"$(_json_cap "${cap_rfds_no:-}")" \
"$(_json_cap "${cap_rfds_clear:-}")" \
"$(_json_cap "${cap_its_no:-}")" \
"$(_json_cap "${cap_sbdr_ssdp_no:-}")" \
"$(_json_cap "${cap_fbsdp_no:-}")" \
"$(_json_cap "${cap_psdp_no:-}")" \
"$(_json_cap "${cap_fb_clear:-}")" \
"$(_json_cap "${cap_rtm:-}")" \
"$(_json_cap "${cap_tsx_force_abort:-}")" \
"$(_json_cap "${cap_tsx_force_abort_rtm_disable:-}")" \
"$(_json_cap "${cap_tsx_force_abort_cpuid_clear:-}")" \
"$(_json_cap "${cap_sgx:-}")" \
"$(_json_cap "${cap_srbds:-}")" \
"$(_json_cap "${cap_srbds_on:-}")" \
"$(_json_cap "${cap_amd_ssb_no:-}")" \
"$(_json_cap "${cap_hygon_ssb_no:-}")" \
"$(_json_cap "${cap_ipred:-}")" \
"$(_json_cap "${cap_rrsba:-}")" \
"$(_json_cap "${cap_bhi:-}")" \
"$(_json_cap "${cap_tsa_sq_no:-}")" \
"$(_json_cap "${cap_tsa_l1_no:-}")" \
"$(_json_cap "${cap_verw_clear:-}")" \
"$(_json_cap "${cap_autoibrs:-}")" \
"$(_json_cap "$sbpb_norm")" \
"$(_json_cap "${cap_avx2:-}")" \
"$(_json_cap "${cap_avx512:-}")")
arch_sub=$(printf '{"family":%s,"model":%s,"stepping":%s,"cpuid":%s,"platform_id":%s,"hybrid":%s,"codename":%s,"capabilities":%s}' \
"$(_json_num "${cpu_family:-}")" \
"$(_json_num "${cpu_model:-}")" \
"$(_json_num "${cpu_stepping:-}")" \
"$(_json_str "$cpuid_hex")" \
"$(_json_num "${cpu_platformid:-}")" \
"$(_json_bool "${cpu_hybrid:-}")" \
"$(_json_str "$codename")" \
"$caps")
;;
ARM | CAVIUM | PHYTIUM)
arch_type='arm'
arch_sub=$(printf '{"part_list":%s,"arch_list":%s,"capabilities":{}}' \
"$(_json_str "${cpu_part_list:-}")" \
"$(_json_str "${cpu_arch_list:-}")")
;;
*)
arch_type=''
arch_sub=''
;;
esac
if [ -n "$arch_type" ]; then
g_json_cpu=$(printf '{"arch":"%s","vendor":%s,"friendly_name":%s,"%s":%s}' \
"$arch_type" \
"$(_json_str "${cpu_vendor:-}")" \
"$(_json_str "${cpu_friendly_name:-}")" \
"$arch_type" \
"$arch_sub")
else
g_json_cpu=$(printf '{"arch":null,"vendor":%s,"friendly_name":%s}' \
"$(_json_str "${cpu_vendor:-}")" \
"$(_json_str "${cpu_friendly_name:-}")")
fi
}
# Build the "cpu_microcode" section of the comprehensive JSON output
# Sets: g_json_cpu_microcode
# shellcheck disable=SC2034
_build_json_cpu_microcode() {
local ucode_uptodate ucode_hex latest_hex blacklisted
if [ -n "${cpu_ucode:-}" ]; then
ucode_hex=$(printf '0x%x' "$cpu_ucode")
else
ucode_hex=''
fi
is_latest_known_ucode
case $? in
0) ucode_uptodate='true' ;;
1) ucode_uptodate='false' ;;
*) ucode_uptodate='null' ;;
esac
if is_ucode_blacklisted; then
blacklisted='true'
else
blacklisted='false'
fi
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}' \
"$(_json_str "$ucode_hex")" \
"$(_json_str "$latest_hex")" \
"$ucode_uptodate" \
"$blacklisted" \
"$(_json_str "${ret_is_latest_known_ucode_latest:-}")" \
"$(_json_str "${g_mcedb_source:-}")" \
"$(_json_str "${g_mcedb_info:-}")")
}
# --- Format-specific batch emitters ---
# Emit a single CVE result as plain text
@@ -289,206 +16,45 @@ _emit_short() {
g_short_output="${g_short_output}$1 "
}
# Append a CVE result as a terse JSON object to the batch output buffer
# Append a CVE result as a JSON object to the batch output buffer
# Args: $1=cve $2=aka $3=status(UNK|VULN|OK) $4=description
# Sets: g_json_output
# Callers: pvulnstatus
_emit_json_terse() {
_emit_json() {
local is_vuln esc_name esc_infos
case "$3" in
UNK) is_vuln="null" ;;
VULN) is_vuln="true" ;;
OK) is_vuln="false" ;;
*)
echo "$0: error: unknown status '$3' passed to _emit_json_terse()" >&2
echo "$0: error: unknown status '$3' passed to _emit_json()" >&2
exit 255
;;
esac
esc_name=$(_json_escape "$2")
esc_infos=$(_json_escape "$4")
# escape backslashes and double quotes for valid JSON strings
esc_name=$(printf '%s' "$2" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g')
esc_infos=$(printf '%s' "$4" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g')
[ -z "$g_json_output" ] && g_json_output='['
g_json_output="${g_json_output}{\"NAME\":\"$esc_name\",\"CVE\":\"$1\",\"VULNERABLE\":$is_vuln,\"INFOS\":\"$esc_infos\"},"
}
# Append a CVE result as a comprehensive JSON object to the batch output buffer
# Args: $1=cve $2=aka $3=status(UNK|VULN|OK) $4=description
# Sets: g_json_vulns
# Callers: pvulnstatus
_emit_json_full() {
local is_vuln esc_name esc_infos aliases cpu_affected sysfs_status sysfs_msg
case "$3" in
UNK) is_vuln="null" ;;
VULN) is_vuln="true" ;;
OK) is_vuln="false" ;;
*)
echo "$0: error: unknown status '$3' passed to _emit_json_full()" >&2
exit 255
;;
esac
esc_name=$(_json_escape "$2")
esc_infos=$(_json_escape "$4")
aliases=$(_cve_registry_field "$1" 4)
# CPU affection status (cached, cheap)
if is_cpu_affected "$1" 2>/dev/null; then
cpu_affected='true'
else
cpu_affected='false'
fi
# sysfs status: use the value captured by this CVE's check function, then clear it
# so it doesn't leak into the next CVE that might not call sys_interface_check
sysfs_status="${g_json_cve_sysfs_status:-}"
sysfs_msg="${g_json_cve_sysfs_msg:-}"
: "${g_json_vulns:=}"
g_json_vulns="${g_json_vulns}{\"cve\":\"$1\",\"name\":\"$esc_name\",\"aliases\":$(_json_str "$aliases"),\"cpu_affected\":$cpu_affected,\"status\":\"$3\",\"vulnerable\":$is_vuln,\"info\":\"$esc_infos\",\"sysfs_status\":$(_json_str "$sysfs_status"),\"sysfs_message\":$(_json_str "$sysfs_msg")},"
}
# Accumulate a CVE result into the NRPE output buffers
# Append vulnerable CVE IDs to the NRPE output buffer
# Args: $1=cve $2=aka $3=status $4=description
# Sets: g_nrpe_total, g_nrpe_vuln_count, g_nrpe_unk_count, g_nrpe_vuln_ids, g_nrpe_vuln_details, g_nrpe_unk_details
# Sets: g_nrpe_vuln
# Callers: pvulnstatus
_emit_nrpe() {
g_nrpe_total=$((g_nrpe_total + 1))
case "$3" in
VULN)
g_nrpe_vuln_count=$((g_nrpe_vuln_count + 1))
g_nrpe_vuln_ids="${g_nrpe_vuln_ids:+$g_nrpe_vuln_ids }$1"
g_nrpe_vuln_details="${g_nrpe_vuln_details:+$g_nrpe_vuln_details\n}[CRITICAL] $1 ($2): $4"
;;
UNK)
g_nrpe_unk_count=$((g_nrpe_unk_count + 1))
g_nrpe_unk_details="${g_nrpe_unk_details:+$g_nrpe_unk_details\n}[UNKNOWN] $1 ($2): $4"
;;
esac
[ "$3" = VULN ] && g_nrpe_vuln="$g_nrpe_vuln $1"
}
# Append a CVE result as a Prometheus gauge to the batch output buffer
# Status is encoded numerically: 0=not_vulnerable, 1=vulnerable, 2=unknown
# Args: $1=cve $2=aka $3=status(UNK|VULN|OK) $4=description
# Sets: g_smc_vuln_output, g_smc_ok_count, g_smc_vuln_count, g_smc_unk_count
# Append a CVE result as a Prometheus metric to the batch output buffer
# Args: $1=cve $2=aka $3=status $4=description
# Sets: g_prometheus_output
# Callers: pvulnstatus
_emit_prometheus() {
local numeric_status cpu_affected full_name esc_name
case "$3" in
OK)
numeric_status=0
g_smc_ok_count=$((g_smc_ok_count + 1))
;;
VULN)
numeric_status=1
g_smc_vuln_count=$((g_smc_vuln_count + 1))
;;
UNK)
numeric_status=2
g_smc_unk_count=$((g_smc_unk_count + 1))
;;
*)
echo "$0: error: unknown status '$3' passed to _emit_prometheus()" >&2
exit 255
;;
esac
if is_cpu_affected "$1" 2>/dev/null; then
cpu_affected='true'
else
cpu_affected='false'
fi
# use the complete CVE name (field 4) rather than the short aka key (field 2)
full_name=$(_cve_registry_field "$1" 4)
esc_name=$(_prom_escape "$full_name")
g_smc_vuln_output="${g_smc_vuln_output:+$g_smc_vuln_output\n}smc_vulnerability_status{cve=\"$1\",name=\"$esc_name\",cpu_affected=\"$cpu_affected\"} $numeric_status"
}
# Build the smc_system_info Prometheus metric line
# Sets: g_smc_system_info_line
# Callers: src/main.sh (after check_cpu / check_cpu_vulnerabilities)
# shellcheck disable=SC2034
_build_prometheus_system_info() {
local kernel_release kernel_arch hypervisor_host sys_labels
if [ "$g_mode" = live ]; then
kernel_release=$(uname -r 2>/dev/null || true)
kernel_arch=$(uname -m 2>/dev/null || true)
else
kernel_release=''
kernel_arch=''
fi
case "${g_has_vmm:-}" in
1) hypervisor_host='true' ;;
0) hypervisor_host='false' ;;
*) hypervisor_host='' ;;
esac
sys_labels=''
[ -n "$kernel_release" ] && sys_labels="${sys_labels:+$sys_labels,}kernel_release=\"$(_prom_escape "$kernel_release")\""
[ -n "$kernel_arch" ] && sys_labels="${sys_labels:+$sys_labels,}kernel_arch=\"$(_prom_escape "$kernel_arch")\""
[ -n "$hypervisor_host" ] && sys_labels="${sys_labels:+$sys_labels,}hypervisor_host=\"$hypervisor_host\""
[ -n "$sys_labels" ] && g_smc_system_info_line="smc_system_info{$sys_labels} 1"
}
# Build the smc_cpu_info Prometheus metric line
# Sets: g_smc_cpu_info_line
# Callers: src/main.sh (after check_cpu / check_cpu_vulnerabilities)
# shellcheck disable=SC2034
_build_prometheus_cpu_info() {
local cpuid_hex ucode_hex ucode_latest_hex ucode_uptodate ucode_blacklisted codename smt_val cpu_labels
if [ -n "${cpu_cpuid:-}" ]; then
cpuid_hex=$(printf '0x%08x' "$cpu_cpuid")
else
cpuid_hex=''
fi
if [ -n "${cpu_ucode:-}" ]; then
ucode_hex=$(printf '0x%x' "$cpu_ucode")
else
ucode_hex=''
fi
is_latest_known_ucode
case $? in
0) ucode_uptodate='true' ;;
1) ucode_uptodate='false' ;;
*) ucode_uptodate='' ;;
esac
ucode_latest_hex="${ret_is_latest_known_ucode_version:-}"
if is_ucode_blacklisted; then
ucode_blacklisted='true'
else
ucode_blacklisted='false'
fi
codename=''
if is_intel; then
codename=$(get_intel_codename 2>/dev/null || true)
fi
is_cpu_smt_enabled
case $? in
0) smt_val='true' ;;
1) smt_val='false' ;;
*) smt_val='' ;;
esac
cpu_labels=''
[ -n "${cpu_vendor:-}" ] && cpu_labels="${cpu_labels:+$cpu_labels,}vendor=\"$(_prom_escape "$cpu_vendor")\""
[ -n "${cpu_friendly_name:-}" ] && cpu_labels="${cpu_labels:+$cpu_labels,}model=\"$(_prom_escape "$cpu_friendly_name")\""
# arch-specific labels
case "${cpu_vendor:-}" in
GenuineIntel | AuthenticAMD | HygonGenuine)
cpu_labels="${cpu_labels:+$cpu_labels,}arch=\"x86\""
[ -n "${cpu_family:-}" ] && cpu_labels="${cpu_labels:+$cpu_labels,}family=\"$cpu_family\""
[ -n "${cpu_model:-}" ] && cpu_labels="${cpu_labels:+$cpu_labels,}model_id=\"$cpu_model\""
[ -n "${cpu_stepping:-}" ] && cpu_labels="${cpu_labels:+$cpu_labels,}stepping=\"$cpu_stepping\""
[ -n "$cpuid_hex" ] && cpu_labels="${cpu_labels:+$cpu_labels,}cpuid=\"$cpuid_hex\""
[ -n "$codename" ] && cpu_labels="${cpu_labels:+$cpu_labels,}codename=\"$(_prom_escape "$codename")\""
;;
ARM | CAVIUM | PHYTIUM)
cpu_labels="${cpu_labels:+$cpu_labels,}arch=\"arm\""
[ -n "${cpu_part_list:-}" ] && cpu_labels="${cpu_labels:+$cpu_labels,}part_list=\"$(_prom_escape "$cpu_part_list")\""
[ -n "${cpu_arch_list:-}" ] && cpu_labels="${cpu_labels:+$cpu_labels,}arch_list=\"$(_prom_escape "$cpu_arch_list")\""
;;
esac
[ -n "$smt_val" ] && cpu_labels="${cpu_labels:+$cpu_labels,}smt=\"$smt_val\""
[ -n "$ucode_hex" ] && cpu_labels="${cpu_labels:+$cpu_labels,}microcode=\"$ucode_hex\""
[ -n "$ucode_latest_hex" ] && cpu_labels="${cpu_labels:+$cpu_labels,}microcode_latest=\"$ucode_latest_hex\""
[ -n "$ucode_uptodate" ] && cpu_labels="${cpu_labels:+$cpu_labels,}microcode_up_to_date=\"$ucode_uptodate\""
# always emit microcode_blacklisted when we have microcode info (it's a boolean, never omit)
[ -n "$ucode_hex" ] && cpu_labels="${cpu_labels:+$cpu_labels,}microcode_blacklisted=\"$ucode_blacklisted\""
[ -n "$cpu_labels" ] && g_smc_cpu_info_line="smc_cpu_info{$cpu_labels} 1"
local esc_info
# escape backslashes and double quotes for Prometheus label values
esc_info=$(printf '%s' "$4" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g')
g_prometheus_output="${g_prometheus_output:+$g_prometheus_output\n}specex_vuln_status{name=\"$2\",cve=\"$1\",status=\"$3\",info=\"$esc_info\"} 1"
}
# Update global state used to determine the program exit code
@@ -519,8 +85,7 @@ pvulnstatus() {
case "$opt_batch_format" in
text) _emit_text "$1" "$aka" "$2" "$3" ;;
short) _emit_short "$1" "$aka" "$2" "$3" ;;
json) _emit_json_full "$1" "$aka" "$2" "$3" ;;
json-terse) _emit_json_terse "$1" "$aka" "$2" "$3" ;;
json) _emit_json "$1" "$aka" "$2" "$3" ;;
nrpe) _emit_nrpe "$1" "$aka" "$2" "$3" ;;
prometheus) _emit_prometheus "$1" "$aka" "$2" "$3" ;;
*)
@@ -528,9 +93,6 @@ pvulnstatus() {
exit 255
;;
esac
# reset per-CVE sysfs globals so they don't leak into the next CVE
g_json_cve_sysfs_status=''
g_json_cve_sysfs_msg=''
fi
_record_result "$1" "$2"

View File

@@ -88,9 +88,7 @@ try_decompress() {
fi
pos=${pos%%:*}
# shellcheck disable=SC2086
# wrap in subshell so that if $3 segfaults (e.g. old BusyBox unlzma on random data),
# the "Segmentation fault" message printed by the shell goes to /dev/null
(tail -c+$pos "$6" 2>/dev/null | $3 $4 >"$g_kerneltmp" 2>/dev/null) 2>/dev/null
tail -c+$pos "$6" 2>/dev/null | $3 $4 >"$g_kerneltmp" 2>/dev/null
ret=$?
if [ ! -s "$g_kerneltmp" ]; then
# don't rely on $ret, sometimes it's != 0 but worked

View File

@@ -5,27 +5,20 @@ readonly WRITE_MSR_RET_ERR=2
readonly WRITE_MSR_RET_LOCKDOWN=3
# Write a value to an MSR register across one or all cores
# Args: $1=msr_address $2=value(optional) $3=cpu_index(optional, default 0)
# Sets: ret_write_msr_msg, ret_write_msr_ADDR_msg (where ADDR is the hex address, e.g. ret_write_msr_0x123_msg)
# Sets: ret_write_msr_msg
# Returns: WRITE_MSR_RET_OK | WRITE_MSR_RET_KO | WRITE_MSR_RET_ERR | WRITE_MSR_RET_LOCKDOWN
write_msr() {
local ret core first_core_ret msr_dec msr
msr_dec=$(($1))
msr=$(printf "0x%x" "$msr_dec")
local ret core first_core_ret
if [ "$opt_cpu" != all ]; then
# we only have one core to write to, do it and return the result
write_msr_one_core "$opt_cpu" "$@"
ret=$?
# shellcheck disable=SC2163
eval "ret_write_msr_${msr}_msg=\$ret_write_msr_msg"
return $ret
return $?
fi
# otherwise we must write on all cores
for core in $(seq 0 "$g_max_core_id"); do
write_msr_one_core "$core" "$@"
ret=$?
# shellcheck disable=SC2163
eval "ret_write_msr_${msr}_msg=\$ret_write_msr_msg"
if [ "$core" = 0 ]; then
# save the result of the first core, for comparison with the others
first_core_ret=$ret
@@ -33,8 +26,6 @@ write_msr() {
# compare first core with the other ones
if [ "$first_core_ret" != "$ret" ]; then
ret_write_msr_msg="result is not homogeneous between all cores, at least core 0 and $core differ!"
# shellcheck disable=SC2163
eval "ret_write_msr_${msr}_msg=\$ret_write_msr_msg"
return $WRITE_MSR_RET_ERR
fi
fi
@@ -52,7 +43,7 @@ write_msr_one_core() {
core="$1"
msr_dec=$(($2))
msr=$(printf "0x%x" "$msr_dec")
value_dec=$((${3:-0}))
value_dec=$(($3))
value=$(printf "0x%x" "$value_dec")
ret_write_msr_msg='unknown error'
@@ -61,30 +52,10 @@ write_msr_one_core() {
mockvarname="SMC_MOCK_WRMSR_${msr}_RET"
# shellcheck disable=SC2086,SC1083
if [ -n "$(eval echo \${$mockvarname:-})" ]; then
local mockret
mockret="$(eval echo \$$mockvarname)"
pr_debug "write_msr: MOCKING enabled for msr $msr func returns $mockret"
pr_debug "write_msr: MOCKING enabled for msr $msr func returns $(eval echo \$$mockvarname)"
g_mocked=1
if [ "$mockret" = "$WRITE_MSR_RET_LOCKDOWN" ]; then
g_msr_locked_down=1
ret_write_msr_msg="kernel lockdown is enabled, MSR writes are restricted"
elif [ "$mockret" = "$WRITE_MSR_RET_ERR" ]; then
ret_write_msr_msg="could not write MSR"
fi
return "$mockret"
fi
# proactive lockdown detection via sysfs (vanilla 5.4+, CentOS 8+, Rocky 9+):
# if the kernel lockdown is set to integrity or confidentiality, MSR writes will be denied,
# so we can skip the write attempt entirely and avoid relying on dmesg parsing
if [ -e "$SYSKERNEL_BASE/security/lockdown" ]; then
if grep -qE '\[integrity\]|\[confidentiality\]' "$SYSKERNEL_BASE/security/lockdown" 2>/dev/null; then
pr_debug "write_msr: kernel lockdown detected via $SYSKERNEL_BASE/security/lockdown"
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_WRMSR_${msr}_RET=$WRITE_MSR_RET_LOCKDOWN")
g_msr_locked_down=1
ret_write_msr_msg="your kernel is locked down, please reboot with lockdown=none in the kernel cmdline and retry"
return $WRITE_MSR_RET_LOCKDOWN
fi
[ "$(eval echo \$$mockvarname)" = $WRITE_MSR_RET_LOCKDOWN ] && g_msr_locked_down=1
return "$(eval echo \$$mockvarname)"
fi
if [ ! -e $CPU_DEV_BASE/0/msr ] && [ ! -e ${BSD_CPUCTL_DEV_BASE}0 ]; then
@@ -92,7 +63,7 @@ write_msr_one_core() {
load_msr
fi
if [ ! -e $CPU_DEV_BASE/0/msr ] && [ ! -e ${BSD_CPUCTL_DEV_BASE}0 ]; then
ret_write_msr_msg="msr kernel module is not available"
ret_read_msr_msg="is msr kernel module available?"
return $WRITE_MSR_RET_ERR
fi
@@ -102,13 +73,14 @@ write_msr_one_core() {
ret=$?
else
# for Linux
# convert to decimal
if [ ! -w $CPU_DEV_BASE/"$core"/msr ]; then
ret_write_msr_msg="No write permission on $CPU_DEV_BASE/$core/msr"
return $WRITE_MSR_RET_ERR
# if wrmsr is available, use it
elif command -v wrmsr >/dev/null 2>&1 && [ "${SMC_NO_WRMSR:-}" != 1 ]; then
pr_debug "write_msr: using wrmsr"
wrmsr -p "$core" $msr_dec $value_dec 2>/dev/null
wrmsr $msr_dec $value_dec 2>/dev/null
ret=$?
# ret=4: msr doesn't exist, ret=127: msr.allow_writes=off
[ "$ret" = 127 ] && write_denied=1
@@ -187,31 +159,22 @@ readonly MSR_IA32_MCU_OPT_CTRL=0x123
readonly READ_MSR_RET_OK=0
readonly READ_MSR_RET_KO=1
readonly READ_MSR_RET_ERR=2
readonly READ_MSR_RET_LOCKDOWN=3
# Read an MSR register value across one or all cores
# Args: $1=msr_address $2=cpu_index(optional, default 0)
# Sets: ret_read_msr_value, ret_read_msr_value_hi, ret_read_msr_value_lo, ret_read_msr_msg,
# ret_read_msr_ADDR_msg (where ADDR is the hex address, e.g. ret_read_msr_0x10a_msg)
# Returns: READ_MSR_RET_OK | READ_MSR_RET_KO | READ_MSR_RET_ERR | READ_MSR_RET_LOCKDOWN
# Sets: ret_read_msr_value, ret_read_msr_value_hi, ret_read_msr_value_lo, ret_read_msr_msg
# Returns: READ_MSR_RET_OK | READ_MSR_RET_KO | READ_MSR_RET_ERR
read_msr() {
local ret core first_core_ret first_core_value msr_dec msr
msr_dec=$(($1))
msr=$(printf "0x%x" "$msr_dec")
local ret core first_core_ret first_core_value
if [ "$opt_cpu" != all ]; then
# we only have one core to read, do it and return the result
read_msr_one_core "$opt_cpu" "$@"
ret=$?
# shellcheck disable=SC2163
eval "ret_read_msr_${msr}_msg=\$ret_read_msr_msg"
return $ret
return $?
fi
# otherwise we must read all cores
for core in $(seq 0 "$g_max_core_id"); do
read_msr_one_core "$core" "$@"
ret=$?
# shellcheck disable=SC2163
eval "ret_read_msr_${msr}_msg=\$ret_read_msr_msg"
if [ "$core" = 0 ]; then
# save the result of the first core, for comparison with the others
first_core_ret=$ret
@@ -220,8 +183,6 @@ read_msr() {
# compare first core with the other ones
if [ "$first_core_ret" != "$ret" ] || [ "$first_core_value" != "$ret_read_msr_value" ]; then
ret_read_msr_msg="result is not homogeneous between all cores, at least core 0 and $core differ!"
# shellcheck disable=SC2163
eval "ret_read_msr_${msr}_msg=\$ret_read_msr_msg"
return $READ_MSR_RET_ERR
fi
fi
@@ -233,7 +194,7 @@ read_msr() {
# Read an MSR register value from a single CPU core
# Args: $1=core $2=msr_address
# Sets: ret_read_msr_value, ret_read_msr_value_hi, ret_read_msr_value_lo, ret_read_msr_msg
# Returns: READ_MSR_RET_OK | READ_MSR_RET_KO | READ_MSR_RET_ERR | READ_MSR_RET_LOCKDOWN
# Returns: READ_MSR_RET_OK | READ_MSR_RET_KO | READ_MSR_RET_ERR
read_msr_one_core() {
local ret core msr msr_dec mockvarname msr_h msr_l mockval
core="$1"
@@ -265,29 +226,9 @@ read_msr_one_core() {
mockvarname="SMC_MOCK_RDMSR_${msr}_RET"
# shellcheck disable=SC2086,SC1083
if [ -n "$(eval echo \${$mockvarname:-})" ] && [ "$(eval echo \$$mockvarname)" -ne 0 ]; then
local mockret
mockret="$(eval echo \$$mockvarname)"
pr_debug "read_msr: MOCKING enabled for msr $msr func returns $mockret"
pr_debug "read_msr: MOCKING enabled for msr $msr func returns $(eval echo \$$mockvarname)"
g_mocked=1
if [ "$mockret" = "$READ_MSR_RET_LOCKDOWN" ]; then
ret_read_msr_msg="kernel lockdown is enabled, MSR reads are restricted"
elif [ "$mockret" = "$READ_MSR_RET_ERR" ]; then
ret_read_msr_msg="could not read MSR"
fi
return "$mockret"
fi
# proactive lockdown detection via sysfs (vanilla 5.4+, CentOS 8+, Rocky 9+):
# if the kernel lockdown is set to integrity or confidentiality, MSR reads will be denied,
# so we can skip the read attempt entirely and avoid relying on dmesg parsing
if [ -e "$SYSKERNEL_BASE/security/lockdown" ]; then
if grep -qE '\[integrity\]|\[confidentiality\]' "$SYSKERNEL_BASE/security/lockdown" 2>/dev/null; then
pr_debug "read_msr: kernel lockdown detected via $SYSKERNEL_BASE/security/lockdown"
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_RDMSR_${msr}_RET=$READ_MSR_RET_LOCKDOWN")
g_msr_locked_down=1
ret_read_msr_msg="kernel lockdown is enabled, MSR reads are restricted"
return $READ_MSR_RET_LOCKDOWN
fi
return "$(eval echo \$$mockvarname)"
fi
if [ ! -e $CPU_DEV_BASE/0/msr ] && [ ! -e ${BSD_CPUCTL_DEV_BASE}0 ]; then
@@ -295,7 +236,7 @@ read_msr_one_core() {
load_msr
fi
if [ ! -e $CPU_DEV_BASE/0/msr ] && [ ! -e ${BSD_CPUCTL_DEV_BASE}0 ]; then
ret_read_msr_msg="msr kernel module is not available"
ret_read_msr_msg="is msr kernel module available?"
return $READ_MSR_RET_ERR
fi

View File

@@ -24,22 +24,13 @@ parse_cpu_details() {
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_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
# (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
cpu_impl_list=$(awk '/CPU implementer/ {print $4}' "$g_procfs/cpuinfo")
cpu_part_list=$(awk '/CPU part/ {print $4}' "$g_procfs/cpuinfo")
cpu_arch_list=$(awk '/CPU architecture/ {print $3}' "$g_procfs/cpuinfo")
cpu_variant_list=$(awk '/CPU variant/ {print $4}' "$g_procfs/cpuinfo")
cpu_revision_list=$(awk '/CPU revision/ {print $4}' "$g_procfs/cpuinfo")
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.
# special case for ARM follows
if grep -qi 'CPU implementer[[:space:]]*:[[:space:]]*0x41' "$g_procfs/cpuinfo"; then
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
# shellcheck disable=SC2086
arch=$(echo $cpu_arch_list | awk '{ print $1 }')
@@ -74,7 +65,6 @@ parse_cpu_details() {
# see https://elixir.bootlin.com/linux/v6.0/source/arch/x86/kernel/cpu/microcode/intel.c#L694
# Set it to 8 (impossible value as it is 3 bit long) by default
cpu_platformid=8
# use direct cpu_vendor comparison: is_intel() calls parse_cpu_details() which would recurse
if [ "$cpu_vendor" = GenuineIntel ] && [ "$cpu_model" -ge 5 ]; then
read_msr $MSR_IA32_PLATFORM_ID
ret=$?
@@ -127,23 +117,6 @@ parse_cpu_details() {
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_CPU_PLATFORMID='$cpu_platformid'")
fi
# Detect hybrid CPU: CPUID.(EAX=7,ECX=0):EDX[15] = 1 means hybrid
cpu_hybrid=0
# use direct cpu_vendor comparison: is_intel() calls parse_cpu_details() which would recurse
if [ "$cpu_vendor" = GenuineIntel ]; then
read_cpuid 0x7 0x0 $EDX 15 1 1
if [ $? = $READ_CPUID_RET_OK ]; then
cpu_hybrid=1
fi
fi
if [ -n "${SMC_MOCK_CPU_HYBRID:-}" ]; then
cpu_hybrid="$SMC_MOCK_CPU_HYBRID"
pr_debug "parse_cpu_details: MOCKING cpu hybrid to $cpu_hybrid"
g_mocked=1
else
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_CPU_HYBRID='$cpu_hybrid'")
fi
# get raw cpuid, it's always useful (referenced in the Intel doc for firmware updates for example)
if [ "$g_mocked" != 1 ] && read_cpuid 0x1 0x0 $EAX 0 0xFFFFFFFF; then
cpu_cpuid="$ret_read_cpuid_value"
@@ -157,8 +130,7 @@ parse_cpu_details() {
if [ -z "$cpu_ucode" ] && [ "$g_os" != Linux ]; then
load_cpuid
if [ -e ${BSD_CPUCTL_DEV_BASE}0 ]; then
# use direct cpu_vendor comparison: is_amd/is_hygon/is_intel() call parse_cpu_details() which would recurse
if [ "$cpu_vendor" = AuthenticAMD ] || [ "$cpu_vendor" = HygonGenuine ]; then
if [ "$cpu_vendor" = AuthenticAMD ]; then
# AMD: read MSR_PATCHLEVEL (0xC0010058) directly
cpu_ucode=$(cpucontrol -m 0xC0010058 ${BSD_CPUCTL_DEV_BASE}0 2>/dev/null | awk '{print $3}')
elif [ "$cpu_vendor" = GenuineIntel ]; then
@@ -191,15 +163,11 @@ parse_cpu_details() {
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_CPU_UCODE='$cpu_ucode'")
fi
local ucode_str
if [ -n "$cpu_ucode" ]; then
echo "$cpu_ucode" | grep -q ^0x && cpu_ucode=$((cpu_ucode))
ucode_str=$(printf "0x%x" "$cpu_ucode")
else
ucode_str="unknown"
fi
g_ucode_found=$(printf "family 0x%x model 0x%x stepping 0x%x ucode %s cpuid 0x%x pfid 0x%x" \
"$cpu_family" "$cpu_model" "$cpu_stepping" "$ucode_str" "$cpu_cpuid" "$cpu_platformid")
g_ucode_found=$(printf "family 0x%x model 0x%x stepping 0x%x ucode 0x%s cpuid 0x%x pfid 0x%x" \
"$cpu_family" "$cpu_model" "$cpu_stepping" "${cpu_ucode:-unknown}" "$cpu_cpuid" "$cpu_platformid")
g_parse_cpu_details_done=1
}

View File

@@ -21,28 +21,6 @@ is_intel() {
return 1
}
# Check whether the host CPU is x86/x86_64.
# Use this to gate CPUID, MSR, and microcode operations.
# Returns: 0 if x86, 1 otherwise
is_x86_cpu() {
parse_cpu_details
case "$cpu_vendor" in
GenuineIntel | AuthenticAMD | HygonGenuine | CentaurHauls | Shanghai) return 0 ;;
esac
return 1
}
# Check whether the host CPU is ARM/ARM64.
# Use this to gate ARM-specific hardware checks.
# Returns: 0 if ARM, 1 otherwise
is_arm_cpu() {
parse_cpu_details
case "$cpu_vendor" in
ARM | CAVIUM | PHYTIUM) return 0 ;;
esac
return 1
}
# Check whether SMT (HyperThreading) is enabled on the system
# Returns: 0 if SMT enabled, 1 otherwise
is_cpu_smt_enabled() {

View File

@@ -1,120 +0,0 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# Kernel architecture detection helpers.
# Detects the target kernel's architecture regardless of the host system,
# enabling correct behavior in offline cross-inspection (e.g. x86 host
# analyzing an ARM kernel image or System.map).
# Global cache; populated by _detect_kernel_arch on first call.
# Values: 'arm', 'x86', 'unknown'
g_kernel_arch=''
# Internal: populate g_kernel_arch using all available information sources,
# in order from most to least reliable.
_detect_kernel_arch() {
# Return immediately if already detected
[ -n "$g_kernel_arch" ] && return 0
# arm64_sys_ is the ARM64 syscall table symbol prefix; present in any
# ARM64 System.map (or /proc/kallsyms) and in the kernel image itself.
# sys_call_table + vector_swi is the ARM (32-bit) equivalent.
if [ -n "$opt_map" ]; then
if grep -q 'arm64_sys_' "$opt_map" 2>/dev/null; then
g_kernel_arch='arm'
return 0
fi
if grep -q ' vector_swi$' "$opt_map" 2>/dev/null; then
g_kernel_arch='arm'
return 0
fi
fi
if [ -n "$g_kernel" ]; then
if grep -q 'arm64_sys_' "$g_kernel" 2>/dev/null; then
g_kernel_arch='arm'
return 0
fi
fi
# Kconfig is definitive when available
if [ -n "$opt_config" ]; then
if grep -qE '^CONFIG_(ARM64|ARM)=y' "$opt_config" 2>/dev/null; then
g_kernel_arch='arm'
return 0
fi
if grep -qE '^CONFIG_X86(_64)?=y' "$opt_config" 2>/dev/null; then
g_kernel_arch='x86'
return 0
fi
fi
# Cross-compilation prefix as a last resort (e.g. --arch-prefix aarch64-linux-gnu-)
case "${opt_arch_prefix:-}" in
aarch64-* | arm64-* | arm-* | armv*-)
g_kernel_arch='arm'
return 0
;;
x86_64-* | i686-* | i?86-*)
g_kernel_arch='x86'
return 0
;;
esac
# Last resort: if no artifacts identified the arch, assume the target
# kernel matches the host CPU. This covers live mode when no kernel
# image, config, or System.map is available.
if is_x86_cpu; then
g_kernel_arch='x86'
return 0
fi
if is_arm_cpu; then
g_kernel_arch='arm'
return 0
fi
g_kernel_arch='unknown'
return 0
}
# Return 0 (true) if the target kernel is ARM (32 or 64-bit), 1 otherwise.
is_arm_kernel() {
_detect_kernel_arch
[ "$g_kernel_arch" = 'arm' ]
}
# Return 0 (true) if the target kernel is x86/x86_64, 1 otherwise.
is_x86_kernel() {
_detect_kernel_arch
[ "$g_kernel_arch" = 'x86' ]
}
# Compare the target kernel's architecture against the host CPU.
# If they differ, hardware reads (CPUID, MSR, sysfs) would reflect the host,
# not the target kernel — force no-hw mode to avoid misleading results.
# Sets: g_mode (when mismatch detected)
# Callers: src/main.sh (after check_kernel_info, before check_cpu)
check_kernel_cpu_arch_mismatch() {
local host_arch
_detect_kernel_arch
host_arch='unknown'
if is_x86_cpu; then
host_arch='x86'
elif is_arm_cpu; then
host_arch='arm'
fi
# Unsupported CPU architecture (MIPS, RISC-V, PowerPC, ...): force no-hw
# since we have no hardware-level checks for these platforms
if [ "$host_arch" = 'unknown' ]; then
pr_warn "Unsupported CPU architecture (vendor: $cpu_vendor), forcing no-hw mode"
g_mode='no-hw'
return 0
fi
# If kernel arch is unknown, we can't tell if there's a mismatch
[ "$g_kernel_arch" = 'unknown' ] && return 0
[ "$host_arch" = "$g_kernel_arch" ] && return 0
pr_warn "Target kernel architecture ($g_kernel_arch) differs from host CPU ($host_arch), forcing no-hw mode"
g_mode='no-hw'
}

View File

@@ -26,16 +26,18 @@ read_mcedb() {
# Read the Intel official affected CPUs database (builtin) to stdout
read_inteldb() {
awk '/^# %%% ENDOFINTELDB/ { exit } { if (DELIM==1) { print $2 } } /^# %%% INTELDB/ { DELIM=1 }' "$0"
if [ "$opt_intel_db" = 1 ]; then
awk '/^# %%% ENDOFINTELDB/ { exit } { if (DELIM==1) { print $2 } } /^# %%% INTELDB/ { DELIM=1 }' "$0"
fi
# otherwise don't output nothing, it'll be as if the database is empty
}
# Check whether the CPU is running the latest known microcode version
# Sets: ret_is_latest_known_ucode_latest, ret_is_latest_known_ucode_version
# Sets: ret_is_latest_known_ucode_latest
# Returns: 0=latest, 1=outdated, 2=unknown
is_latest_known_ucode() {
local brand_prefix tuple pfmask ucode ucode_date
parse_cpu_details
ret_is_latest_known_ucode_version=''
if [ "$cpu_cpuid" = 0 ]; then
ret_is_latest_known_ucode_latest="couldn't get your cpuid"
return 2
@@ -62,8 +64,6 @@ is_latest_known_ucode() {
ucode_date=$(echo "$tuple" | cut -d, -f5 | sed -E 's=(....)(..)(..)=\1/\2/\3=')
pr_debug "is_latest_known_ucode: with cpuid $cpu_cpuid has ucode $cpu_ucode, last known is $ucode from $ucode_date"
ret_is_latest_known_ucode_latest=$(printf "latest version is 0x%x dated $ucode_date according to $g_mcedb_info" "$ucode")
# shellcheck disable=SC2034
ret_is_latest_known_ucode_version=$(printf "0x%x" "$ucode")
if [ "$cpu_ucode" -ge "$ucode" ]; then
return 0
else

View File

@@ -18,7 +18,7 @@ if [ "$g_os" = Darwin ] || [ "$g_os" = VMkernel ]; then
fi
# check for mode selection inconsistency
if [ "$g_mode" = hw-only ]; then
if [ "$opt_hw_only" = 1 ]; then
if [ "$opt_cve_all" = 0 ]; then
show_usage
echo "$0: error: incompatible modes specified, --hw-only vs --variant" >&2
@@ -89,8 +89,10 @@ if [ "$opt_cpu" != all ] && [ "$opt_cpu" -gt "$g_max_core_id" ]; then
exit 255
fi
if has_runtime; then
if [ "$opt_live" = 1 ]; then
pr_info "Checking for vulnerabilities on current system"
pr_info "Kernel is \033[35m$g_os $(uname -r) $(uname -v) $(uname -m)\033[0m"
pr_info "CPU is \033[35m$cpu_friendly_name\033[0m"
# try to find the image of the current running kernel
if [ -n "$opt_kernel" ]; then
@@ -187,6 +189,7 @@ if has_runtime; then
fi
else
pr_info "Checking for vulnerabilities against specified kernel"
pr_info "CPU is \033[35m$cpu_friendly_name\033[0m"
fi
if [ -n "$opt_kernel" ]; then
@@ -219,14 +222,16 @@ if [ "$g_os" = Linux ]; then
g_bad_accuracy=1
fi
: "${g_bad_accuracy:=0}"
if [ "${g_bad_accuracy:=0}" = 1 ]; then
pr_warn "We're missing some kernel info (see -v), accuracy might be reduced"
fi
fi
if [ -e "$opt_kernel" ]; then
if ! command -v "${opt_arch_prefix}readelf" >/dev/null 2>&1; then
pr_debug "readelf not found"
g_kernel_err="missing '${opt_arch_prefix}readelf' tool, please install it, usually it's in the 'binutils' package"
elif [ "$opt_sysfs_only" = 1 ] || [ "$g_mode" = hw-only ]; then
elif [ "$opt_sysfs_only" = 1 ] || [ "$opt_hw_only" = 1 ]; then
g_kernel_err='kernel image decompression skipped'
else
extract_kernel "$opt_kernel"
@@ -251,13 +256,13 @@ else
fi
if [ -n "$g_kernel_version" ]; then
# in live mode, check if the img we found is the correct one
if has_runtime; then
if [ "$opt_live" = 1 ]; then
pr_verbose "Kernel image is \033[35m$g_kernel_version"
if ! echo "$g_kernel_version" | grep -qF "$(uname -r)"; then
pr_warn "Possible discrepancy between your running kernel '$(uname -r)' and the image '$g_kernel_version' we found ($opt_kernel), results might be incorrect"
fi
else
pr_verbose "Kernel image is \033[35m$g_kernel_version"
pr_info "Kernel image is \033[35m$g_kernel_version"
fi
else
pr_verbose "Kernel image version is unknown"
@@ -283,7 +288,7 @@ sys_interface_check() {
msg=''
ret_sys_interface_check_fullmsg=''
if has_runtime && [ "$opt_no_sysfs" = 0 ] && [ -r "$file" ]; then
if [ "$opt_live" = 1 ] && [ "$opt_no_sysfs" = 0 ] && [ -r "$file" ]; then
:
else
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_SYSFS_$(basename "$file")_RET=1")
@@ -312,14 +317,9 @@ sys_interface_check() {
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_SYSFS_$(basename "$file")='$ret_sys_interface_check_fullmsg'")
fi
if [ "$mode" = silent ]; then
# capture sysfs message for JSON even in silent mode
# shellcheck disable=SC2034
g_json_cve_sysfs_msg="$ret_sys_interface_check_fullmsg"
return 0
elif [ "$mode" = quiet ]; then
pr_info "* Information from the /sys interface: $ret_sys_interface_check_fullmsg"
# shellcheck disable=SC2034
g_json_cve_sysfs_msg="$ret_sys_interface_check_fullmsg"
return 0
fi
pr_info_nol "* Mitigated according to the /sys interface: "
@@ -339,83 +339,19 @@ sys_interface_check() {
ret_sys_interface_check_status=UNK
pstatus yellow UNKNOWN "$ret_sys_interface_check_fullmsg"
fi
# capture for JSON full output (read by _emit_json_full via pvulnstatus)
# shellcheck disable=SC2034
g_json_cve_sysfs_status="$ret_sys_interface_check_status"
# shellcheck disable=SC2034
g_json_cve_sysfs_msg="$ret_sys_interface_check_fullmsg"
pr_debug "sys_interface_check: $file=$msg (re=$regex)"
return 0
}
# Display kernel image, config, and System.map availability
check_kernel_info() {
local config_display
pr_info "\033[1;34mKernel information\033[0m"
if has_runtime; then
pr_info "* Kernel is \033[35m$g_os $(uname -r) $(uname -v) $(uname -m)\033[0m"
elif [ -n "$g_kernel_version" ]; then
pr_info "* Kernel is \033[35m$g_kernel_version\033[0m"
else
pr_info "* Kernel is \033[35munknown\033[0m"
fi
if [ -n "$opt_kernel" ] && [ -e "$opt_kernel" ]; then
pr_info "* Kernel image found at \033[35m$opt_kernel\033[0m"
else
pr_info "* Kernel image NOT found"
fi
if [ -n "$opt_config" ]; then
if [ -n "${g_dumped_config:-}" ]; then
config_display="$g_procfs/config.gz"
else
config_display="$opt_config"
fi
pr_info "* Kernel config found at \033[35m$config_display\033[0m"
else
pr_info "* Kernel config NOT found"
fi
if [ -n "$opt_map" ]; then
pr_info "* Kernel System.map found at \033[35m$opt_map\033[0m"
else
pr_info "* Kernel System.map NOT found"
fi
if [ "${g_bad_accuracy:-0}" = 1 ]; then
pr_warn "We're missing some kernel info, accuracy might be reduced"
fi
}
# Display hardware-level CPU mitigation support (microcode features, ARCH_CAPABILITIES, etc.)
check_cpu() {
local capabilities ret spec_ctrl_msr codename ucode_str
local capabilities ret spec_ctrl_msr
pr_info "\033[1;34mHardware check\033[0m"
if ! uname -m | grep -qwE 'x86_64|i[3-6]86|amd64'; then
return
fi
pr_info "* CPU details"
pr_info " * Vendor: $cpu_vendor"
pr_info " * Model name: $cpu_friendly_name"
pr_info " * Family: $(printf '0x%02x' "$cpu_family") Model: $(printf '0x%02x' "$cpu_model") Stepping: $(printf '0x%02x' "$cpu_stepping")"
if [ -n "$cpu_ucode" ]; then
ucode_str=$(printf '0x%x' "$cpu_ucode")
else
ucode_str="N/A"
fi
pr_info " * Microcode: $ucode_str"
pr_info " * CPUID: $(printf '0x%08x' "$cpu_cpuid")"
if is_intel; then
pr_info " * Platform ID: $(printf '0x%02x' "$cpu_platformid")"
if [ "$cpu_hybrid" = 1 ]; then
pr_info " * Hybrid CPU: YES"
else
pr_info " * Hybrid CPU: NO"
fi
codename=$(get_intel_codename)
if [ -n "$codename" ]; then
pr_info " * Codename: $codename"
fi
fi
pr_info "* Hardware support (CPU microcode) for mitigation techniques"
pr_info " * Indirect Branch Restricted Speculation (IBRS)"
pr_info_nol " * SPEC_CTRL MSR is available: "
@@ -456,15 +392,6 @@ check_cpu() {
ret=invalid
pstatus yellow NO "unknown CPU"
fi
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
if grep ^flags "$g_procfs/cpuinfo" | grep -qw ibrs; then
cap_ibrs='IBRS (cpuinfo)'
cap_spec_ctrl=1
pstatus green YES "ibrs flag in $g_procfs/cpuinfo"
ret=$READ_CPUID_RET_OK
fi
fi
if [ $ret = $READ_CPUID_RET_KO ]; then
pstatus yellow NO
elif [ $ret = $READ_CPUID_RET_ERR ]; then
@@ -533,10 +460,6 @@ check_cpu() {
if [ $ret = $READ_CPUID_RET_OK ]; then
cap_ibpb='IBPB_SUPPORT'
pstatus green YES "IBPB_SUPPORT feature bit"
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
cap_ibpb='IBPB (cpuinfo)'
pstatus green YES "ibpb flag in $g_procfs/cpuinfo"
elif [ $ret = $READ_CPUID_RET_KO ]; then
pstatus yellow NO
else
@@ -572,7 +495,7 @@ check_cpu() {
elif [ "$spec_ctrl_msr" = 0 ]; then
pstatus yellow NO
else
pstatus yellow UNKNOWN "$ret_read_msr_msg"
pstatus yellow UNKNOWN "is msr kernel module available?"
fi
pr_info_nol " * CPU indicates STIBP capability: "
@@ -604,14 +527,6 @@ check_cpu() {
ret=invalid
pstatus yellow UNKNOWN "unknown CPU"
fi
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
if grep ^flags "$g_procfs/cpuinfo" | grep -qw stibp; then
cap_stibp='STIBP (cpuinfo)'
pstatus green YES "stibp flag in $g_procfs/cpuinfo"
ret=$READ_CPUID_RET_OK
fi
fi
if [ $ret = $READ_CPUID_RET_KO ]; then
pstatus yellow NO
elif [ $ret = $READ_CPUID_RET_ERR ]; then
@@ -676,15 +591,6 @@ check_cpu() {
fi
fi
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
if grep ^flags "$g_procfs/cpuinfo" | grep -qw ssbd; then
cap_ssbd='SSBD (cpuinfo)'
elif grep ^flags "$g_procfs/cpuinfo" | grep -qw virt_ssbd; then
cap_ssbd='SSBD in VIRT_SPEC_CTRL (cpuinfo)'
fi
fi
if [ -n "${cap_ssbd:=}" ]; then
pstatus green YES "$cap_ssbd"
elif [ "$ret24" = $READ_CPUID_RET_ERR ] && [ "$ret25" = $READ_CPUID_RET_ERR ]; then
@@ -720,16 +626,17 @@ check_cpu() {
if [ "$opt_allow_msr_write" = 1 ]; then
pr_info_nol " * FLUSH_CMD MSR is available: "
# the new MSR 'FLUSH_CMD' is at offset 0x10b, write-only
# this is probed for informational purposes only, the CPUID L1D flush bit
# (cap_l1df) is the authoritative indicator per Intel guidance
write_msr 0x10b
ret=$?
if [ $ret = $WRITE_MSR_RET_OK ]; then
pstatus green YES
cap_flush_cmd=1
elif [ $ret = $WRITE_MSR_RET_KO ]; then
pstatus yellow NO
cap_flush_cmd=0
else
pstatus yellow UNKNOWN "$ret_write_msr_msg"
cap_flush_cmd=-1
fi
fi
@@ -740,10 +647,6 @@ check_cpu() {
if [ $ret = $READ_CPUID_RET_OK ]; then
pstatus green YES "L1D flush feature bit"
cap_l1df=1
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
pstatus green YES "flush_l1d flag in $g_procfs/cpuinfo"
cap_l1df=1
elif [ $ret = $READ_CPUID_RET_KO ]; then
pstatus yellow NO
cap_l1df=0
@@ -752,6 +655,12 @@ check_cpu() {
cap_l1df=-1
fi
# if we weren't allowed to probe the write-only MSR but the CPUID
# bit says that it shoul be there, make the assumption that it is
if [ "$opt_allow_msr_write" != 1 ]; then
cap_flush_cmd=$cap_l1df
fi
if is_intel; then
pr_info " * Microarchitectural Data Sampling"
pr_info_nol " * VERW instruction is available: "
@@ -760,10 +669,6 @@ check_cpu() {
if [ $ret = $READ_CPUID_RET_OK ]; then
cap_md_clear=1
pstatus green YES "MD_CLEAR feature bit"
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
cap_md_clear=1
pstatus green YES "md_clear flag in $g_procfs/cpuinfo"
elif [ $ret = $READ_CPUID_RET_KO ]; then
cap_md_clear=0
pstatus yellow NO
@@ -830,10 +735,6 @@ check_cpu() {
if [ $ret = $READ_CPUID_RET_OK ]; then
pstatus green YES
cap_arch_capabilities=1
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
pstatus green YES "arch_capabilities flag in $g_procfs/cpuinfo"
cap_arch_capabilities=1
elif [ $ret = $READ_CPUID_RET_KO ]; then
pstatus yellow NO
cap_arch_capabilities=0
@@ -856,10 +757,6 @@ check_cpu() {
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
if [ "$cap_arch_capabilities" = -1 ]; then
pstatus yellow UNKNOWN
elif [ "$cap_arch_capabilities" != 1 ]; then
@@ -877,10 +774,6 @@ check_cpu() {
cap_rfds_no=0
cap_rfds_clear=0
cap_its_no=0
cap_sbdr_ssdp_no=0
cap_fbsdp_no=0
cap_psdp_no=0
cap_fb_clear=0
pstatus yellow NO
else
read_msr $MSR_IA32_ARCH_CAPABILITIES
@@ -899,10 +792,6 @@ check_cpu() {
cap_rfds_no=0
cap_rfds_clear=0
cap_its_no=0
cap_sbdr_ssdp_no=0
cap_fbsdp_no=0
cap_psdp_no=0
cap_fb_clear=0
if [ $ret = $READ_MSR_RET_OK ]; then
capabilities=$ret_read_msr_value
# https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/arch/x86/include/asm/msr-index.h#n82
@@ -916,16 +805,12 @@ check_cpu() {
[ $((ret_read_msr_value_lo >> 6 & 1)) -eq 1 ] && cap_pschange_msc_no=1
[ $((ret_read_msr_value_lo >> 7 & 1)) -eq 1 ] && cap_tsx_ctrl_msr=1
[ $((ret_read_msr_value_lo >> 8 & 1)) -eq 1 ] && cap_taa_no=1
[ $((ret_read_msr_value_lo >> 13 & 1)) -eq 1 ] && cap_sbdr_ssdp_no=1
[ $((ret_read_msr_value_lo >> 14 & 1)) -eq 1 ] && cap_fbsdp_no=1
[ $((ret_read_msr_value_lo >> 15 & 1)) -eq 1 ] && cap_psdp_no=1
[ $((ret_read_msr_value_lo >> 17 & 1)) -eq 1 ] && cap_fb_clear=1
[ $((ret_read_msr_value_lo >> 25 & 1)) -eq 1 ] && cap_gds_ctrl=1
[ $((ret_read_msr_value_lo >> 26 & 1)) -eq 1 ] && cap_gds_no=1
[ $((ret_read_msr_value_lo >> 27 & 1)) -eq 1 ] && cap_rfds_no=1
[ $((ret_read_msr_value_lo >> 28 & 1)) -eq 1 ] && cap_rfds_clear=1
[ $((ret_read_msr_value_hi >> 30 & 1)) -eq 1 ] && cap_its_no=1
pr_debug "capabilities says rdcl_no=$cap_rdcl_no ibrs_all=$cap_ibrs_all rsba=$cap_rsba l1dflush_no=$cap_l1dflush_no ssb_no=$cap_ssb_no mds_no=$cap_mds_no taa_no=$cap_taa_no pschange_msc_no=$cap_pschange_msc_no rfds_no=$cap_rfds_no rfds_clear=$cap_rfds_clear its_no=$cap_its_no sbdr_ssdp_no=$cap_sbdr_ssdp_no fbsdp_no=$cap_fbsdp_no psdp_no=$cap_psdp_no fb_clear=$cap_fb_clear"
pr_debug "capabilities says rdcl_no=$cap_rdcl_no ibrs_all=$cap_ibrs_all rsba=$cap_rsba l1dflush_no=$cap_l1dflush_no ssb_no=$cap_ssb_no mds_no=$cap_mds_no taa_no=$cap_taa_no pschange_msc_no=$cap_pschange_msc_no rfds_no=$cap_rfds_no rfds_clear=$cap_rfds_clear its_no=$cap_its_no"
if [ "$cap_ibrs_all" = 1 ]; then
pstatus green YES
else
@@ -1026,8 +911,7 @@ check_cpu() {
elif [ "$cap_tsx_ctrl_rtm_disable" = 0 ]; then
pstatus blue NO
else
# shellcheck disable=SC2154
pstatus yellow UNKNOWN "$ret_read_msr_0x122_msg"
pstatus yellow UNKNOWN "couldn't read MSR"
fi
pr_info_nol " * TSX_CTRL MSR indicates TSX CPUID bit is cleared: "
@@ -1036,8 +920,7 @@ check_cpu() {
elif [ "$cap_tsx_ctrl_cpuid_clear" = 0 ]; then
pstatus blue NO
else
# shellcheck disable=SC2154
pstatus yellow UNKNOWN "$ret_read_msr_0x122_msg"
pstatus yellow UNKNOWN "couldn't read MSR"
fi
fi
@@ -1062,8 +945,7 @@ check_cpu() {
pr_info_nol " * GDS microcode mitigation is disabled (GDS_MITG_DIS): "
if [ "$cap_gds_mitg_dis" = -1 ]; then
# shellcheck disable=SC2154
pstatus yellow UNKNOWN "$ret_read_msr_0x123_msg"
pstatus yellow UNKNOWN "couldn't read MSR"
elif [ "$cap_gds_mitg_dis" = 1 ]; then
pstatus yellow YES
else
@@ -1072,8 +954,7 @@ check_cpu() {
pr_info_nol " * GDS microcode mitigation is locked in enabled state (GDS_MITG_LOCK): "
if [ "$cap_gds_mitg_lock" = -1 ]; then
# shellcheck disable=SC2154
pstatus yellow UNKNOWN "$ret_read_msr_0x123_msg"
pstatus yellow UNKNOWN "couldn't read MSR"
elif [ "$cap_gds_mitg_lock" = 1 ]; then
pstatus blue YES
else
@@ -1090,24 +971,6 @@ check_cpu() {
pstatus yellow NO
fi
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
pstatus yellow UNKNOWN "couldn't read MSR"
elif is_arch_cap_mmio_immune; then
pstatus green YES
else
pstatus yellow NO
fi
pr_info_nol " * CPU microcode supports Fill Buffer clearing (FB_CLEAR): "
if [ "$cap_fb_clear" = -1 ]; then
pstatus yellow UNKNOWN "couldn't read MSR"
elif [ "$cap_fb_clear" = 1 ]; then
pstatus green YES
else
pstatus yellow NO
fi
pr_info_nol " * CPU explicitly indicates not being affected by RFDS (RFDS_NO): "
if [ "$cap_rfds_no" = -1 ]; then
pstatus yellow UNKNOWN "couldn't read MSR"
@@ -1261,8 +1124,7 @@ check_cpu() {
elif [ "$cap_tsx_force_abort_rtm_disable" = 0 ]; then
pstatus blue NO
else
# shellcheck disable=SC2154
pstatus yellow UNKNOWN "$ret_read_msr_0x10f_msg"
pstatus yellow UNKNOWN "couldn't read MSR"
fi
pr_info_nol " * TSX_FORCE_ABORT MSR indicates TSX CPUID bit is cleared: "
@@ -1271,8 +1133,7 @@ check_cpu() {
elif [ "$cap_tsx_force_abort_cpuid_clear" = 0 ]; then
pstatus blue NO
else
# shellcheck disable=SC2154
pstatus yellow UNKNOWN "$ret_read_msr_0x10f_msg"
pstatus yellow UNKNOWN "couldn't read MSR"
fi
fi
@@ -1367,19 +1228,11 @@ check_cpu() {
fi
}
# 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.
# Display per-CVE CPU vulnerability status based on CPU model/family
check_cpu_vulnerabilities() {
local cve
pr_info "* CPU vulnerability to the speculative execution attack variants"
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")): "
if is_cpu_affected "$cve"; then
pstatus yellow YES

View File

@@ -1,63 +1,18 @@
# vim: set ts=4 sw=4 sts=4 et:
check_kernel_info
# Detect arch mismatch between host CPU and target kernel (e.g. x86 host
# inspecting an ARM kernel): force no-hw mode so CPUID/MSR/sysfs reads
# from the host don't pollute the results.
check_kernel_cpu_arch_mismatch
# Build JSON meta and system sections early (after kernel info is resolved)
if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "json" ]; then
_build_json_meta
fi
pr_info
if [ "$g_mode" != no-hw ] && [ -z "$opt_arch_prefix" ]; then
pr_info "\033[1;34mHardware check\033[0m"
if [ "$opt_no_hw" = 0 ] && [ -z "$opt_arch_prefix" ]; then
check_cpu
check_cpu_vulnerabilities
pr_info
fi
# Build JSON system/cpu/microcode sections (after check_cpu has populated cap_* vars and VMM detection)
if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "json" ]; then
_build_json_system
if [ "$g_mode" != no-hw ] && [ -z "$opt_arch_prefix" ]; then
_build_json_cpu
_build_json_cpu_microcode
fi
fi
# Build Prometheus info metric lines (same timing requirement as JSON builders above)
if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "prometheus" ]; then
_build_prometheus_system_info
if [ "$g_mode" != no-hw ] && [ -z "$opt_arch_prefix" ]; then
_build_prometheus_cpu_info
fi
fi
# now run the checks the user asked for (hw-only mode skips CVE checks)
if [ "$g_mode" = hw-only ]; then
pr_info "Hardware-only mode, skipping vulnerability checks"
else
for cve in $g_supported_cve_list; do
# In a default "all CVEs" run, skip checks whose arch tag doesn't match
# the host CPU or the inspected kernel. Explicit --cve/--variant/--errata
# selection bypasses the gate.
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
# now run the checks the user asked for
for cve in $g_supported_cve_list; do
if [ "$opt_cve_all" = 1 ] || echo "$opt_cve_list" | grep -qw "$cve"; then
check_"$(echo "$cve" | tr - _)"
pr_info
done
fi # g_mode != hw-only
fi
done
if [ -n "$g_final_summary" ]; then
pr_info "> \033[46m\033[30mSUMMARY:\033[0m$g_final_summary"
@@ -65,7 +20,7 @@ if [ -n "$g_final_summary" ]; then
fi
if [ "$g_bad_accuracy" = 1 ]; then
pr_warn "We're missing some kernel information (see kernel section at the top), accuracy might be reduced"
pr_warn "We're missing some kernel info (see -v), accuracy might be reduced"
fi
g_vars=$(set | grep -Ev '^[A-Z_[:space:]]' | grep -v -F 'g_mockme=' | sort | tr "\n" '|')
@@ -76,7 +31,7 @@ if [ -n "$g_mockme" ] && [ "$opt_mock" = 1 ]; then
# not a useless use of cat: gzipping cpuinfo directly doesn't work well
# shellcheck disable=SC2002
if command -v "base64" >/dev/null 2>&1; then
g_mock_cpuinfo="$(cat /proc/cpuinfo | gzip -c | base64 | tr -d '\n')"
g_mock_cpuinfo="$(cat /proc/cpuinfo | gzip -c | base64 -w0)"
elif command -v "uuencode" >/dev/null 2>&1; then
g_mock_cpuinfo="$(cat /proc/cpuinfo | gzip -c | uuencode -m - | grep -Fv 'begin-base64' | grep -Fxv -- '====' | tr -d "\n")"
fi
@@ -110,121 +65,25 @@ if [ "$g_mocked" = 1 ]; then
fi
if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "nrpe" ]; then
_nrpe_is_root=0
[ "$(id -u)" -eq 0 ] && _nrpe_is_root=1
# Non-root + VULN: demote to UNKNOWN, MSR reads were skipped so VULN findings
# may be false positives or genuine mitigations may have gone undetected
_nrpe_demoted=0
[ "$g_nrpe_vuln_count" -gt 0 ] && [ "$_nrpe_is_root" = 0 ] && _nrpe_demoted=1
# Determine status word and build the one-line summary
if [ "$_nrpe_demoted" = 1 ]; then
_nrpe_status_word='UNKNOWN'
_nrpe_summary="${g_nrpe_vuln_count}/${g_nrpe_total} CVE(s) appear vulnerable (unconfirmed, not root): ${g_nrpe_vuln_ids}"
[ "$g_nrpe_unk_count" -gt 0 ] && _nrpe_summary="${_nrpe_summary}, ${g_nrpe_unk_count} inconclusive"
elif [ "$g_nrpe_vuln_count" -gt 0 ]; then
_nrpe_status_word='CRITICAL'
_nrpe_summary="${g_nrpe_vuln_count}/${g_nrpe_total} CVE(s) vulnerable: ${g_nrpe_vuln_ids}"
[ "$g_nrpe_unk_count" -gt 0 ] && _nrpe_summary="${_nrpe_summary}, ${g_nrpe_unk_count} inconclusive"
elif [ "$g_nrpe_unk_count" -gt 0 ]; then
_nrpe_status_word='UNKNOWN'
_nrpe_summary="${g_nrpe_unk_count}/${g_nrpe_total} CVE checks inconclusive"
if [ -n "$g_nrpe_vuln" ]; then
echo "Vulnerable:$g_nrpe_vuln"
else
_nrpe_status_word='OK'
_nrpe_summary="All ${g_nrpe_total} CVE checks passed"
echo "OK"
fi
# Line 1: status word + summary + performance data (Nagios plugin spec)
echo "${_nrpe_status_word}: ${_nrpe_summary} | checked=${g_nrpe_total} vulnerable=${g_nrpe_vuln_count} unknown=${g_nrpe_unk_count}"
# Long output (lines 2+): context notes, then per-CVE details
[ "$opt_paranoid" = 1 ] && echo "NOTE: paranoid mode active, stricter mitigation requirements applied"
case "${g_has_vmm:-}" in
1) echo "NOTE: hypervisor host detected (${g_has_vmm_reason:-VMM}); L1TF/MDS severity is elevated" ;;
0) echo "NOTE: not a hypervisor host" ;;
esac
[ "$_nrpe_is_root" = 0 ] && echo "NOTE: not running as root; MSR reads skipped, results may be incomplete"
# VULN details first, then UNK details (each group in CVE-registry order)
[ -n "${g_nrpe_vuln_details:-}" ] && printf "%b\n" "$g_nrpe_vuln_details"
[ -n "${g_nrpe_unk_details:-}" ] && printf "%b\n" "$g_nrpe_unk_details"
# Exit with the correct Nagios code when we demoted VULN→UNKNOWN due to non-root
# (g_critical=1 would otherwise cause exit 2 below)
[ "$_nrpe_demoted" = 1 ] && exit 3
fi
if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "short" ]; then
_pr_echo 0 "${g_short_output% }"
fi
if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "json-terse" ]; then
if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "json" ]; then
_pr_echo 0 "${g_json_output%?}]"
fi
if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "json" ]; then
# Assemble the comprehensive JSON output from pre-built sections
# Inject mocked flag into meta (g_mocked can be set at any point during the run)
g_json_meta="${g_json_meta%\}},\"mocked\":$(_json_bool "${g_mocked:-0}")}"
_json_final='{'
_json_final="${_json_final}\"meta\":${g_json_meta:-null}"
_json_final="${_json_final},\"system\":${g_json_system:-null}"
_json_final="${_json_final},\"cpu\":${g_json_cpu:-null}"
_json_final="${_json_final},\"cpu_microcode\":${g_json_cpu_microcode:-null}"
if [ -n "${g_json_vulns:-}" ]; then
_json_final="${_json_final},\"vulnerabilities\":[${g_json_vulns%,}]"
else
_json_final="${_json_final},\"vulnerabilities\":[]"
fi
_json_final="${_json_final}}"
_pr_echo 0 "$_json_final"
fi
if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "prometheus" ]; then
prom_run_as_root='false'
[ "$(id -u)" -eq 0 ] && prom_run_as_root='true'
prom_mode="$g_mode"
prom_paranoid='false'
[ "$opt_paranoid" = 1 ] && prom_paranoid='true'
prom_sysfs_only='false'
[ "$opt_sysfs_only" = 1 ] && prom_sysfs_only='true'
prom_reduced_accuracy='false'
[ "${g_bad_accuracy:-0}" = 1 ] && prom_reduced_accuracy='true'
prom_mocked='false'
[ "${g_mocked:-0}" = 1 ] && prom_mocked='true'
echo "# HELP smc_build_info spectre-meltdown-checker script metadata (always 1)"
echo "# TYPE smc_build_info gauge"
printf 'smc_build_info{version="%s",mode="%s",run_as_root="%s",paranoid="%s",sysfs_only="%s",reduced_accuracy="%s",mocked="%s"} 1\n' \
"$(_prom_escape "$VERSION")" \
"$prom_mode" \
"$prom_run_as_root" \
"$prom_paranoid" \
"$prom_sysfs_only" \
"$prom_reduced_accuracy" \
"$prom_mocked"
if [ -n "${g_smc_system_info_line:-}" ]; then
echo "# HELP smc_system_info Operating system and kernel metadata (always 1)"
echo "# TYPE smc_system_info gauge"
echo "$g_smc_system_info_line"
fi
if [ -n "${g_smc_cpu_info_line:-}" ]; then
echo "# HELP smc_cpu_info CPU hardware and microcode metadata (always 1)"
echo "# TYPE smc_cpu_info gauge"
echo "$g_smc_cpu_info_line"
fi
echo "# HELP smc_vulnerability_status Vulnerability check result per CVE: 0=not_vulnerable, 1=vulnerable, 2=unknown"
echo "# TYPE smc_vulnerability_status gauge"
printf "%b\n" "$g_smc_vuln_output"
echo "# HELP smc_vulnerable_count Number of CVEs with vulnerable status"
echo "# TYPE smc_vulnerable_count gauge"
echo "smc_vulnerable_count $g_smc_vuln_count"
echo "# HELP smc_unknown_count Number of CVEs with unknown status"
echo "# TYPE smc_unknown_count gauge"
echo "smc_unknown_count $g_smc_unk_count"
echo "# HELP smc_last_scan_timestamp_seconds Unix timestamp when this scan completed"
echo "# TYPE smc_last_scan_timestamp_seconds gauge"
echo "smc_last_scan_timestamp_seconds $(date +%s 2>/dev/null || echo 0)"
echo "# TYPE specex_vuln_status untyped"
echo "# HELP specex_vuln_status Exposure of system to speculative execution vulnerabilities"
printf "%b\n" "$g_prometheus_output"
fi
# exit with the proper exit code

View File

@@ -3,7 +3,7 @@
check_mds_bsd() {
local kernel_md_clear kernel_smt_allowed kernel_mds_enabled kernel_mds_state
pr_info_nol "* Kernel supports using MD_CLEAR mitigation: "
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
if sysctl hw.mds_disable >/dev/null 2>&1; then
pstatus green YES
kernel_md_clear=1
@@ -76,7 +76,7 @@ check_mds_bsd() {
else
if [ "$cap_md_clear" = 1 ]; then
if [ "$kernel_md_clear" = 1 ]; then
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
# mitigation must also be enabled
if [ "$kernel_mds_enabled" -ge 1 ]; then
if [ "$opt_paranoid" != 1 ] || [ "$kernel_smt_allowed" = 0 ]; then
@@ -95,7 +95,7 @@ check_mds_bsd() {
pvulnstatus "$cve" VULN "Your microcode supports mitigation, but your kernel doesn't, upgrade it to mitigate the vulnerability"
fi
else
if [ "$kernel_md_clear" = 1 ] && [ "$g_mode" = live ]; then
if [ "$kernel_md_clear" = 1 ] && [ "$opt_live" = 1 ]; then
# no MD_CLEAR in microcode, but FreeBSD may still have software-only mitigation active
case "$kernel_mds_state" in
software*)
@@ -132,54 +132,50 @@ check_mds_linux() {
fi
if [ "$opt_sysfs_only" != 1 ]; then
# MDS is Intel-only; skip x86-specific kernel/cpuinfo checks on non-x86 kernels
pr_info_nol "* Kernel supports using MD_CLEAR mitigation: "
kernel_md_clear=''
kernel_md_clear_can_tell=0
if is_x86_kernel; then
pr_info_nol "* Kernel supports using MD_CLEAR mitigation: "
kernel_md_clear_can_tell=1
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_can_tell=1
if [ "$opt_live" = 1 ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw md_clear; then
kernel_md_clear="md_clear found in $g_procfs/cpuinfo"
pstatus green YES "$kernel_md_clear"
fi
if [ -z "$kernel_md_clear" ]; then
if ! command -v "${opt_arch_prefix}strings" >/dev/null 2>&1; then
kernel_md_clear_can_tell=0
elif [ -n "$g_kernel_err" ]; then
kernel_md_clear_can_tell=0
elif "${opt_arch_prefix}strings" "$g_kernel" | grep -q 'Clear CPU buffers'; then
pr_debug "md_clear: found 'Clear CPU buffers' string in kernel image"
kernel_md_clear='found md_clear implementation evidence in kernel image'
pstatus green YES "$kernel_md_clear"
fi
if [ -z "$kernel_md_clear" ]; then
if ! command -v "${opt_arch_prefix}strings" >/dev/null 2>&1; then
kernel_md_clear_can_tell=0
elif [ -n "$g_kernel_err" ]; then
kernel_md_clear_can_tell=0
elif "${opt_arch_prefix}strings" "$g_kernel" | grep -q 'Clear CPU buffers'; then
pr_debug "md_clear: found 'Clear CPU buffers' string in kernel image"
kernel_md_clear='found md_clear implementation evidence in kernel image'
pstatus green YES "$kernel_md_clear"
fi
fi
if [ -z "$kernel_md_clear" ]; then
if [ "$kernel_md_clear_can_tell" = 1 ]; then
pstatus yellow NO
else
pstatus yellow UNKNOWN
fi
fi
if [ -z "$kernel_md_clear" ]; then
if [ "$kernel_md_clear_can_tell" = 1 ]; then
pstatus yellow NO
else
pstatus yellow UNKNOWN
fi
fi
if [ "$g_mode" = live ] && [ "$sys_interface_available" = 1 ]; then
pr_info_nol "* Kernel mitigation is enabled and active: "
if echo "$ret_sys_interface_check_fullmsg" | grep -qi ^mitigation; then
mds_mitigated=1
pstatus green YES
else
mds_mitigated=0
pstatus yellow NO
fi
pr_info_nol "* SMT is either mitigated or disabled: "
if echo "$ret_sys_interface_check_fullmsg" | grep -Eq 'SMT (disabled|mitigated)'; then
mds_smt_mitigated=1
pstatus green YES
else
mds_smt_mitigated=0
pstatus yellow NO
fi
if [ "$opt_live" = 1 ] && [ "$sys_interface_available" = 1 ]; then
pr_info_nol "* Kernel mitigation is enabled and active: "
if echo "$ret_sys_interface_check_fullmsg" | grep -qi ^mitigation; then
mds_mitigated=1
pstatus green YES
else
mds_mitigated=0
pstatus yellow NO
fi
fi # is_x86_kernel
pr_info_nol "* SMT is either mitigated or disabled: "
if echo "$ret_sys_interface_check_fullmsg" | grep -Eq 'SMT (disabled|mitigated)'; then
mds_smt_mitigated=1
pstatus green YES
else
mds_smt_mitigated=0
pstatus yellow NO
fi
fi
elif [ "$sys_interface_available" = 0 ]; then
# we have no sysfs but were asked to use it only!
msg="/sys vulnerability interface use forced, but it's not available!"
@@ -194,7 +190,7 @@ check_mds_linux() {
# compute mystatus and mymsg from our own logic
if [ "$cap_md_clear" = 1 ]; then
if [ -n "$kernel_md_clear" ]; then
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
# mitigation must also be enabled
if [ "$mds_mitigated" = 1 ]; then
if [ "$opt_paranoid" != 1 ] || [ "$mds_smt_mitigated" = 1 ]; then

View File

@@ -1,305 +0,0 @@
# vim: set ts=4 sw=4 sts=4 et:
# MMIO Stale Data (Processor MMIO Stale Data Vulnerabilities) - BSD mitigation check
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
unk="your CPU's MMIO Stale Data status is unknown (Intel never officially assessed this CPU, its servicing period has ended)"
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif is_cpu_mmio_unknown; then
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
else
pvulnstatus "$cve" VULN "your CPU is affected and no BSD has implemented an MMIO Stale Data mitigation"
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
}
# MMIO Stale Data (Processor MMIO Stale Data Vulnerabilities) - Linux mitigation check
check_mmio_linux() {
local status sys_interface_available msg kernel_mmio kernel_mmio_can_tell mmio_mitigated mmio_smt_mitigated mystatus mymsg unk
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "$VULN_SYSFS_BASE/mmio_stale_data" '^[^;]+'; then
# Kernel source inventory for MMIO Stale Data, traced via git blame walkback
# across /shared/linux, /shared/linux-stable, and /shared/linux-centos-redhat:
#
# --- sysfs messages ---
# all versions:
# "Not affected" (cpu_show_common, generic)
#
# 8cb861e9e3c9 (v5.19, initial MMIO mitigation, Pawan Gupta 2022-05-19):
# enum mmio_mitigations: MMIO_MITIGATION_OFF, MMIO_MITIGATION_UCODE_NEEDED, MMIO_MITIGATION_VERW
# mmio_strings[]:
# "Vulnerable" (MMIO_MITIGATION_OFF)
# "Vulnerable: Clear CPU buffers attempted, no microcode" (MMIO_MITIGATION_UCODE_NEEDED)
# "Mitigation: Clear CPU buffers" (MMIO_MITIGATION_VERW)
#
# 8d50cdf8b834 (v5.19, sysfs reporting, Pawan Gupta 2022-05-19):
# mmio_stale_data_show_state() added with SMT suffix:
# "{mmio_strings[state]}; SMT vulnerable" (sched_smt_active() true)
# "{mmio_strings[state]}; SMT disabled" (sched_smt_active() false)
# "{mmio_strings[state]}; SMT Host state unknown" (boot_cpu_has(HYPERVISOR))
# No SMT suffix when MMIO_MITIGATION_OFF.
# Uses sysfs_emit() in mainline. CentOS 7 backport uses sprintf().
#
# 7df548840c49 (v6.0, "unknown" reporting, Pawan Gupta 2022-08-03):
# Added X86_BUG_MMIO_UNKNOWN handling:
# "Unknown: No mitigations" (X86_BUG_MMIO_UNKNOWN set)
# Present in: v6.0 through v6.15, stable 5.10.y/5.15.y/6.1.y/6.6.y, rocky8, rocky9
#
# dd86a1d013e0 (v6.16, removed MMIO_UNKNOWN, Borislav Petkov 2025-04-14):
# Removed X86_BUG_MMIO_UNKNOWN -- "Unknown" message no longer produced.
# Replaced by general X86_BUG_OLD_MICROCODE mechanism.
#
# 4a5a04e61d7f (v6.16, restructured, David Kaplan 2025-04-18):
# Split into select/update/apply pattern. Same strings, same output.
#
# all messages start with "Not affected", "Vulnerable", "Mitigation", or "Unknown"
#
# --- stable backports ---
# Stable branches 5.4.y through 6.15.y: identical mmio_strings[] array.
# 5.4.y uses sprintf(); 5.10.y+ uses sysfs_emit().
# v6.0.y through v6.15.y include "Unknown: No mitigations" branch.
# v6.16.y+: restructured, no "Unknown" message.
#
# --- RHEL/CentOS ---
# centos7: sprintf() instead of sysfs_emit(), otherwise identical strings.
# rocky8: sysfs_emit(), includes X86_BUG_MMIO_UNKNOWN.
# rocky9: sysfs_emit(), includes X86_BUG_MMIO_UNKNOWN.
# rocky10: restructured, matches mainline v6.16+.
# All RHEL branches use identical mmio_strings[] array.
#
# --- Kconfig symbols ---
# No Kconfig symbol: v5.19 through v6.11 (mitigation always compiled in when CPU_SUP_INTEL)
# 163f9fe6b625 (v6.12, Breno Leitao 2024-07-29): CONFIG_MITIGATION_MMIO_STALE_DATA (bool, default y, depends CPU_SUP_INTEL)
# No other name variants exist (no renames). Single symbol throughout history.
#
# --- stable ---
# Only linux-rolling-lts and linux-rolling-stable have the Kconfig symbol.
# Stable branches 5.x through 6.11.y: no Kconfig (always compiled in).
#
# --- RHEL ---
# rocky9, rocky10: CONFIG_MITIGATION_MMIO_STALE_DATA present.
# rocky8, centos7: no Kconfig symbol.
#
# --- kernel functions (for $opt_map / System.map) ---
# 8cb861e9e3c9 (v5.19): mmio_select_mitigation() [static __init]
# 8cb861e9e3c9 (v5.19): mmio_stale_data_parse_cmdline() [static __init]
# 8d50cdf8b834 (v5.19): mmio_stale_data_show_state() [static]
# 8d50cdf8b834 (v5.19): cpu_show_mmio_stale_data() [global, non-static -- visible in System.map]
# 4a5a04e61d7f (v6.16): + mmio_update_mitigation() [static __init]
# 4a5a04e61d7f (v6.16): + mmio_apply_mitigation() [static __init]
#
# Best grep targets for $opt_map: mmio_select_mitigation, cpu_show_mmio_stale_data
# Best grep targets for $g_kernel: mmio_stale_data (appears in sysfs strings and parameter name)
#
# --- stable ---
# 5.4.y-6.15.y: mmio_select_mitigation, mmio_stale_data_parse_cmdline, mmio_stale_data_show_state
# 6.16.y+: + mmio_update_mitigation, mmio_apply_mitigation
#
# --- RHEL ---
# rocky8/rocky9: mmio_select_mitigation, mmio_stale_data_parse_cmdline, mmio_stale_data_show_state
# rocky10: + mmio_update_mitigation, mmio_apply_mitigation
#
# --- CPU affection logic (for is_cpu_affected) ---
# 51802186158c (v5.19, initial model list, Pawan Gupta 2022-05-19):
# Intel Family 6:
# 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)
# All steppings. No stepping restrictions for MMIO flag itself.
#
# 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)
# All three must be set. Checked via arch_cap_mmio_immune() in common.c.
#
# 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).
#
# vendor scope: Intel only. Non-Intel CPUs never set X86_BUG_MMIO_STALE_DATA.
sys_interface_available=1
status=$ret_sys_interface_check_status
fi
if [ "$opt_sysfs_only" != 1 ]; then
# MMIO Stale Data is Intel-only; skip x86-specific kernel/MSR checks on non-x86 kernels
kernel_mmio=''
kernel_mmio_can_tell=0
if is_x86_kernel; then
pr_info_nol "* Kernel supports MMIO Stale Data mitigation: "
kernel_mmio_can_tell=1
if [ -n "$g_kernel_err" ]; then
kernel_mmio_can_tell=0
elif grep -q 'mmio_stale_data' "$g_kernel" 2>/dev/null; then
pr_debug "mmio: found 'mmio_stale_data' string in kernel image"
kernel_mmio='found MMIO Stale Data mitigation evidence in kernel image'
pstatus green YES "$kernel_mmio"
fi
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'
pstatus green YES "$kernel_mmio"
fi
if [ -z "$kernel_mmio" ] && [ -n "$opt_map" ]; then
if grep -qE 'mmio_select_mitigation|cpu_show_mmio_stale_data' "$opt_map"; then
kernel_mmio='found MMIO Stale Data mitigation function in System.map'
pstatus green YES "$kernel_mmio"
fi
fi
if [ -z "$kernel_mmio" ]; then
if [ "$kernel_mmio_can_tell" = 1 ]; then
pstatus yellow NO
else
pstatus yellow UNKNOWN
fi
fi
pr_info_nol "* CPU microcode supports Fill Buffer clearing: "
if [ "$cap_fb_clear" = -1 ]; then
pstatus yellow UNKNOWN
elif [ "$cap_fb_clear" = 1 ]; then
pstatus green YES
else
pstatus yellow NO
fi
if [ "$g_mode" = live ] && [ "$sys_interface_available" = 1 ]; then
pr_info_nol "* Kernel mitigation is enabled and active: "
if echo "$ret_sys_interface_check_fullmsg" | grep -qi ^mitigation; then
mmio_mitigated=1
pstatus green YES
else
mmio_mitigated=0
pstatus yellow NO
fi
pr_info_nol "* SMT is either mitigated or disabled: "
if echo "$ret_sys_interface_check_fullmsg" | grep -Eq 'SMT (disabled|mitigated)'; then
mmio_smt_mitigated=1
pstatus green YES
else
mmio_smt_mitigated=0
pstatus yellow NO
fi
fi
fi # is_x86_kernel
elif [ "$sys_interface_available" = 0 ]; then
# we have no sysfs but were asked to use it only!
msg="/sys vulnerability interface use forced, but it's not available!"
status=UNK
fi
if ! is_cpu_affected "$cve"; then
# override status & msg in case CPU is not vulnerable after all
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).
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. Consider replacing affected hardware."
else
pvulnstatus "$cve" UNK "$unk; no mitigation is available in any case"
fi
else
if [ "$opt_sysfs_only" != 1 ]; then
# compute mystatus and mymsg from our own logic
if [ "$cap_fb_clear" = 1 ]; then
if [ -n "$kernel_mmio" ]; then
if [ "$g_mode" = live ]; then
# mitigation must also be enabled
if [ "$mmio_mitigated" = 1 ]; then
if [ "$opt_paranoid" != 1 ] || [ "$mmio_smt_mitigated" = 1 ]; then
mystatus=OK
mymsg="Your microcode and kernel are both up to date for this mitigation, and mitigation is enabled"
else
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"
fi
else
mystatus=VULN
mymsg="Your microcode and kernel are both up to date for this mitigation, but the mitigation is not active"
fi
else
mystatus=OK
mymsg="Your microcode and kernel are both up to date for this mitigation"
fi
else
mystatus=VULN
mymsg="Your microcode supports mitigation, but your kernel doesn't, upgrade it to mitigate the vulnerability"
fi
else
if [ -n "$kernel_mmio" ]; then
mystatus=VULN
mymsg="Your kernel supports mitigation, but your CPU microcode also needs to be updated to mitigate the vulnerability"
else
mystatus=VULN
mymsg="Neither your kernel or your microcode support mitigation, upgrade both to mitigate the vulnerability"
fi
fi
else
# sysfs only: return the status/msg we got
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
return
fi
# if we didn't get a msg+status from sysfs, use ours
if [ -z "$msg" ]; then
pvulnstatus "$cve" "$mystatus" "$mymsg"
elif [ "$opt_paranoid" = 1 ]; then
# if paranoid mode is enabled, we know that we won't agree on status, so take ours
pvulnstatus "$cve" "$mystatus" "$mymsg"
elif [ "$status" = "$mystatus" ]; then
# if we agree on status, we'll print the common status and our message (more detailed than the sysfs one)
pvulnstatus "$cve" "$status" "$mymsg"
else
# if we don't agree on status, maybe our logic is flawed due to a new kernel/mitigation? use the one from sysfs
pvulnstatus "$cve" "$status" "$msg"
fi
if [ "$mystatus" = VULN ]; then
explain "Update your kernel to a version that includes MMIO Stale Data mitigation (Linux 5.19+), and update your CPU microcode. If you are using a distribution kernel, make sure you are up to date. To enforce full mitigation including SMT, boot with 'mmio_stale_data=full,nosmt'."
fi
fi
}

View File

@@ -1,6 +1,6 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# Straight-Line Speculation (SLS) supplementary check (--extra only)
# Straight-Line Speculation (SLS) supplementary check (--extra only)
#
# SLS: x86 CPUs may speculatively execute instructions past unconditional
# control flow changes (RET, indirect JMP/CALL). Mitigated at compile time
@@ -173,8 +173,10 @@ check_CVE_0000_0001_linux() {
return
fi
# --- ARM: no kernel mitigation available ---
if is_arm_kernel; then
# --- arm64: no kernel mitigation available ---
local _sls_arch
_sls_arch=$(uname -m 2>/dev/null || echo unknown)
if echo "$_sls_arch" | grep -qw 'aarch64'; then
pvulnstatus "$cve" VULN "no kernel mitigation available for arm64 SLS (CVE-2020-13844)"
explain "Your ARM processor is affected by Straight-Line Speculation (CVE-2020-13844).\n" \
"GCC and Clang support -mharden-sls=all for aarch64, which inserts SB (Speculation Barrier)\n" \
@@ -184,12 +186,7 @@ check_CVE_0000_0001_linux() {
return
fi
# --- x86: config check and binary heuristic ---
if ! is_x86_kernel; then
pvulnstatus "$cve" UNK "SLS mitigation detection not supported for this kernel architecture"
return
fi
# --- method 1: kernel config check (x86_64) ---
local _sls_config=''
if [ -n "$opt_config" ] && [ -r "$opt_config" ]; then
pr_info_nol " * Kernel compiled with SLS mitigation: "
@@ -261,6 +258,9 @@ check_CVE_0000_0001_linux() {
# --- verdict (x86_64) ---
if [ "$_sls_config" = 1 ] || [ "$_sls_heuristic" = 1 ]; then
pvulnstatus "$cve" OK "kernel compiled with SLS mitigation"
explain "Your kernel was compiled with CONFIG_MITIGATION_SLS=y (or CONFIG_SLS=y on kernels before 6.8),\n" \
"which enables the GCC flag -mharden-sls=all to insert INT3 instructions after unconditional\n" \
"control flow changes, blocking straight-line speculation."
elif [ "$_sls_config" = 0 ] || [ "$_sls_heuristic" = 0 ]; then
pvulnstatus "$cve" VULN "kernel not compiled with SLS mitigation"
explain "Recompile your kernel with CONFIG_MITIGATION_SLS=y (or CONFIG_SLS=y on kernels before 6.8).\n" \

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
}

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
}

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
}

File diff suppressed because it is too large Load Diff

View File

@@ -57,12 +57,12 @@ check_CVE_2017_5753_linux() {
status=$ret_sys_interface_check_status
fi
if [ "$opt_sysfs_only" != 1 ]; then
# no /sys interface (or no-runtime mode), fallback to our own ways
# no /sys interface (or offline mode), fallback to our own ways
# Primary detection: grep for sysfs mitigation strings in the kernel binary.
# The string "__user pointer sanitization" is present in all kernel versions
# that have spectre_v1 sysfs support (x86 v4.16+, ARM64 v5.2+, ARM32 v5.17+),
# including RHEL "Load fences" variants. This is cheap and works in no-runtime mode.
# including RHEL "Load fences" variants. This is cheap and works offline.
pr_info_nol "* Kernel has spectre_v1 mitigation (kernel image): "
v1_kernel_mitigated=''
v1_kernel_mitigated_err=''
@@ -98,51 +98,63 @@ check_CVE_2017_5753_linux() {
# Fallback for v4.15-era kernels: binary pattern matching for array_index_mask_nospec().
# The sysfs mitigation strings were not present in the kernel image until v4.16 (x86)
# and v5.2 (ARM64), but the actual mitigation code landed in v4.15 (x86) and v4.16 (ARM64).
# For no-runtime analysis of these old kernels, match the specific instruction patterns.
# For offline analysis of these old kernels, match the specific instruction patterns.
if [ -z "$v1_kernel_mitigated" ]; then
pr_info_nol "* Kernel has array_index_mask_nospec (v4.15 binary pattern): "
# vanilla: look for the Linus' mask aka array_index_mask_nospec()
# that is inlined at least in raw_copy_from_user (__get_user_X symbols)
#mov PER_CPU_VAR(current_task), %_ASM_DX
#cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
#jae bad_get_user
# /* array_index_mask_nospec() are the 2 opcodes that follow */
#+sbb %_ASM_DX, %_ASM_DX
#+and %_ASM_DX, %_ASM_AX
#ASM_STAC
# x86 64bits: jae(0x0f 0x83 0x?? 0x?? 0x?? 0x??) sbb(0x48 0x19 0xd2) and(0x48 0x21 0xd0)
# x86 32bits: cmp(0x3b 0x82 0x?? 0x?? 0x00 0x00) jae(0x73 0x??) sbb(0x19 0xd2) and(0x21 0xd0)
#
# arm32
##ifdef CONFIG_THUMB2_KERNEL
##define CSDB ".inst.w 0xf3af8014"
##else
##define CSDB ".inst 0xe320f014" e320f014
##endif
#asm volatile(
# "cmp %1, %2\n" e1500003
#" sbc %0, %1, %1\n" e0c03000
#CSDB
#: "=r" (mask)
#: "r" (idx), "Ir" (sz)
#: "cc");
#
# http://git.arm.linux.org.uk/cgit/linux-arm.git/commit/?h=spectre&id=a78d156587931a2c3b354534aa772febf6c9e855
v1_mask_nospec=''
if [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)"
elif is_x86_kernel; then
# x86: binary pattern matching for array_index_mask_nospec()
# x86 64bits: jae(0x0f 0x83 ....) sbb(0x48 0x19 0xd2) and(0x48 0x21 0xd0)
# x86 32bits: cmp(0x3b 0x82 .. .. 0x00 0x00) jae(0x73 ..) sbb(0x19 0xd2) and(0x21 0xd0)
if ! command -v perl >/dev/null 2>&1; then
pstatus yellow UNKNOWN "missing 'perl' binary, please install it"
elif ! command -v perl >/dev/null 2>&1; then
pstatus yellow UNKNOWN "missing 'perl' binary, please install it"
else
perl -ne '/\x0f\x83....\x48\x19\xd2\x48\x21\xd0/ and $found++; END { exit($found ? 0 : 1) }' "$g_kernel"
ret=$?
if [ "$ret" -eq 0 ]; then
pstatus green YES "x86 64 bits array_index_mask_nospec()"
v1_mask_nospec="x86 64 bits array_index_mask_nospec"
else
perl -ne '/\x0f\x83....\x48\x19\xd2\x48\x21\xd0/ and $found++; END { exit($found ? 0 : 1) }' "$g_kernel"
perl -ne '/\x3b\x82..\x00\x00\x73.\x19\xd2\x21\xd0/ and $found++; END { exit($found ? 0 : 1) }' "$g_kernel"
ret=$?
if [ "$ret" -eq 0 ]; then
pstatus green YES "x86 64 bits array_index_mask_nospec()"
v1_mask_nospec="x86 64 bits array_index_mask_nospec"
pstatus green YES "x86 32 bits array_index_mask_nospec()"
v1_mask_nospec="x86 32 bits array_index_mask_nospec"
else
perl -ne '/\x3b\x82..\x00\x00\x73.\x19\xd2\x21\xd0/ and $found++; END { exit($found ? 0 : 1) }' "$g_kernel"
ret=$?
if [ "$ret" -eq 0 ]; then
pstatus green YES "x86 32 bits array_index_mask_nospec()"
v1_mask_nospec="x86 32 bits array_index_mask_nospec"
ret=$("${opt_arch_prefix}objdump" "$g_objdump_options" "$g_kernel" | grep -w -e f3af8014 -e e320f014 -B2 | grep -B1 -w sbc | grep -w -c cmp)
if [ "$ret" -gt 0 ]; then
pstatus green YES "$ret occurrence(s) found of arm 32 bits array_index_mask_nospec()"
v1_mask_nospec="arm 32 bits array_index_mask_nospec"
else
pstatus yellow NO
fi
fi
fi
elif is_arm_kernel; then
# arm32: match CSDB instruction (0xf3af8014 Thumb2 or 0xe320f014 ARM) preceded by sbc+cmp
# http://git.arm.linux.org.uk/cgit/linux-arm.git/commit/?h=spectre&id=a78d156587931a2c3b354534aa772febf6c9e855
if ! command -v "${opt_arch_prefix}objdump" >/dev/null 2>&1; then
pstatus yellow UNKNOWN "missing '${opt_arch_prefix}objdump' tool, please install it, usually it's in the binutils package"
else
ret=$("${opt_arch_prefix}objdump" "$g_objdump_options" "$g_kernel" | grep -w -e f3af8014 -e e320f014 -B2 | grep -B1 -w sbc | grep -w -c cmp)
if [ "$ret" -gt 0 ]; then
pstatus green YES "$ret occurrence(s) found of arm 32 bits array_index_mask_nospec()"
v1_mask_nospec="arm 32 bits array_index_mask_nospec"
else
pstatus yellow NO
fi
fi
else
pstatus yellow NO
fi
fi
@@ -160,69 +172,67 @@ check_CVE_2017_5753_linux() {
pstatus yellow NO
fi
if is_arm_kernel; then
pr_info_nol "* Kernel has mask_nospec64 (arm64): "
#.macro mask_nospec64, idx, limit, tmp
#sub \tmp, \idx, \limit
#bic \tmp, \tmp, \idx
#and \idx, \idx, \tmp, asr #63
#csdb
#.endm
#$ aarch64-linux-gnu-objdump -d vmlinux | grep -w bic -A1 -B1 | grep -w sub -A2 | grep -w and -B2
#ffffff8008082e44: cb190353 sub x19, x26, x25
#ffffff8008082e48: 8a3a0273 bic x19, x19, x26
#ffffff8008082e4c: 8a93ff5a and x26, x26, x19, asr #63
#ffffff8008082e50: d503229f hint #0x14
# /!\ can also just be "csdb" instead of "hint #0x14" for native objdump
#
# if we already have a detection, don't bother disassembling the kernel, the answer is no.
if [ -n "$v1_kernel_mitigated" ] || [ -n "$v1_mask_nospec" ] || [ "$g_redhat_canonical_spectre" -gt 0 ]; then
pstatus yellow NO
elif [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)"
elif ! command -v perl >/dev/null 2>&1; then
pstatus yellow UNKNOWN "missing 'perl' binary, please install it"
elif ! command -v "${opt_arch_prefix}objdump" >/dev/null 2>&1; then
pstatus yellow UNKNOWN "missing '${opt_arch_prefix}objdump' tool, please install it, usually it's in the binutils package"
pr_info_nol "* Kernel has mask_nospec64 (arm64): "
#.macro mask_nospec64, idx, limit, tmp
#sub \tmp, \idx, \limit
#bic \tmp, \tmp, \idx
#and \idx, \idx, \tmp, asr #63
#csdb
#.endm
#$ aarch64-linux-gnu-objdump -d vmlinux | grep -w bic -A1 -B1 | grep -w sub -A2 | grep -w and -B2
#ffffff8008082e44: cb190353 sub x19, x26, x25
#ffffff8008082e48: 8a3a0273 bic x19, x19, x26
#ffffff8008082e4c: 8a93ff5a and x26, x26, x19, asr #63
#ffffff8008082e50: d503229f hint #0x14
# /!\ can also just be "csdb" instead of "hint #0x14" for native objdump
#
# if we already have a detection, don't bother disassembling the kernel, the answer is no.
if [ -n "$v1_kernel_mitigated" ] || [ -n "$v1_mask_nospec" ] || [ "$g_redhat_canonical_spectre" -gt 0 ]; then
pstatus yellow NO
elif [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)"
elif ! command -v perl >/dev/null 2>&1; then
pstatus yellow UNKNOWN "missing 'perl' binary, please install it"
elif ! command -v "${opt_arch_prefix}objdump" >/dev/null 2>&1; then
pstatus yellow UNKNOWN "missing '${opt_arch_prefix}objdump' tool, please install it, usually it's in the binutils package"
else
"${opt_arch_prefix}objdump" "$g_objdump_options" "$g_kernel" | perl -ne 'push @r, $_; /\s(hint|csdb)\s/ && $r[0]=~/\ssub\s+(x\d+)/ && $r[1]=~/\sbic\s+$1,\s+$1,/ && $r[2]=~/\sand\s/ && exit(9); shift @r if @r>3'
ret=$?
if [ "$ret" -eq 9 ]; then
pstatus green YES "mask_nospec64 macro is present and used"
v1_mask_nospec="arm64 mask_nospec64"
else
"${opt_arch_prefix}objdump" "$g_objdump_options" "$g_kernel" | perl -ne 'push @r, $_; /\s(hint|csdb)\s/ && $r[0]=~/\ssub\s+(x\d+)/ && $r[1]=~/\sbic\s+$1,\s+$1,/ && $r[2]=~/\sand\s/ && exit(9); shift @r if @r>3'
ret=$?
if [ "$ret" -eq 9 ]; then
pstatus green YES "mask_nospec64 macro is present and used"
v1_mask_nospec="arm64 mask_nospec64"
else
pstatus yellow NO
fi
pstatus yellow NO
fi
fi
pr_info_nol "* Kernel has array_index_nospec (arm64): "
# in 4.19+ kernels, the mask_nospec64 asm64 macro is replaced by array_index_nospec, defined in nospec.h, and used in invoke_syscall()
# ffffff8008090a4c: 2a0203e2 mov w2, w2
# ffffff8008090a50: eb0200bf cmp x5, x2
# ffffff8008090a54: da1f03e2 ngc x2, xzr
# ffffff8008090a58: d503229f hint #0x14
# /!\ can also just be "csdb" instead of "hint #0x14" for native objdump
#
# if we already have a detection, don't bother disassembling the kernel, the answer is no.
if [ -n "$v1_kernel_mitigated" ] || [ -n "$v1_mask_nospec" ] || [ "$g_redhat_canonical_spectre" -gt 0 ]; then
pstatus yellow NO
elif [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)"
elif ! command -v perl >/dev/null 2>&1; then
pstatus yellow UNKNOWN "missing 'perl' binary, please install it"
elif ! command -v "${opt_arch_prefix}objdump" >/dev/null 2>&1; then
pstatus yellow UNKNOWN "missing '${opt_arch_prefix}objdump' tool, please install it, usually it's in the binutils package"
pr_info_nol "* Kernel has array_index_nospec (arm64): "
# in 4.19+ kernels, the mask_nospec64 asm64 macro is replaced by array_index_nospec, defined in nospec.h, and used in invoke_syscall()
# ffffff8008090a4c: 2a0203e2 mov w2, w2
# ffffff8008090a50: eb0200bf cmp x5, x2
# ffffff8008090a54: da1f03e2 ngc x2, xzr
# ffffff8008090a58: d503229f hint #0x14
# /!\ can also just be "csdb" instead of "hint #0x14" for native objdump
#
# if we already have a detection, don't bother disassembling the kernel, the answer is no.
if [ -n "$v1_kernel_mitigated" ] || [ -n "$v1_mask_nospec" ] || [ "$g_redhat_canonical_spectre" -gt 0 ]; then
pstatus yellow NO
elif [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)"
elif ! command -v perl >/dev/null 2>&1; then
pstatus yellow UNKNOWN "missing 'perl' binary, please install it"
elif ! command -v "${opt_arch_prefix}objdump" >/dev/null 2>&1; then
pstatus yellow UNKNOWN "missing '${opt_arch_prefix}objdump' tool, please install it, usually it's in the binutils package"
else
"${opt_arch_prefix}objdump" "$g_objdump_options" "$g_kernel" | perl -ne 'push @r, $_; /\s(hint|csdb)\s/ && $r[0]=~/\smov\s+(w\d+),\s+(w\d+)/ && $r[1]=~/\scmp\s+(x\d+),\s+(x\d+)/ && $r[2]=~/\sngc\s+$2,/ && exit(9); shift @r if @r>3'
ret=$?
if [ "$ret" -eq 9 ]; then
pstatus green YES "array_index_nospec macro is present and used"
v1_mask_nospec="arm64 array_index_nospec"
else
"${opt_arch_prefix}objdump" "$g_objdump_options" "$g_kernel" | perl -ne 'push @r, $_; /\s(hint|csdb)\s/ && $r[0]=~/\smov\s+(w\d+),\s+(w\d+)/ && $r[1]=~/\scmp\s+(x\d+),\s+(x\d+)/ && $r[2]=~/\sngc\s+$2,/ && exit(9); shift @r if @r>3'
ret=$?
if [ "$ret" -eq 9 ]; then
pstatus green YES "array_index_nospec macro is present and used"
v1_mask_nospec="arm64 array_index_nospec"
else
pstatus yellow NO
fi
pstatus yellow NO
fi
fi # is_arm_kernel
fi
elif [ "$sys_interface_available" = 0 ]; then
msg="/sys vulnerability interface use forced, but it's not available!"

View File

@@ -104,7 +104,7 @@ check_CVE_2017_5754_linux() {
mount_debugfs
pr_info_nol " * PTI enabled and active: "
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
dmesg_grep="Kernel/User page tables isolation: enabled"
dmesg_grep="$dmesg_grep|Kernel page table isolation enabled"
dmesg_grep="$dmesg_grep|x86/pti: Unmapping kernel while in userspace"
@@ -150,13 +150,10 @@ check_CVE_2017_5754_linux() {
pstatus yellow NO
fi
else
pstatus blue N/A "not testable in no-runtime mode"
pstatus blue N/A "not testable in offline mode"
fi
# PCID/INVPCID are x86-only CPU features
if is_x86_cpu; then
pti_performance_check
fi
pti_performance_check
elif [ "$sys_interface_available" = 0 ]; then
# we have no sysfs but were asked to use it only!
@@ -170,7 +167,7 @@ check_CVE_2017_5754_linux() {
is_xen_dom0 && xen_pv_domo=1
is_xen_domU && xen_pv_domu=1
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
# checking whether we're running under Xen PV 64 bits. If yes, we are affected by affected_variant3
# (unless we are a Dom0)
pr_info_nol "* Running as a Xen PV DomU: "
@@ -186,7 +183,7 @@ check_CVE_2017_5754_linux() {
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif [ -z "$msg" ]; then
# if msg is empty, sysfs check didn't fill it, rely on our own test
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
if [ "$kpti_enabled" = 1 ]; then
pvulnstatus "$cve" OK "PTI mitigates the vulnerability"
elif [ "$xen_pv_domo" = 1 ]; then
@@ -212,12 +209,12 @@ check_CVE_2017_5754_linux() {
fi
else
if [ -n "$kpti_support" ]; then
pvulnstatus "$cve" OK "no-runtime mode: PTI will mitigate the vulnerability if enabled at runtime"
pvulnstatus "$cve" OK "offline mode: PTI will mitigate the vulnerability if enabled at runtime"
elif [ "$kpti_can_tell" = 1 ]; then
pvulnstatus "$cve" VULN "PTI is needed to mitigate the vulnerability"
explain "If you're using a distro kernel, upgrade your distro to get the latest kernel available. Otherwise, recompile the kernel with the CONFIG_(MITIGATION_)PAGE_TABLE_ISOLATION option (named CONFIG_KAISER for some kernels), or the CONFIG_UNMAP_KERNEL_AT_EL0 option (for ARM64)"
else
pvulnstatus "$cve" UNK "no-runtime mode: not enough information"
pvulnstatus "$cve" UNK "offline mode: not enough information"
explain "Re-run this script with root privileges, and give it the kernel image (--kernel), the kernel configuration (--config) and the System.map file (--map) corresponding to the kernel you would like to inspect."
fi
fi

View File

@@ -24,7 +24,7 @@ check_CVE_2018_12207_linux() {
if [ -n "$g_kernel_err" ]; then
kernel_itlbmh_err="$g_kernel_err"
# commit 5219505fcbb640e273a0d51c19c38de0100ec5a9
elif is_x86_kernel && grep -q 'itlb_multihit' "$g_kernel"; then
elif grep -q 'itlb_multihit' "$g_kernel"; then
kernel_itlbmh="found itlb_multihit in kernel image"
fi
if [ -n "$kernel_itlbmh" ]; then
@@ -36,7 +36,7 @@ check_CVE_2018_12207_linux() {
fi
pr_info_nol "* iTLB Multihit mitigation enabled and active: "
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
if [ -n "$ret_sys_interface_check_fullmsg" ]; then
if echo "$ret_sys_interface_check_fullmsg" | grep -qF 'Mitigation'; then
pstatus green YES "$ret_sys_interface_check_fullmsg"
@@ -47,7 +47,7 @@ check_CVE_2018_12207_linux() {
pstatus yellow NO "itlb_multihit not found in sysfs hierarchy"
fi
else
pstatus blue N/A "not testable in no-runtime mode"
pstatus blue N/A "not testable in offline mode"
fi
elif [ "$sys_interface_available" = 0 ]; then
# we have no sysfs but were asked to use it only!
@@ -63,7 +63,7 @@ check_CVE_2018_12207_linux() {
elif [ -z "$msg" ]; then
# if msg is empty, sysfs check didn't fill it, rely on our own test
if [ "$opt_sysfs_only" != 1 ]; then
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
# if we're in live mode and $msg is empty, sysfs file is not there so kernel is too old
pvulnstatus "$cve" VULN "Your kernel doesn't support iTLB Multihit mitigation, update it"
else

View File

@@ -8,10 +8,15 @@ check_CVE_2018_3615() {
pr_info "\033[1;34m$cve aka '$(cve2name "$cve")'\033[0m"
pr_info_nol "* CPU microcode mitigates the vulnerability: "
if [ "$cap_l1df" = 1 ] && [ "$cap_sgx" = 1 ]; then
# the L1D flush CPUID bit indicates that the microcode supports L1D flushing,
# and microcodes that have this also have the fixed SGX (for CPUs that support it),
# because Intel delivered fixed microcodes for both issues at the same time
if { [ "$cap_flush_cmd" = 1 ] || { [ "$g_msr_locked_down" = 1 ] && [ "$cap_l1df" = 1 ]; }; } && [ "$cap_sgx" = 1 ]; then
# no easy way to detect a fixed SGX but we know that
# microcodes that have the FLUSH_CMD MSR also have the
# fixed SGX (for CPUs that support it), because Intel
# delivered fixed microcodes for both issues at the same time
#
# if the system we're running on is locked down (no way to write MSRs),
# make the assumption that if the L1D flush CPUID bit is set, probably
# that FLUSH_CMD MSR is here too
pstatus green YES
elif [ "$cap_sgx" = 1 ]; then
pstatus red NO
@@ -22,7 +27,7 @@ check_CVE_2018_3615() {
if ! is_cpu_affected "$cve"; then
# override status & msg in case CPU is not vulnerable after all
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif [ "$cap_l1df" = 1 ]; then
elif [ "$cap_flush_cmd" = 1 ] || { [ "$g_msr_locked_down" = 1 ] && [ "$cap_l1df" = 1 ]; }; then
pvulnstatus "$cve" OK "your CPU microcode mitigates the vulnerability"
else
pvulnstatus "$cve" VULN "your CPU supports SGX and the microcode is not up to date"

View File

@@ -1,31 +0,0 @@
--- src/vulns/CVE-2018-3615.sh
+++ src/vulns/CVE-2018-3615.sh
@@ -8,15 +8,10 @@ check_CVE_2018_3615() {
pr_info "\033[1;34m$cve aka '$(cve2name "$cve")'\033[0m"
pr_info_nol "* CPU microcode mitigates the vulnerability: "
- if { [ "$cap_flush_cmd" = 1 ] || { [ "$g_msr_locked_down" = 1 ] && [ "$cap_l1df" = 1 ]; }; } && [ "$cap_sgx" = 1 ]; then
- # no easy way to detect a fixed SGX but we know that
- # microcodes that have the FLUSH_CMD MSR also have the
- # fixed SGX (for CPUs that support it), because Intel
- # delivered fixed microcodes for both issues at the same time
- #
- # if the system we're running on is locked down (no way to write MSRs),
- # make the assumption that if the L1D flush CPUID bit is set, probably
- # that FLUSH_CMD MSR is here too
+ if [ "$cap_l1df" = 1 ] && [ "$cap_sgx" = 1 ]; then
+ # the L1D flush CPUID bit indicates that the microcode supports L1D flushing,
+ # and microcodes that have this also have the fixed SGX (for CPUs that support it),
+ # because Intel delivered fixed microcodes for both issues at the same time
pstatus green YES
elif [ "$cap_sgx" = 1 ]; then
pstatus red NO
@@ -27,7 +22,7 @@ check_CVE_2018_3615() {
if ! is_cpu_affected "$cve"; then
# override status & msg in case CPU is not vulnerable after all
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
- elif [ "$cap_flush_cmd" = 1 ] || { [ "$g_msr_locked_down" = 1 ] && [ "$cap_l1df" = 1 ]; }; then
+ elif [ "$cap_l1df" = 1 ]; then
pvulnstatus "$cve" OK "your CPU microcode mitigates the vulnerability"
else
pvulnstatus "$cve" VULN "your CPU supports SGX and the microcode is not up to date"

View File

@@ -37,7 +37,7 @@ check_CVE_2018_3620_linux() {
fi
pr_info_nol "* PTE inversion enabled and active: "
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
if [ -n "$ret_sys_interface_check_fullmsg" ]; then
if echo "$ret_sys_interface_check_fullmsg" | grep -q 'Mitigation: PTE Inversion'; then
pstatus green YES
@@ -51,7 +51,7 @@ check_CVE_2018_3620_linux() {
pteinv_active=-1
fi
else
pstatus blue N/A "not testable in no-runtime mode"
pstatus blue N/A "not testable in offline mode"
fi
elif [ "$sys_interface_available" = 0 ]; then
# we have no sysfs but were asked to use it only!
@@ -66,7 +66,7 @@ check_CVE_2018_3620_linux() {
# if msg is empty, sysfs check didn't fill it, rely on our own test
if [ "$opt_sysfs_only" != 1 ]; then
if [ "$pteinv_supported" = 1 ]; then
if [ "$pteinv_active" = 1 ] || [ "$g_mode" != live ]; then
if [ "$pteinv_active" = 1 ] || [ "$opt_live" != 1 ]; then
pvulnstatus "$cve" OK "PTE inversion mitigates the vulnerability"
else
pvulnstatus "$cve" VULN "Your kernel supports PTE inversion but it doesn't seem to be enabled"

View File

@@ -18,19 +18,19 @@ check_CVE_2018_3639_linux() {
fi
if [ "$opt_sysfs_only" != 1 ]; then
pr_info_nol "* Kernel supports disabling speculative store bypass (SSB): "
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
if grep -Eq 'Speculation.?Store.?Bypass:' "$g_procfs/self/status" 2>/dev/null; then
kernel_ssb="found in $g_procfs/self/status"
pr_debug "found Speculation.Store.Bypass: in $g_procfs/self/status"
fi
fi
# spec_store_bypass is x86-specific; ARM kernels use ARM64_SSBD instead
if [ -z "$kernel_ssb" ] && [ -n "$g_kernel" ] && is_x86_kernel; then
# arm64 kernels can have cpu_show_spec_store_bypass with ARM64_SSBD, so exclude them
if [ -z "$kernel_ssb" ] && [ -n "$g_kernel" ] && ! grep -q 'arm64_sys_' "$g_kernel"; then
kernel_ssb=$("${opt_arch_prefix}strings" "$g_kernel" | grep spec_store_bypass | head -n1)
[ -n "$kernel_ssb" ] && kernel_ssb="found $kernel_ssb in kernel"
fi
# spec_store_bypass is x86-specific; ARM kernels use ARM64_SSBD instead
if [ -z "$kernel_ssb" ] && [ -n "$opt_map" ] && is_x86_kernel; then
# arm64 kernels can have cpu_show_spec_store_bypass with ARM64_SSBD, so exclude them
if [ -z "$kernel_ssb" ] && [ -n "$opt_map" ] && ! grep -q 'arm64_sys_' "$opt_map"; then
kernel_ssb=$(grep spec_store_bypass "$opt_map" | awk '{print $3}' | head -n1)
[ -n "$kernel_ssb" ] && kernel_ssb="found $kernel_ssb in System.map"
fi
@@ -57,7 +57,7 @@ check_CVE_2018_3639_linux() {
fi
kernel_ssbd_enabled=-1
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
# https://elixir.bootlin.com/linux/v5.0/source/fs/proc/array.c#L340
pr_info_nol "* SSB mitigation is enabled and active: "
if grep -Eq 'Speculation.?Store.?Bypass:[[:space:]]+thread' "$g_procfs/self/status" 2>/dev/null; then
@@ -106,7 +106,7 @@ check_CVE_2018_3639_linux() {
# if msg is empty, sysfs check didn't fill it, rely on our own test
if [ -n "$cap_ssbd" ]; then
if [ -n "$kernel_ssb" ]; then
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
if [ "$kernel_ssbd_enabled" -gt 0 ]; then
pvulnstatus "$cve" OK "your CPU and kernel both support SSBD and mitigation is enabled"
else
@@ -121,21 +121,11 @@ check_CVE_2018_3639_linux() {
fi
else
if [ -n "$kernel_ssb" ]; then
if is_arm_kernel; then
pvulnstatus "$cve" VULN "no SSB mitigation is active on your system"
explain "ARM CPUs mitigate SSB either through a hardware SSBS bit (ARMv8.5+ CPUs) or through firmware support for SMCCC ARCH_WORKAROUND_2. Your kernel reports SSB status but neither mechanism appears to be active. For CPUs predating ARMv8.5 (such as Cortex-A57 or Cortex-A72), check with your board or SoC vendor for a firmware update that provides SMCCC ARCH_WORKAROUND_2 support."
else
pvulnstatus "$cve" VULN "Your CPU doesn't support SSBD"
explain "Your kernel is recent enough to use the CPU microcode features for mitigation, but your CPU microcode doesn't actually provide the necessary features for the kernel to use. The microcode of your CPU hence needs to be upgraded. This is usually done at boot time by your kernel (the upgrade is not persistent across reboots which is why it's done at each boot). If you're using a distro, make sure you are up to date, as microcode updates are usually shipped alongside with the distro kernel. Availability of a microcode update for you CPU model depends on your CPU vendor. You can usually find out online if a microcode update is available for your CPU by searching for your CPUID (indicated in the Hardware Check section)."
fi
pvulnstatus "$cve" VULN "Your CPU doesn't support SSBD"
explain "Your kernel is recent enough to use the CPU microcode features for mitigation, but your CPU microcode doesn't actually provide the necessary features for the kernel to use. The microcode of your CPU hence needs to be upgraded. This is usually done at boot time by your kernel (the upgrade is not persistent across reboots which is why it's done at each boot). If you're using a distro, make sure you are up to date, as microcode updates are usually shipped alongside with the distro kernel. Availability of a microcode update for you CPU model depends on your CPU vendor. You can usually find out online if a microcode update is available for your CPU by searching for your CPUID (indicated in the Hardware Check section)."
else
if is_arm_kernel; then
pvulnstatus "$cve" VULN "your kernel and firmware do not support SSB mitigation"
explain "ARM SSB mitigation requires kernel support (CONFIG_ARM64_SSBD) combined with either a hardware SSBS bit (ARMv8.5+ CPUs) or firmware support for SMCCC ARCH_WORKAROUND_2. Ensure you are running a recent kernel compiled with CONFIG_ARM64_SSBD. For CPUs predating ARMv8.5, also check with your board or SoC vendor for a firmware update providing SMCCC ARCH_WORKAROUND_2 support."
else
pvulnstatus "$cve" VULN "Neither your CPU nor your kernel support SSBD"
explain "Both your CPU microcode and your kernel are lacking support for mitigation. If you're using a distro kernel, upgrade your distro to get the latest kernel available. Otherwise, recompile the kernel from recent-enough sources. The microcode of your CPU also needs to be upgraded. This is usually done at boot time by your kernel (the upgrade is not persistent across reboots which is why it's done at each boot). If you're using a distro, make sure you are up to date, as microcode updates are usually shipped alongside with the distro kernel. Availability of a microcode update for you CPU model depends on your CPU vendor. You can usually find out online if a microcode update is available for your CPU by searching for your CPUID (indicated in the Hardware Check section)."
fi
pvulnstatus "$cve" VULN "Neither your CPU nor your kernel support SSBD"
explain "Both your CPU microcode and your kernel are lacking support for mitigation. If you're using a distro kernel, upgrade your distro to get the latest kernel available. Otherwise, recompile the kernel from recent-enough sources. The microcode of your CPU also needs to be upgraded. This is usually done at boot time by your kernel (the upgrade is not persistent across reboots which is why it's done at each boot). If you're using a distro, make sure you are up to date, as microcode updates are usually shipped alongside with the distro kernel. Availability of a microcode update for you CPU model depends on your CPU vendor. You can usually find out online if a microcode update is available for your CPU by searching for your CPUID (indicated in the Hardware Check section)."
fi
fi
else

View File

@@ -3,7 +3,7 @@
# CVE-2018-3640, Variant 3a, Rogue System Register Read
check_CVE_2018_3640() {
local status sys_interface_available msg cve arm_v3a_mitigation
local status sys_interface_available msg cve
cve='CVE-2018-3640'
pr_info "\033[1;34m$cve aka '$(cve2name "$cve")'\033[0m"
@@ -11,52 +11,22 @@ check_CVE_2018_3640() {
sys_interface_available=0
msg=''
if is_arm_kernel; then
# ARM64: mitigation is via an EL2 indirect trampoline (spectre_v3a_enable_mitigation),
# applied automatically at boot for affected CPUs (Cortex-A57, Cortex-A72).
# No microcode update is involved.
arm_v3a_mitigation=''
if [ -n "$opt_map" ] && grep -qw spectre_v3a_enable_mitigation "$opt_map" 2>/dev/null; then
arm_v3a_mitigation="found spectre_v3a_enable_mitigation in System.map"
fi
if [ -z "$arm_v3a_mitigation" ] && [ -n "$g_kernel" ]; then
if "${opt_arch_prefix}strings" "$g_kernel" 2>/dev/null | grep -qw spectre_v3a_enable_mitigation; then
arm_v3a_mitigation="found spectre_v3a_enable_mitigation in kernel image"
fi
fi
pr_info_nol "* Kernel mitigates the vulnerability via EL2 hardening: "
if [ -n "$arm_v3a_mitigation" ]; then
pstatus green YES "$arm_v3a_mitigation"
else
pstatus yellow NO
fi
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif [ -n "$arm_v3a_mitigation" ]; then
pvulnstatus "$cve" OK "your kernel mitigates the vulnerability via EL2 vector hardening"
else
pvulnstatus "$cve" VULN "your kernel does not include the EL2 vector hardening mitigation"
explain "ARM64 Spectre v3a mitigation is provided by the kernel using an indirect trampoline for EL2 (hypervisor) vectors (spectre_v3a_enable_mitigation). Ensure you are running a recent kernel. If you're using a distro kernel, upgrading your distro should provide a kernel with this mitigation included."
fi
pr_info_nol "* CPU microcode mitigates the vulnerability: "
if [ -n "$cap_ssbd" ]; then
# microcodes that ship with SSBD are known to also fix affected_variant3a
# there is no specific cpuid bit as far as we know
pstatus green YES
else
# x86: microcodes that ship with SSBD are known to also fix variant 3a;
# there is no specific CPUID bit for variant 3a as far as we know.
pr_info_nol "* CPU microcode mitigates the vulnerability: "
if [ -n "$cap_ssbd" ]; then
pstatus green YES
else
pstatus yellow NO
fi
pstatus yellow NO
fi
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif [ -n "$cap_ssbd" ]; then
pvulnstatus "$cve" OK "your CPU microcode mitigates the vulnerability"
else
pvulnstatus "$cve" VULN "an up-to-date CPU microcode is needed to mitigate this vulnerability"
explain "The microcode of your CPU needs to be upgraded to mitigate this vulnerability. This is usually done at boot time by your kernel (the upgrade is not persistent across reboots which is why it's done at each boot). If you're using a distro, make sure you are up to date, as microcode updates are usually shipped alongside with the distro kernel. Availability of a microcode update for you CPU model depends on your CPU vendor. You can usually find out online if a microcode update is available for your CPU by searching for your CPUID (indicated in the Hardware Check section). The microcode update is enough, there is no additional OS, kernel or software change needed."
fi
if ! is_cpu_affected "$cve"; then
# override status & msg in case CPU is not vulnerable after all
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif [ -n "$cap_ssbd" ]; then
pvulnstatus "$cve" OK "your CPU microcode mitigates the vulnerability"
else
pvulnstatus "$cve" VULN "an up-to-date CPU microcode is needed to mitigate this vulnerability"
explain "The microcode of your CPU needs to be upgraded to mitigate this vulnerability. This is usually done at boot time by your kernel (the upgrade is not persistent across reboots which is why it's done at each boot). If you're using a distro, make sure you are up to date, as microcode updates are usually shipped alongside with the distro kernel. Availability of a microcode update for you CPU model depends on your CPU vendor. You can usually find out online if a microcode update is available for your CPU by searching for your CPUID (indicated in the Hardware Check section). The microcode update is enough, there is no additional OS, kernel or software change needed."
fi
}

View File

@@ -69,27 +69,22 @@ check_CVE_2018_3646_linux() {
pr_info "* Mitigation 1 (KVM)"
pr_info_nol " * EPT is disabled: "
ept_disabled=-1
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
if ! [ -r "$SYS_MODULE_BASE/kvm_intel/parameters/ept" ]; then
pstatus blue N/A "the kvm_intel module is not loaded"
elif [ "$(cat "$SYS_MODULE_BASE/kvm_intel/parameters/ept")" = N ]; then
pstatus green YES
ept_disabled=1
else
ept_value="$(cat "$SYS_MODULE_BASE/kvm_intel/parameters/ept" 2>/dev/null || echo ERROR)"
if [ "$ept_value" = N ]; then
pstatus green YES
ept_disabled=1
elif [ "$ept_value" = ERROR ]; then
pstatus yellow UNK "Couldn't read $SYS_MODULE_BASE/kvm_intel/parameters/ept"
else
pstatus yellow NO
fi
pstatus yellow NO
fi
else
pstatus blue N/A "not testable in no-runtime mode"
pstatus blue N/A "not testable in offline mode"
fi
pr_info "* Mitigation 2"
pr_info_nol " * L1D flush is supported by kernel: "
if [ "$g_mode" = live ] && grep -qw flush_l1d "$g_procfs/cpuinfo"; then
if [ "$opt_live" = 1 ] && grep -qw flush_l1d "$g_procfs/cpuinfo"; then
l1d_kernel="found flush_l1d in $g_procfs/cpuinfo"
fi
if [ -z "$l1d_kernel" ]; then
@@ -111,7 +106,7 @@ check_CVE_2018_3646_linux() {
fi
pr_info_nol " * L1D flush enabled: "
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
if [ -n "$ret_sys_interface_check_fullmsg" ]; then
# vanilla: VMX: $l1dstatus, SMT $smtstatus
# Red Hat: VMX: SMT $smtstatus, L1D $l1dstatus
@@ -157,18 +152,18 @@ check_CVE_2018_3646_linux() {
fi
else
l1d_mode=-1
pstatus blue N/A "not testable in no-runtime mode"
pstatus blue N/A "not testable in offline mode"
fi
pr_info_nol " * Hardware-backed L1D flush supported: "
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; 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"
else
pstatus blue NO "flush will be done in software, this is slower"
fi
else
pstatus blue N/A "not testable in no-runtime mode"
pstatus blue N/A "not testable in offline mode"
fi
pr_info_nol " * Hyper-Threading (SMT) is enabled: "

View File

@@ -21,7 +21,7 @@ check_CVE_2019_11135_linux() {
kernel_taa=''
if [ -n "$g_kernel_err" ]; then
kernel_taa_err="$g_kernel_err"
elif is_x86_kernel && grep -q 'tsx_async_abort' "$g_kernel"; then
elif grep -q 'tsx_async_abort' "$g_kernel"; then
kernel_taa="found tsx_async_abort in kernel image"
fi
if [ -n "$kernel_taa" ]; then
@@ -33,7 +33,7 @@ check_CVE_2019_11135_linux() {
fi
pr_info_nol "* TAA mitigation enabled and active: "
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
if [ -n "$ret_sys_interface_check_fullmsg" ]; then
if echo "$ret_sys_interface_check_fullmsg" | grep -qE '^Mitigation'; then
pstatus green YES "$ret_sys_interface_check_fullmsg"
@@ -44,7 +44,7 @@ check_CVE_2019_11135_linux() {
pstatus yellow NO "tsx_async_abort not found in sysfs hierarchy"
fi
else
pstatus blue N/A "not testable in no-runtime mode"
pstatus blue N/A "not testable in offline mode"
fi
elif [ "$sys_interface_available" = 0 ]; then
# we have no sysfs but were asked to use it only!
@@ -57,7 +57,7 @@ check_CVE_2019_11135_linux() {
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif [ -z "$msg" ]; then
# if msg is empty, sysfs check didn't fill it, rely on our own test
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
# if we're in live mode and $msg is empty, sysfs file is not there so kernel is too old
pvulnstatus "$cve" VULN "Your kernel doesn't support TAA mitigation, update it"
else

View File

@@ -21,7 +21,7 @@ check_CVE_2020_0543_linux() {
kernel_srbds=''
if [ -n "$g_kernel_err" ]; then
kernel_srbds_err="$g_kernel_err"
elif is_x86_kernel && grep -q 'Dependent on hypervisor' "$g_kernel"; then
elif grep -q 'Dependent on hypervisor' "$g_kernel"; then
kernel_srbds="found SRBDS implementation evidence in kernel image. Your kernel is up to date for SRBDS mitigation"
fi
if [ -n "$kernel_srbds" ]; then
@@ -32,7 +32,7 @@ check_CVE_2020_0543_linux() {
pstatus yellow NO
fi
pr_info_nol "* SRBDS mitigation control is enabled and active: "
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
if [ -n "$ret_sys_interface_check_fullmsg" ]; then
if echo "$ret_sys_interface_check_fullmsg" | grep -qE '^Mitigation'; then
pstatus green YES "$ret_sys_interface_check_fullmsg"
@@ -43,7 +43,7 @@ check_CVE_2020_0543_linux() {
pstatus yellow NO "SRBDS not found in sysfs hierarchy"
fi
else
pstatus blue N/A "not testable in no-runtime mode"
pstatus blue N/A "not testable in offline mode"
fi
elif [ "$sys_interface_available" = 0 ]; then
# we have no sysfs but were asked to use it only!
@@ -61,7 +61,7 @@ check_CVE_2020_0543_linux() {
# SRBDS mitigation control is enabled
if [ -z "$msg" ]; then
# if msg is empty, sysfs check didn't fill it, rely on our own test
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
# if we're in live mode and $msg is empty, sysfs file is not there so kernel is too old
pvulnstatus "$cve" OK "Your microcode is up to date for SRBDS mitigation control. The kernel needs to be updated"
fi
@@ -75,7 +75,7 @@ check_CVE_2020_0543_linux() {
elif [ "$cap_srbds_on" = 0 ]; then
# SRBDS mitigation control is disabled
if [ -z "$msg" ]; then
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
# if we're in live mode and $msg is empty, sysfs file is not there so kernel is too old
pvulnstatus "$cve" VULN "Your microcode is up to date for SRBDS mitigation control. The kernel needs to be updated. Mitigation is disabled"
fi

View File

@@ -1,7 +0,0 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2022-21123, SBDR, Shared Buffers Data Read, MMIO Stale Data
check_CVE_2022_21123() {
check_cve 'CVE-2022-21123' check_mmio
}

View File

@@ -1,7 +0,0 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2022-21125, SBDS, Shared Buffers Data Sampling, MMIO Stale Data
check_CVE_2022_21125() {
check_cve 'CVE-2022-21125' check_mmio
}

View File

@@ -1,7 +0,0 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2022-21166, DRPW, Device Register Partial Write, MMIO Stale Data
check_CVE_2022_21166() {
check_cve 'CVE-2022-21166' check_mmio
}

View File

@@ -174,14 +174,14 @@ check_CVE_2022_29900_linux() {
# Zen/Zen+/Zen2: check IBPB microcode support and SMT
if [ "$cpu_family" = $((0x17)) ]; then
pr_info_nol "* CPU supports IBPB: "
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
if [ -n "$cap_ibpb" ]; then
pstatus green YES "$cap_ibpb"
else
pstatus yellow NO
fi
else
pstatus blue N/A "not testable in no-runtime mode"
pstatus blue N/A "not testable in offline mode"
fi
pr_info_nol "* Hyper-Threading (SMT) is enabled: "
@@ -217,7 +217,7 @@ check_CVE_2022_29900_linux() {
"doesn't fully protect cross-thread speculation."
elif [ -z "$kernel_unret" ] && [ -z "$kernel_ibpb_entry" ]; then
pvulnstatus "$cve" VULN "Your kernel doesn't have either UNRET_ENTRY or IBPB_ENTRY compiled-in"
elif [ "$smt_enabled" = 0 ] && [ -z "$cap_ibpb" ] && [ "$g_mode" = live ]; then
elif [ "$smt_enabled" = 0 ] && [ -z "$cap_ibpb" ] && [ "$opt_live" = 1 ]; then
pvulnstatus "$cve" VULN "SMT is enabled and your microcode doesn't support IBPB"
explain "Update your CPU microcode to get IBPB support, or disable SMT by adding\n" \
"\`nosmt\` to your kernel command line."

View File

@@ -84,7 +84,7 @@ check_CVE_2022_29901_linux() {
fi
pr_info_nol "* CPU supports Enhanced IBRS (IBRS_ALL): "
if [ "$g_mode" = live ] || [ "$cap_ibrs_all" != -1 ]; then
if [ "$opt_live" = 1 ] || [ "$cap_ibrs_all" != -1 ]; then
if [ "$cap_ibrs_all" = 1 ]; then
pstatus green YES
elif [ "$cap_ibrs_all" = 0 ]; then
@@ -93,11 +93,11 @@ check_CVE_2022_29901_linux() {
pstatus yellow UNKNOWN
fi
else
pstatus blue N/A "not testable in no-runtime mode"
pstatus blue N/A "not testable in offline mode"
fi
pr_info_nol "* CPU has RSB Alternate Behavior (RSBA): "
if [ "$g_mode" = live ] || [ "$cap_rsba" != -1 ]; then
if [ "$opt_live" = 1 ] || [ "$cap_rsba" != -1 ]; then
if [ "$cap_rsba" = 1 ]; then
pstatus yellow YES "this CPU is affected by RSB underflow"
elif [ "$cap_rsba" = 0 ]; then
@@ -106,7 +106,7 @@ check_CVE_2022_29901_linux() {
pstatus yellow UNKNOWN
fi
else
pstatus blue N/A "not testable in no-runtime mode"
pstatus blue N/A "not testable in offline mode"
fi
elif [ "$sys_interface_available" = 0 ]; then

View File

@@ -119,17 +119,17 @@ check_CVE_2022_40982_linux() {
kernel_gds_err=''
if [ -n "$g_kernel_err" ]; then
kernel_gds_err="$g_kernel_err"
elif is_x86_kernel && grep -q 'gather_data_sampling' "$g_kernel"; then
elif grep -q 'gather_data_sampling' "$g_kernel"; then
kernel_gds="found gather_data_sampling in kernel image"
fi
if [ -z "$kernel_gds" ] && is_x86_kernel && [ -r "$opt_config" ]; then
if [ -z "$kernel_gds" ] && [ -r "$opt_config" ]; then
if grep -q '^CONFIG_GDS_FORCE_MITIGATION=y' "$opt_config" ||
grep -q '^CONFIG_MITIGATION_GDS_FORCE=y' "$opt_config" ||
grep -q '^CONFIG_MITIGATION_GDS=y' "$opt_config"; then
kernel_gds="GDS mitigation config option found enabled in kernel config"
fi
fi
if [ -z "$kernel_gds" ] && is_x86_kernel && [ -n "$opt_map" ]; then
if [ -z "$kernel_gds" ] && [ -n "$opt_map" ]; then
if grep -q 'gds_select_mitigation' "$opt_map"; then
kernel_gds="found gds_select_mitigation in System.map"
fi
@@ -145,17 +145,17 @@ check_CVE_2022_40982_linux() {
if [ -n "$kernel_gds" ]; then
pr_info_nol "* Kernel has disabled AVX as a mitigation: "
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
# Check dmesg message to see whether AVX has been disabled
dmesg_grep 'Microcode update needed! Disabling AVX as mitigation'
dmesgret=$?
if [ "$dmesgret" -eq 0 ]; then
kernel_avx_disabled="AVX disabled by the kernel (dmesg)"
pstatus green YES "$kernel_avx_disabled"
elif [ "$cap_avx2" = 0 ] && is_x86_cpu; then
elif [ "$cap_avx2" = 0 ]; then
# Find out by ourselves
# cpuinfo says we don't have AVX2, query
# the CPU directly about AVX2 support (x86-only)
# the CPU directly about AVX2 support
read_cpuid 0x7 0x0 "$EBX" 5 1 1
ret=$?
if [ "$ret" -eq "$READ_CPUID_RET_OK" ]; then
@@ -172,7 +172,7 @@ check_CVE_2022_40982_linux() {
pstatus yellow NO "AVX support is enabled"
fi
else
pstatus blue N/A "not testable in no-runtime mode"
pstatus blue N/A "not testable in offline mode"
fi
fi

View File

@@ -88,10 +88,10 @@ check_CVE_2023_20588_linux() {
kernel_mitigated=''
if [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "$g_kernel_err"
elif is_x86_kernel && grep -q 'amd_clear_divider' "$g_kernel"; then
elif grep -q 'amd_clear_divider' "$g_kernel"; then
kernel_mitigated="found amd_clear_divider in kernel image"
pstatus green YES "$kernel_mitigated"
elif is_x86_kernel && [ -n "$opt_map" ] && grep -q 'amd_clear_divider' "$opt_map"; then
elif [ -n "$opt_map" ] && grep -q 'amd_clear_divider' "$opt_map"; then
kernel_mitigated="found amd_clear_divider in System.map"
pstatus green YES "$kernel_mitigated"
else
@@ -101,7 +101,7 @@ check_CVE_2023_20588_linux() {
pr_info_nol "* DIV0 mitigation enabled and active: "
cpuinfo_div0=''
dmesg_div0=''
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
if [ -e "$g_procfs/cpuinfo" ] && grep -qw 'div0' "$g_procfs/cpuinfo" 2>/dev/null; then
cpuinfo_div0=1
pstatus green YES "div0 found in $g_procfs/cpuinfo bug flags"
@@ -119,19 +119,11 @@ check_CVE_2023_20588_linux() {
fi
fi
else
pstatus blue N/A "not testable in no-runtime mode"
pstatus blue N/A "not testable in offline mode"
fi
pr_info_nol "* SMT (Simultaneous Multi-Threading) is enabled: "
pr_info_nol "* SMT (Simultaneous Multi-Threading) status: "
is_cpu_smt_enabled
smt_ret=$?
if [ "$smt_ret" = 0 ]; then
pstatus yellow YES
elif [ "$smt_ret" = 2 ]; then
pstatus yellow UNKNOWN
else
pstatus green NO
fi
elif [ "$sys_interface_available" = 0 ]; then
msg="/sys vulnerability interface use forced, but it's not available!"
status=UNK
@@ -141,7 +133,7 @@ check_CVE_2023_20588_linux() {
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif [ -z "$msg" ]; then
if [ "$opt_sysfs_only" != 1 ]; then
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
# live mode: cpuinfo div0 flag is the strongest proof the mitigation is active
if [ "$cpuinfo_div0" = 1 ] || [ "$dmesg_div0" = 1 ]; then
_cve_2023_20588_pvulnstatus_smt
@@ -153,7 +145,7 @@ check_CVE_2023_20588_linux() {
_cve_2023_20588_pvulnstatus_no_kernel
fi
else
# no-runtime mode: only kernel image / System.map evidence is available
# offline mode: only kernel image / System.map evidence is available
if [ -n "$kernel_mitigated" ]; then
pvulnstatus "$cve" OK "Mitigation: amd_clear_divider found in kernel image"
else

View File

@@ -28,7 +28,7 @@ check_CVE_2023_20593_linux() {
pstatus yellow NO
fi
pr_info_nol "* Zenbleed kernel mitigation enabled and active: "
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
# read the DE_CFG MSR, we want to check the 9th bit
# don't do it on non-Zen2 AMD CPUs or later, aka Family 17h,
# as the behavior could be unknown on others
@@ -53,7 +53,7 @@ check_CVE_2023_20593_linux() {
pstatus blue N/A "CPU is incompatible"
fi
else
pstatus blue N/A "not testable in no-runtime mode"
pstatus blue N/A "not testable in offline mode"
fi
pr_info_nol "* Zenbleed mitigation is supported by CPU microcode: "
@@ -82,7 +82,7 @@ check_CVE_2023_20593_linux() {
elif [ -z "$msg" ]; then
# if msg is empty, sysfs check didn't fill it, rely on our own test
zenbleed_print_vuln=0
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
if [ "$fp_backup_fix" = 1 ] && [ "$ucode_zenbleed" = 1 ]; then
# this should never happen, but if it does, it's interesting to know
pvulnstatus "$cve" OK "Both your CPU microcode and kernel are mitigating Zenbleed"

View File

@@ -69,48 +69,44 @@ check_CVE_2023_28746_linux() {
fi
if [ "$opt_sysfs_only" != 1 ]; then
if is_x86_cpu; then
pr_info_nol "* CPU microcode mitigates the vulnerability: "
if [ "$cap_rfds_clear" = 1 ]; then
pstatus green YES "RFDS_CLEAR capability indicated by microcode"
elif [ "$cap_rfds_clear" = 0 ]; then
pstatus yellow NO
else
pstatus yellow UNKNOWN "couldn't read MSR"
fi
pr_info_nol "* CPU microcode mitigates the vulnerability: "
if [ "$cap_rfds_clear" = 1 ]; then
pstatus green YES "RFDS_CLEAR capability indicated by microcode"
elif [ "$cap_rfds_clear" = 0 ]; then
pstatus yellow NO
else
pstatus yellow UNKNOWN "couldn't read MSR"
fi
if is_x86_kernel; then
pr_info_nol "* Kernel supports RFDS mitigation (VERW on transitions): "
kernel_rfds=''
kernel_rfds_err=''
if [ -n "$g_kernel_err" ]; then
kernel_rfds_err="$g_kernel_err"
elif grep -q 'Clear Register File' "$g_kernel"; then
kernel_rfds="found 'Clear Register File' string in kernel image"
elif grep -q 'reg_file_data_sampling' "$g_kernel"; then
kernel_rfds="found reg_file_data_sampling in kernel image"
fi
if [ -z "$kernel_rfds" ] && [ -r "$opt_config" ]; then
if grep -q '^CONFIG_MITIGATION_RFDS=y' "$opt_config"; then
kernel_rfds="RFDS mitigation config option found enabled in kernel config"
fi
fi
if [ -z "$kernel_rfds" ] && [ -n "$opt_map" ]; then
if grep -q 'rfds_select_mitigation' "$opt_map"; then
kernel_rfds="found rfds_select_mitigation in System.map"
fi
fi
if [ -n "$kernel_rfds" ]; then
pstatus green YES "$kernel_rfds"
elif [ -n "$kernel_rfds_err" ]; then
pstatus yellow UNKNOWN "$kernel_rfds_err"
else
pstatus yellow NO
pr_info_nol "* Kernel supports RFDS mitigation (VERW on transitions): "
kernel_rfds=''
kernel_rfds_err=''
if [ -n "$g_kernel_err" ]; then
kernel_rfds_err="$g_kernel_err"
elif grep -q 'Clear Register File' "$g_kernel"; then
kernel_rfds="found 'Clear Register File' string in kernel image"
elif grep -q 'reg_file_data_sampling' "$g_kernel"; then
kernel_rfds="found reg_file_data_sampling in kernel image"
fi
if [ -z "$kernel_rfds" ] && [ -r "$opt_config" ]; then
if grep -q '^CONFIG_MITIGATION_RFDS=y' "$opt_config"; then
kernel_rfds="RFDS mitigation config option found enabled in kernel config"
fi
fi
if [ -z "$kernel_rfds" ] && [ -n "$opt_map" ]; then
if grep -q 'rfds_select_mitigation' "$opt_map"; then
kernel_rfds="found rfds_select_mitigation in System.map"
fi
fi
if [ -n "$kernel_rfds" ]; then
pstatus green YES "$kernel_rfds"
elif [ -n "$kernel_rfds_err" ]; then
pstatus yellow UNKNOWN "$kernel_rfds_err"
else
pstatus yellow NO
fi
if is_x86_cpu && [ "$g_mode" = live ] && [ "$sys_interface_available" = 1 ]; then
if [ "$opt_live" = 1 ] && [ "$sys_interface_available" = 1 ]; then
pr_info_nol "* RFDS mitigation is enabled and active: "
if echo "$ret_sys_interface_check_fullmsg" | grep -qi '^Mitigation'; then
rfds_mitigated=1
@@ -133,7 +129,7 @@ check_CVE_2023_28746_linux() {
if [ "$opt_sysfs_only" != 1 ]; then
if [ "$cap_rfds_clear" = 1 ]; then
if [ -n "$kernel_rfds" ]; then
if [ "$g_mode" = live ]; then
if [ "$opt_live" = 1 ]; then
if [ "$rfds_mitigated" = 1 ]; then
pvulnstatus "$cve" OK "Your microcode and kernel are both up to date for this mitigation, and mitigation is enabled"
else

View File

@@ -92,15 +92,15 @@ check_CVE_2024_28956_linux() {
kernel_its_err=''
if [ -n "$g_kernel_err" ]; then
kernel_its_err="$g_kernel_err"
elif is_x86_kernel && grep -q 'indirect_target_selection' "$g_kernel"; then
elif grep -q 'indirect_target_selection' "$g_kernel"; then
kernel_its="found indirect_target_selection in kernel image"
fi
if [ -z "$kernel_its" ] && is_x86_kernel && [ -r "$opt_config" ]; then
if [ -z "$kernel_its" ] && [ -r "$opt_config" ]; then
if grep -q '^CONFIG_MITIGATION_ITS=y' "$opt_config"; then
kernel_its="ITS mitigation config option found enabled in kernel config"
fi
fi
if [ -z "$kernel_its" ] && is_x86_kernel && [ -n "$opt_map" ]; then
if [ -z "$kernel_its" ] && [ -n "$opt_map" ]; then
if grep -q 'its_select_mitigation' "$opt_map"; then
kernel_its="found its_select_mitigation in System.map"
fi

View File

@@ -72,15 +72,15 @@ check_CVE_2024_36350_linux() {
if [ -n "$g_kernel_err" ]; then
kernel_tsa_err="$g_kernel_err"
# commit d8010d4ba43e: "Transient Scheduler Attacks:" is printed by tsa_select_mitigation()
elif is_x86_kernel && grep -q 'Transient Scheduler Attacks' "$g_kernel"; then
elif grep -q 'Transient Scheduler Attacks' "$g_kernel"; then
kernel_tsa="found TSA mitigation message in kernel image"
fi
if [ -z "$kernel_tsa" ] && is_x86_kernel && [ -r "$opt_config" ]; then
if [ -z "$kernel_tsa" ] && [ -r "$opt_config" ]; then
if grep -q '^CONFIG_MITIGATION_TSA=y' "$opt_config"; then
kernel_tsa="CONFIG_MITIGATION_TSA=y found in kernel config"
fi
fi
if [ -z "$kernel_tsa" ] && is_x86_kernel && [ -n "$opt_map" ]; then
if [ -z "$kernel_tsa" ] && [ -n "$opt_map" ]; then
if grep -q 'tsa_select_mitigation' "$opt_map"; then
kernel_tsa="found tsa_select_mitigation in System.map"
fi

View File

@@ -72,15 +72,15 @@ check_CVE_2024_36357_linux() {
if [ -n "$g_kernel_err" ]; then
kernel_tsa_err="$g_kernel_err"
# commit d8010d4ba43e: "Transient Scheduler Attacks:" is printed by tsa_select_mitigation()
elif is_x86_kernel && grep -q 'Transient Scheduler Attacks' "$g_kernel"; then
elif grep -q 'Transient Scheduler Attacks' "$g_kernel"; then
kernel_tsa="found TSA mitigation message in kernel image"
fi
if [ -z "$kernel_tsa" ] && is_x86_kernel && [ -r "$opt_config" ]; then
if [ -z "$kernel_tsa" ] && [ -r "$opt_config" ]; then
if grep -q '^CONFIG_MITIGATION_TSA=y' "$opt_config"; then
kernel_tsa="CONFIG_MITIGATION_TSA=y found in kernel config"
fi
fi
if [ -z "$kernel_tsa" ] && is_x86_kernel && [ -n "$opt_map" ]; then
if [ -z "$kernel_tsa" ] && [ -n "$opt_map" ]; then
if grep -q 'tsa_select_mitigation' "$opt_map"; then
kernel_tsa="found tsa_select_mitigation in System.map"
fi

View File

@@ -85,15 +85,15 @@ check_CVE_2025_40300_linux() {
kernel_vmscape_err=''
if [ -n "$g_kernel_err" ]; then
kernel_vmscape_err="$g_kernel_err"
elif is_x86_kernel && grep -q 'vmscape' "$g_kernel"; then
elif grep -q 'vmscape' "$g_kernel"; then
kernel_vmscape="found vmscape in kernel image"
fi
if [ -z "$kernel_vmscape" ] && is_x86_kernel && [ -r "$opt_config" ]; then
if [ -z "$kernel_vmscape" ] && [ -r "$opt_config" ]; then
if grep -q '^CONFIG_MITIGATION_VMSCAPE=y' "$opt_config"; then
kernel_vmscape="VMScape mitigation config option found enabled in kernel config"
fi
fi
if [ -z "$kernel_vmscape" ] && is_x86_kernel && [ -n "$opt_map" ]; then
if [ -z "$kernel_vmscape" ] && [ -n "$opt_map" ]; then
if grep -q 'vmscape_select_mitigation' "$opt_map"; then
kernel_vmscape="found vmscape_select_mitigation in System.map"
fi

View File

@@ -1,151 +0,0 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2025-54505, FPDSS, AMD Zen1 Floating-Point Divider Stale Data Leak
check_CVE_2025_54505() {
check_cve 'CVE-2025-54505'
}
# Print remediation advice for FPDSS when reporting VULN
# Callers: check_CVE_2025_54505_linux
_cve_2025_54505_explain_fix() {
explain "Update your kernel to one that carries commit e55d98e77561 (\"x86/CPU: Fix FPDSS on Zen1\", mainline Linux 7.1),\n " \
"or the equivalent backport from your distribution. The kernel sets bit 9 of MSR 0xc0011028 unconditionally on\n " \
"every Zen1 CPU at boot, which disables the hardware optimization responsible for the leak.\n " \
"To manually mitigate the issue right now, you may use the following command:\n " \
"\`wrmsr -a 0xc0011028 \$((\$(rdmsr -c 0xc0011028) | (1<<9)))\`,\n " \
"however note that this manual mitigation will only be active until the next reboot.\n " \
"No microcode update is required: the chicken bit is present on every Zen1 CPU."
}
check_CVE_2025_54505_linux() {
local status sys_interface_available msg kernel_mitigated dmesg_fpdss msr_fpdss ret
status=UNK
sys_interface_available=0
msg=''
# No sysfs interface exists for this vulnerability (no /sys/devices/system/cpu/vulnerabilities/fpdss).
# sys_interface_available stays 0.
#
# Kernel source inventory for FPDSS, traced via git blame:
#
# --- sysfs messages ---
# none: this vulnerability has no sysfs entry
#
# --- Kconfig symbols ---
# none: the mitigation is unconditional, not configurable (no CONFIG_* knob)
#
# --- kernel functions (for $opt_map / System.map) ---
# none: the fix is two inline lines in init_amd_zen1(), no dedicated function
#
# --- dmesg ---
# e55d98e77561 (v7.1, initial fix): "AMD Zen1 FPDSS bug detected, enabling mitigation."
# (printed via pr_notice_once on every Zen1 CPU)
#
# --- /proc/cpuinfo bugs field ---
# none: no X86_BUG_FPDSS flag defined; no cpuinfo exposure
#
# --- MSR ---
# e55d98e77561 (v7.1): MSR_AMD64_FP_CFG = 0xc0011028, bit 9 = ZEN1_DENORM_FIX_BIT
# kernel calls msr_set_bit() unconditionally on any Zen1 CPU in init_amd_zen1().
# The bit is present in Zen1 silicon independently of microcode (no microcode
# revision gate in the kernel, unlike Zenbleed which uses amd_zenbleed_microcode[]).
#
# --- CPU affection logic (for is_cpu_affected) ---
# e55d98e77561 (v7.1): applied unconditionally in init_amd_zen1(), i.e. all Zen1
# AMD: family 0x17 models 0x00-0x2f, 0x50-0x5f (same cohort as DIV0)
# vendor scope: AMD only (Zen1 microarchitecture)
#
# --- stable backports ---
# as of this writing, no stable/LTS backport has landed; only mainline (Linux 7.1).
if [ "$opt_sysfs_only" != 1 ]; then
pr_info_nol "* Kernel supports FPDSS mitigation: "
kernel_mitigated=''
if [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "$g_kernel_err"
elif is_x86_kernel && grep -q 'AMD Zen1 FPDSS bug detected' "$g_kernel"; then
kernel_mitigated="found FPDSS mitigation message in kernel image"
pstatus green YES "$kernel_mitigated"
else
pstatus yellow NO
fi
pr_info_nol "* FPDSS mitigation enabled and active: "
msr_fpdss=''
dmesg_fpdss=''
if [ "$g_mode" = live ] && is_x86_cpu && is_cpu_affected "$cve"; then
# guard with is_cpu_affected to avoid #GP on non-Zen1 CPUs where 0xc0011028 is undefined
read_msr 0xc0011028
ret=$?
if [ "$ret" = "$READ_MSR_RET_OK" ]; then
if [ $((ret_read_msr_value_lo >> 9 & 1)) -eq 1 ]; then
msr_fpdss=1
pstatus green YES "ZEN1_DENORM_FIX_BIT set in FP_CFG MSR"
else
msr_fpdss=0
pstatus yellow NO "ZEN1_DENORM_FIX_BIT is cleared in FP_CFG MSR"
fi
else
# MSR unreadable (lockdown, no msr module, etc.): fall back to dmesg
dmesg_grep 'AMD Zen1 FPDSS bug detected'
ret=$?
if [ "$ret" -eq 0 ]; then
dmesg_fpdss=1
pstatus green YES "FPDSS mitigation message found in dmesg"
elif [ "$ret" -eq 2 ]; then
pstatus yellow UNKNOWN "couldn't read MSR and dmesg is truncated"
else
pstatus yellow UNKNOWN "couldn't read MSR and no FPDSS message in dmesg"
fi
fi
elif [ "$g_mode" = live ]; then
pstatus blue N/A "CPU is incompatible"
else
pstatus blue N/A "not testable in no-runtime mode"
fi
elif [ "$sys_interface_available" = 0 ]; then
msg="/sys vulnerability interface use forced, but it's not available!"
status=UNK
fi
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif [ -z "$msg" ]; then
if [ "$opt_sysfs_only" != 1 ]; then
if [ "$g_mode" = live ]; then
if [ "$msr_fpdss" = 1 ] || [ "$dmesg_fpdss" = 1 ]; then
pvulnstatus "$cve" OK "ZEN1_DENORM_FIX_BIT is set in FP_CFG MSR, mitigation is active"
elif [ "$msr_fpdss" = 0 ]; then
pvulnstatus "$cve" VULN "ZEN1_DENORM_FIX_BIT is cleared in FP_CFG MSR, FPDSS can leak data between threads"
_cve_2025_54505_explain_fix
elif [ -n "$kernel_mitigated" ]; then
# MSR unreadable at runtime, but kernel image carries the mitigation code
# and init_amd_zen1() sets the bit unconditionally, so mitigation is active
pvulnstatus "$cve" OK "kernel image carries FPDSS mitigation code (init_amd_zen1 sets the MSR bit unconditionally at boot)"
else
pvulnstatus "$cve" VULN "your kernel doesn't support FPDSS mitigation"
_cve_2025_54505_explain_fix
fi
else
if [ -n "$kernel_mitigated" ]; then
pvulnstatus "$cve" OK "Mitigation: FPDSS message found in kernel image"
else
pvulnstatus "$cve" VULN "your kernel doesn't support FPDSS mitigation"
_cve_2025_54505_explain_fix
fi
fi
else
pvulnstatus "$cve" "$status" "no sysfs interface available for this CVE, use --no-sysfs to check"
fi
else
pvulnstatus "$cve" "$status" "$msg"
fi
}
check_CVE_2025_54505_bsd() {
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
else
pvulnstatus "$cve" UNK "your CPU is affected, but mitigation detection has not yet been implemented for BSD in this script"
fi
}