Compare commits

..

556 Commits

Author SHA1 Message Date
Stéphane Lesimple
e2d110a3b5 doc: update output formats doc + normalize json to bool 2026-04-20 12:55:34 +02:00
Stéphane Lesimple
1bb33d5cf2 chore: remove from test branch workflows that must live on master 2026-04-20 12:53:36 +02:00
Stéphane Lesimple
6732eb141b doc: CVE-2018-3665 (Lazy FP State Restore (LazyFP)), unsupported 2026-04-19 12:49:17 +02:00
Stéphane Lesimple
048ce5b6a2 enh: add FPDSS check for AMD Zen1/Zen+ (CVE-2025-54505) 2026-04-18 17:18:42 +02:00
Stéphane Lesimple
48454a5344 fix: remove useless checks under ARM for CVE-2023-28746 2026-04-10 19:50:15 +02:00
Stéphane Lesimple
e67c9e4265 enh: use g_mode to explicitly save/load the current running mode 2026-04-10 19:28:10 +02:00
Stéphane Lesimple
f7ba617e16 enh: guard x86/arm specific checks in kernel/cpu for the proper arch 2026-04-10 19:28:10 +02:00
Stéphane Lesimple
e110706df8 enh: factorize is_arch_kernel 2026-04-10 18:37:14 +02:00
Stéphane Lesimple
de853fc801 chore: fix build workflow 2026-04-08 23:00:40 +02:00
Stéphane Lesimple
98ec067aef enh: rework json/prom output to better split x86/arm 2026-04-08 22:58:36 +02:00
Stéphane Lesimple
ff42393fa6 new batch mode docs, add doc/ to -build branch 2026-04-08 22:58:36 +02:00
Stéphane Lesimple
f0fb59310e fix: add a missing pstatus to CVE-2023-20588 check 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
be0f2d20d2 fix: remove misleading explain on correctly mitigated SLS 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
3639de9e8a chore: fix github workflow check with new --batch output 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
df3c2aeaa3 add screenshot to README 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
945f70bb63 fix: early abort when using --allow-msr-write 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
db84fc10de chore: make fmt 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
60ea669e41 enh: better explain the 4 run modes 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
f1c0d5548c chg: remove --no-intel-db, it's now always used when available 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
9e617a4363 remove prometheus-legacy format 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
b9c203120b enh: --no-runtime and --no-hw modes replacing --live and implicit 'offline' mode 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
3f7e0a11f7 enh: CVE-2018-3640 (Spectre 3a): enhance ARM mitigation detection 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
5c469787ea enh: rework --batch nrpe entirely 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
a952fe32c4 fix: exit_cleanup: don't lose passed exit code 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
61fa02d577 feat: rework the --batch prometheus output entirely 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
39dea1245e feat: rework the --batch json output entirely 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
3afbda8430 enh: when reading CPUID is unavailable (VM?), fallback to cpuinfo where applicable
cap_* variable <= cpuinfo flag

cap_ibrs              <= ibrs
cap_ibpb              <= ibpb
cap_stibp             <= stibp
cap_ssbd              <= ssbd / virt_ssbd
cap_l1df              <= flush_l1d
cap_md_clear          <= md_clear
cap_arch_capabilities <= arch_capabilities

Should fix #288
2026-04-08 22:35:53 +02:00
Stéphane Lesimple
6d69ce9a77 enh: read/write_msr: clearer error messages 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
3ebfba2ac2 fix: CVE-2017-5715 (Spectre V2): Red Hat specific fix for RSB Filling (fixes #235) 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
a3f6553e65 fix: read/write msr and lockdown: fix a variable error, properly report lockdown to users 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
42ed8efa65 fix: better compatibility under busybox, silence buggy unzlma versions (fix #432) 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
2c766b7cc6 fix: wrmsr: specify core number (closes #294) 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
49472f1b64 enh: clearer kernel info section at the top of the script 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
333aa74fea enh: clearer CPU details section 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
8d9504d174 chore: add comment about is_intel/amd/hygon recursion 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
6043f586ef enh: update IntelDB affected CPU list to 2026-04 data, including Hybrid CPU detection 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
e1ace7c281 doc: document Platypus (CVE-2020-8694 CVE-2020-8695) as out of scope (#384) 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
24ab98d757 doc: document CVE-2020-24511 and CVE-2020-24512 as being out of scope along with rationale (#409) 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
155b3808b9 fix: CPUs affected by MSBDS but not MDS (fix #351) 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
b6a41918b0 doc: add CVE-2019-11157 (Plundervolt) to unsupported CVE list 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
3c56ac35dd fix: better detect kernel lockdown & no longer require cap_flush_cmd to deem CVE-2018-3615 as mitigated (fix #296) 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
b0bb1f4676 feat: implement check for MMIO Stale Data (CVE-2022-21123 CVE-2022-21125 CVE-2022-21166) (#437) 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
0fa7e44327 doc: add Blindside to unsupported list (#374) 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
f100b4e1dc doc: add CVE-2020-0549 (L1D Eviction Sampling, CacheOut) as unsupported 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
6332fc3405 fix: CVE-2019-11135 (TAA) detect new 0x10F MSR for TSX-disabled CPUs (#414) 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
3c61c7489b fix: CVE-2024-3635[0,7] don't print lines about TSA CPUID bits under non-AMD 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
3d01978cd4 feat: add CVE-2023-20588 (AMD DIV0 bug) (#473) 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
53c45e3363 doc: update dev guidelines 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
acf8b585a5 doc: add CVE-2024-2201 (Native BHI) and TLBleed as unsupported 2026-04-08 22:35:53 +02:00
Stéphane Lesimple
076a1d5723 fix: CVE-2020-0543 (SRBDS): microcode mitigation misdetected (#492) 2026-04-08 22:35:52 +02:00
Stéphane Lesimple
ee618ead07 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-08 22:35:52 +02:00
Stéphane Lesimple
1ff1dfbe26 fix: don't default to 0x0 ucode when unknown 2026-04-08 22:35:52 +02:00
Stéphane Lesimple
78e4d25319 fix: bsd: use proper MSR for AMD in ucode version read fallback 2026-04-08 22:35:52 +02:00
Stéphane Lesimple
24ed9ccaf6 enh: MDS FreeBSD: detect software mitigation as OK unless --paranoid (#503) 2026-04-08 22:35:52 +02:00
Stéphane Lesimple
a49234ed96 doc: add CVE-2021-26318 (ADM Prefetch) to unsupported list 2026-04-08 22:35:52 +02:00
Stéphane Lesimple
2ed15da028 feat: implement CVE-2023-28746 (RFDS, Register File Data Sampling) 2026-04-08 22:35:52 +02:00
Stéphane Lesimple
0fcdc6e6cc feat: add SLS (Straight-Line Speculation) check with --extra option 2026-04-08 22:35:52 +02:00
Stéphane Lesimple
7a7408d124 fix: add rebleet to --variant 2026-04-04 16:22:05 +00:00
Stéphane Lesimple
cccb3c0081 enh: add known fixed ucode versions for CVE-2023-23583 (Reptar) and CVE-2024-45332 (BPI) 2026-04-04 16:07:12 +00:00
Stéphane Lesimple
090f109c52 doc: add CVE-2023-31315 (SinkClose) to the unsupported list, add categories 2026-04-04 16:07:12 +00:00
Stéphane Lesimple
5dc9c3c18d chore: reorder CVE list in README.md 2026-04-04 16:07:12 +00:00
Stéphane Lesimple
a00fab131f feat: implement CVE-2025-40300 (VMScape) and CVE-2024-45332 (BTI) 2026-04-04 16:07:12 +00:00
Stéphane Lesimple
e0b818f8fa chore: stalebot: disable dryrun by default 2026-04-04 16:07:12 +00:00
Stéphane Lesimple
4af11551ba feat: implement CVE-2024-28956 (ITS, Indirect Target Selection) vulnerability and mitigation detection 2026-04-04 16:07:12 +00:00
Stéphane Lesimple
dfed6f35c5 doc: add note about more unsupported CVEs
CVE-2020-12965 - Transient Execution of Non-Canonical Accesses (SLAM)
CVE-2024-7881 - ARM Prefetcher Privilege Escalation
CVE-2024-56161 - EntrySign (AMD Microcode Signature Bypass)
CVE-2025-20623 - Shared Microarchitectural Predictor State (10th Gen Intel)
CVE-2025-24495 - Lion Cove BPU Initialization
CVE-2025-29943 - StackWarp (AMD SEV-SNP)
2026-04-04 16:07:12 +00:00
Stéphane Lesimple
1652977f47 add a generated version of src/libs/003_intel_models.sh 2026-04-04 16:07:12 +00:00
Stéphane Lesimple
a089ae8cef fix: sys_interface_check() must set the caller's $msg var (closes #533) 2026-04-04 16:07:12 +00:00
Stéphane Lesimple
cc6bbaad19 chore: don't include src/ generated files in build 2026-04-04 16:07:12 +00:00
Stéphane Lesimple
2717b0a4be doc: CVE-2020-12965 unsupported (#478) 2026-04-04 16:07:12 +00:00
Stéphane Lesimple
6fac2d8ff1 Merge pull request #532 from speed47/test
Retbleed / Downfall overhald / doc updates
2026-04-02 21:32:39 +00:00
Stéphane Lesimple
ae5493257e doc: CVE-2018-3693 CVE-2019-1125 CVE-2019-15902 unsupported or already included 2026-04-02 23:22:31 +02:00
Stéphane Lesimple
47e202100a doc: CVE-2018-15572 is already implemented along Spectre V2 2026-04-02 23:12:29 +02:00
Stéphane Lesimple
0edb357894 doc: CVE-2018-9056 is out of scope (closes #169) 2026-04-02 22:58:45 +02:00
Stéphane Lesimple
ed6a0a2882 doc: unsupported CVE list 2026-04-02 22:51:55 +02:00
Stéphane Lesimple
86e0fae48a enh: group results by 4 in the summary line at the end of the run 2026-04-02 22:45:08 +02:00
Stéphane Lesimple
cb3b9a37fa enh: rework VERSION adjust when we're cloned 2026-04-02 22:33:48 +02:00
Stéphane Lesimple
b9f75346d4 enh: auto-generate intel model list 2026-04-02 22:33:48 +02:00
Stéphane Lesimple
4f6dbb36c8 feat: implement Retbleed (CVE-2022-29900 CVE-2022-29901) mitigation detection 2026-04-02 22:33:48 +02:00
Stéphane Lesimple
d644941a76 chore: update dev doc with check_CVE_* header exception 2026-04-02 22:09:09 +02:00
Stéphane Lesimple
3ea8e213ec chore: add proper header to all src/vulns/* files 2026-04-02 21:03:29 +02:00
Stéphane Lesimple
5e3033e2f5 enh: CVE-2022-40982 (Downfall) overhaul & Spectre V2 enhancements
Downfall:

- added `--kernel-config` support for all three Kconfig variants seen over all kernel versions up to now
- added `--kernel-map` support for `gds_select_mitigation` in `System.map`
- fixed the `--sysfs-only` mode
- added verbose information about remediation when `--explain` is used
- implemented `--paranoid mode`, requiring `GDS_MITIGATION_LOCKED` so that mitigation can't be disabled at runtime
- fixed offline mode (was wrongly looking at the system `dmesg`)
- better microcode status reporting (enabled, disabled, unsupported, unknown)
- fixed unknown (EOL) AVX-capable Intel family 6 CPUs now defaulting to affected
- fixed 2 missing known affected CPU models: INTEL_FAM6_SKYLAKE_L and INTEL_FAM6_SKYLAKE
- fixed case when we're running in a VM and the hypervisor doesn't let us read the MSR

Spectre V2:
- fix: affected_cpu: added Centaur family 7 (CentaurHauls) and Zhaoxin family 7 (Shanghai) as immune
- fix: added Centaur family 5 (CentaurHauls) and NSC family 5 (Geode by NSC) to is_cpu_specex_free()
- enh: offline mode: added detection logic by probing System.map and Kconfig
2026-04-02 21:00:30 +02:00
Stéphane Lesimple
37204869f8 chore: update dev guidelines 2026-04-02 19:55:07 +02:00
Stéphane Lesimple
d3c0f1a24d Merge pull request #530 from speed47/test
chore: workflows revamp
2026-04-02 16:49:41 +00:00
Stéphane Lesimple
c799974038 chore: build: also add new files, handle github workflows 2026-04-02 18:47:00 +02:00
Stéphane Lesimple
0974871a6c chore: build: also add new files 2026-04-02 18:43:51 +02:00
Stéphane Lesimple
952fe6a87f Merge branch 'test' into source 2026-04-02 18:40:05 +02:00
Stéphane Lesimple
5e2af29e6a chore: conditional workflows on all branches 2026-04-02 18:37:46 +02:00
Stéphane Lesimple
afadf53f7f chore: add stalebot in dryrun 2026-04-02 11:15:36 +00:00
Stéphane Lesimple
5fc008f2d4 chore: add stalebot in dryrun 2026-04-02 13:13:19 +02:00
Stéphane Lesimple
e5c6d2d905 enh: CVE-2017-5715; check for unprivileged eBPF for paranoid mode 2026-04-01 20:37:54 +00:00
Stéphane Lesimple
ac327ce7c5 chore: shellcheck fixes 2026-04-01 20:10:29 +00:00
Stéphane Lesimple
03f63714b5 fix: CVE-2023-20569: logic errors with kernel_sro type change (bool => str) 2026-04-01 19:58:20 +00:00
Stéphane Lesimple
08702b07c9 fix: bad kernel/config var names 2026-04-01 19:53:34 +00:00
Stéphane Lesimple
4718134427 chore: cap_ipred unused for now, make shellcheck happy 2026-04-01 21:37:56 +02:00
Stéphane Lesimple
e23712129d enh: rework is_cpu_affected() to enhance maintainability 2026-04-01 21:36:45 +02:00
Stéphane Lesimple
43c515ac74 enh: CVE-2017-5715 (spectre v2): make vuln assessment cap_bhi-aware 2026-04-01 21:34:12 +02:00
Stéphane Lesimple
8c3fb7b2cc enh: CVE-2024-36357 CVE-2024-36350 (TSA): inventory of sysfs strings + consider vuln if TSA mitigation forced to user/kernel on hypervisors 2026-04-01 21:12:23 +02:00
Stéphane Lesimple
d05601ed3f feat: add CVE-2023-20593 (Zenbleed) mitigation detection for BSD 2026-04-01 21:12:23 +02:00
Stéphane Lesimple
690725ccc1 enh: add BSD stubs for CVE-2022-40982 CVE-2023-20569 CVE-2023-23583, detecting unaffected CPUs 2026-04-01 21:12:23 +02:00
Stéphane Lesimple
4875b4c71c feat: add CVE-2020-0543 (SRBDS) mitigation detection under BSD 2026-04-01 21:12:23 +02:00
Stéphane Lesimple
2b603c68ce feat: add CVE-2019-11135 (TAA) mitigation detection under BSD 2026-04-01 21:12:23 +02:00
Stéphane Lesimple
0628a3e565 enh: vmm detection has been greatly enhanced
We also cache the result instead of computing it every time
2026-04-01 21:12:23 +02:00
Stéphane Lesimple
536dfb8701 enh: massive update for Spectre v2 (CVE-2017-5715)
The state of the mitigations for spectre v2 has been
updated several times in the kernel, this commit brings
up the script to par with the view of the most recent kernels.

When run on old kernels, that might deem the vulnerability as
mitigated, we'll reclassify it as vulnerable if applicable, unless
the `--sysfs-only` parameter is passed, which instructs the script
to blindly trust what the kernel has to say.

A full inventory of all mitigation strings found in mainline,
stable and redhat kernels since the first spectre v2 mitigation
has been added as a gigantic comment to help understanding the context.

Gory details below:

  1. New structured sub-mitigation parsing ("Mitigation 3")

  A new section parses the sysfs message into discrete variables for each sub-mitigation component:
  - v2_base_mode: The primary mitigation (eibrs, eibrs_lfence, eibrs_retpoline, ibrs, retpoline, lfence, none) - parsed from sysfs with hardware fallback
  - v2_stibp_status: STIBP state (always-on, forced, conditional, disabled, eibrs-implicit, etc.)
  - v2_ibpb_mode: IBPB mode (always-on, conditional, disabled)
  - v2_pbrsb_status: PBRSB-eIBRS mitigation (not-affected, sw-sequence, vulnerable)
  - v2_bhi_status: BHI mitigation (not-affected, bhi_dis_s, sw-loop, retpoline, vulnerable)
  - v2_vuln_module: Whether a non-retpoline kernel module is loaded
  - v2_is_autoibrs: Distinguishes AMD AutoIBRS from Intel eIBRS (they have different cross-thread properties)

  2. Rewritten verdict logic (Phase 4)

  The old flat if/elif chain is replaced with per-base-mode branches, each checking all relevant sub-mitigations:
  - LFENCE: Always VULN (reclassified in kernel v5.17)
  - eIBRS path: Checks BHI, PBRSB (VMM-only), AutoIBRS STIBP, vulnerable modules, paranoid mode (IBPB always-on + SMT off)
  - IBRS path: Checks IBPB, STIBP+SMT, RSB filling on Skylake+, BHI, paranoid mode
  - Retpoline path: Checks compiler, runtime enable, RSB filling, BHI+RRSBA, IBPB, vulnerable modules, paranoid mode

  3. Caveat accumulation pattern

  A _v2_add_caveat helper collects all gaps into a single string, producing verdicts like "eIBRS active but insufficient: BHI vulnerable; STIBP not active with SMT on AMD AutoIBRS" instead of the old single-issue messages.

  4. Other changes

  - check_has_vmm called early in Phase 2 (for PBRSB VMM-awareness)
  - explain_hypervisor variable removed - its advice is now folded into the per-path explain calls
  - Offline mode gains eIBRS/AutoIBRS detection via cap_ibrs_all/cap_autoibrs
  - smt_enabled variable added (via is_cpu_smt_enabled) for cross-thread checks
2026-04-01 21:12:23 +02:00
Stéphane Lesimple
e09d0cf221 enh: check_cpu: look for cap_stibp and cap_autoibrs 2026-04-01 21:12:23 +02:00
Stéphane Lesimple
b062fe2184 enh: CVE-2017-5715: inventory of all sysfs strings, fix --sysfs-only path 2026-04-01 21:12:23 +02:00
Stéphane Lesimple
dfe48d67ce enh: CVE-2018-3646: document all sysfs variations, fix --sysfs-only path 2026-04-01 21:12:23 +02:00
Stéphane Lesimple
35d83e19a8 fix: --sysfs-only path for CVE-2018-12207 CVE-2018-3620 2026-04-01 21:12:23 +02:00
Stéphane Lesimple
123ad1c8e6 CVE-2023-20569: detect old kernels sysfs saying mitigations are correct whereas they are not 2026-04-01 21:12:23 +02:00
Stéphane Lesimple
b9e7f7cb8a docs: update development guidelines 2026-04-01 21:12:23 +02:00
Stéphane Lesimple
278989d550 fix: cap_rdcl_no, cap_gds_no, cap_tsa_*_no were not setting the current CPU status as immune for their respective vulns 2026-04-01 00:47:41 +02:00
Stéphane Lesimple
b4f4d11106 fix: CVE-2018-3620: false 'VULN' status on kernels reporting CPU as unaffected and RDCL_NO can't be parsed 2026-04-01 00:41:32 +02:00
Stéphane Lesimple
4738e8f0ad enh: draft rework of CVE-2017-5753 aka spectre v1 2026-04-01 00:22:07 +02:00
Stéphane Lesimple
b32f05b8d2 chore: readme: add a second table one about impact/mitigation, rework sections 2026-04-01 00:21:35 +02:00
Stéphane Lesimple
295324a545 chore: prepare for dev-build renaming to test-build 2026-03-31 19:49:39 +02:00
Stéphane Lesimple
efa07e7fd9 chore: set VERSION when building 2026-03-31 00:18:09 +02:00
Stéphane Lesimple
eabddf3d72 update dev docs and refactor CVE list in readme 2026-03-30 23:35:48 +02:00
Stéphane Lesimple
04221cf8c8 chore: add .gitignore 2026-03-30 23:07:59 +02:00
Stéphane Lesimple
a0032a44ef chore: adjust workflow for dev-build 2026-03-30 23:07:59 +02:00
Stéphane Lesimple
6eb70ab52d chore: move dist files to the dist/ subdir 2026-03-30 23:07:59 +02:00
Stéphane Lesimple
05e09bb7f4 feat: implement CVE-2024-36350 CVE-2024-36357 (Transient Scheduler Attack) 2026-03-30 23:07:59 +02:00
Stéphane Lesimple
5a0c391b06 doc: update development guidelines 2026-03-30 23:07:59 +02:00
Stéphane Lesimple
ebc9e91d78 chore: shfmt 2026-03-30 23:07:59 +02:00
Stéphane Lesimple
c2542e9940 dev-build workflow 2026-03-30 23:07:59 +02:00
Stéphane Lesimple
994608a90a use MSR names for read_msr for readability 2026-03-30 21:01:13 +02:00
Stéphane Lesimple
3d6acc460e fix: rework read_msr for values > INT32_MAX (#507) 2026-03-30 20:53:13 +02:00
Stéphane Lesimple
72824deea5 doc: add a note about the mandatory POSIX compliance of used tools 2026-03-30 20:48:10 +02:00
Stéphane Lesimple
a7cf525b6e POSIX compatibility fix: replace sort -V by a manual comparison 2026-03-30 20:39:05 +02:00
Stéphane Lesimple
70d531ba09 BSD compatibility fix: stat -f and date -r fallbacks 2026-03-30 20:30:29 +02:00
Stéphane Lesimple
cd79597e9a POSIX compatibility fix: sed -r => sed -E 2026-03-30 20:24:04 +02:00
Stéphane Lesimple
b8477d0e4d POSIX compatibility fix: cut -w => awk 2026-03-30 20:15:21 +02:00
Stéphane Lesimple
cebda01d05 split script in multiple files, reassembled through build.sh 2026-03-30 20:04:16 +02:00
Stéphane Lesimple
7e660812e9 standardize function naming and add doc headers to all of them 2026-03-30 19:55:15 +02:00
Stéphane Lesimple
45b26322c4 refactor functions that record/output results 2026-03-30 19:40:26 +02:00
Stéphane Lesimple
a74111bfcd use global readonly vars for common paths/basedirs 2026-03-30 19:31:22 +02:00
Stéphane Lesimple
5a3362a7ed factorize/standardize check_CVE_*() funcs 2026-03-30 19:22:57 +02:00
Stéphane Lesimple
76a6d476ae factorize CVE metadata into a single CVE_REGISTRY global var 2026-03-30 19:15:10 +02:00
Stéphane Lesimple
80a31d25cc second vars renaming pass 2026-03-30 07:13:45 +00:00
Stéphane Lesimple
34c7b221f0 chore: rename status_* to affected_* 2026-03-30 00:28:14 +00:00
Stéphane Lesimple
2029fe10ef chore: apply variables naming convention 2026-03-30 00:25:27 +00:00
Stéphane Lesimple
c34517dc99 chore: add variables naming convention documentation 2026-03-30 00:09:24 +00:00
speed47
61cc0f3a35 update: fwdb from v347+i20251110+615b to v349+i20260227+615b, 50 microcode changes 2026-03-28 01:52:17 +00:00
Stéphane Lesimple
a20641fbad fix: handle non-numeric ARM CPU architecture values
Some old ARM processors (e.g., ARM926EJ-S) report CPU architecture
with suffix in /proc/cpuinfo (e.g., "5TEJ" for ARMv5TEJ).

This caused an "integer expression expected" error when comparing
against numeric values. Extract the numeric prefix before integer comparisons.

Fixes #505.
2026-01-25 12:57:41 +01:00
Stéphane Lesimple
d550ea8c85 fix: harmless 'dmesg: write error' that could happen on some systems
Fixes #519.
2026-01-25 11:53:13 +01:00
Stéphane Lesimple
8e33a1dbf2 fix: set cpu_* vars to a default value
On ARM64 systems, /proc/cpuinfo uses different field names (CPU implementer,
CPU variant, CPU part, CPU revision) instead of x86-style fields (cpu family,
model, stepping). This left these variables empty, causing printf to fail
with 'invalid number' errors when formatting them as hex values.

Fixes #520.
2026-01-25 11:38:50 +01:00
speed47
68b4617fd4 update: fwdb from v345+i20251110+4df2 to v347+i20251110+615b, 2 microcode changes 2026-01-01 11:48:36 +01:00
speed47
9fed5ceb33 update: fwdb from v344+i20250811+1523 to v345+i20251110+4df2, 45 microcode changes 2025-11-23 12:38:27 +01:00
Stéphane Lesimple
72bce72fe8 chore: really fix autoupdate workflow to avoid useless PRs 2025-10-31 19:53:59 +01:00
Stéphane Lesimple
5f18e67f6f chore: fix autoupdate workflow 2025-10-30 23:57:05 +01:00
Gabriel Francisco
a8466b74fe fix CVE-2017-5715 reporting when IBRS_FW is enabled 2025-10-27 08:42:51 +01:00
speed47
b99be2363c update: fwdb from v296+i20240514+988c to v344+i20250811+1523, 128 microcode changes 2025-10-26 22:08:07 +01:00
Stéphane Lesimple
ee4cfd00b8 chore: add autoupdate workflow for fwdb 2025-10-25 20:48:38 +02:00
Stéphane Lesimple
c2c60e0161 chore: fix recent shellcheck warnings 2025-10-25 20:48:38 +02:00
Jörg Sommer
bae43d8370 Replace head -1 by head -n1
The info page of GNU head says:

> For compatibility 'head' also supports an obsolete option syntax
> '-[NUM][bkm][cqv]', [...] Scripts intended for standard hosts should use
> '-c NUM' or '-n NUM' instead.

At least busybox's head does not support the `-NUM` syntax.
2025-10-25 20:45:24 +02:00
Stéphane Lesimple
34c6095912 fix: Linux 6.9+ changed some config options names (#490)
Issue #490 is about retpoline but other options have also changed,
as reported by a comment on the issue, this commit fixes these
other options:

Breno Leitao (10):
      x86/bugs: Rename CONFIG_GDS_FORCE_MITIGATION => CONFIG_MITIGATION_GDS_FORCE
      x86/bugs: Rename CONFIG_CPU_IBPB_ENTRY       => CONFIG_MITIGATION_IBPB_ENTRY
      x86/bugs: Rename CONFIG_CALL_DEPTH_TRACKING  => CONFIG_MITIGATION_CALL_DEPTH_TRACKING
      x86/bugs: Rename CONFIG_PAGE_TABLE_ISOLATION => CONFIG_MITIGATION_PAGE_TABLE_ISOLATION
      x86/bugs: Rename CONFIG_RETPOLINE            => CONFIG_MITIGATION_RETPOLINE
      x86/bugs: Rename CONFIG_SLS                  => CONFIG_MITIGATION_SLS
      x86/bugs: Rename CONFIG_CPU_UNRET_ENTRY      => CONFIG_MITIGATION_UNRET_ENTRY
      x86/bugs: Rename CONFIG_CPU_IBRS_ENTRY       => CONFIG_MITIGATION_IBRS_ENTRY
      x86/bugs: Rename CONFIG_CPU_SRSO             => CONFIG_MITIGATION_SRSO
      x86/bugs: Rename CONFIG_RETHUNK              => CONFIG_MITIGATION_RETHUNK
2024-08-04 15:15:45 +02:00
Stéphane Lesimple
e806e4bc41 chore: docker compose v2
The `docker-compose` command has been replaced by `docker compose`.
The "version" tag has also been deprecated in docker-compose.yml.
2024-08-04 13:53:36 +02:00
Ivan Zahariev
388d44edbd Fix Retpoline detection for Linux 6.9+ (issue #490) 2024-08-04 13:41:01 +02:00
Stéphane Lesimple
bd0c7c94b5 fix: typo introduced by #483, fixes #486 2024-05-18 13:01:48 +02:00
Stéphane Lesimple
d70e4c2974 fwdb: update to v296+i20240514+988c 2024-05-18 13:01:48 +02:00
Stéphane Lesimple
4e29fb5a21 fix: ucode_platformid_mask is hexa (fixes #485) 2024-02-15 17:27:12 +01:00
Stephane Lesimple
0f2edb1a71 feat: blacklist some more microcodes (fixes #475) 2024-01-09 18:54:39 +01:00
Stephane Lesimple
8ac2539a2a fix: microcode check now supports pf_mask (fixes #482) 2024-01-09 17:05:18 +01:00
Stéphane Lesimple
97f4d5f2bc feat(reptar): add detection and mitigation of Reptar 2024-01-09 15:38:16 +01:00
Stéphane Lesimple
9b7b09ada3 fix(inception): continued mitigation detection 2023-08-25 18:50:53 +02:00
Sébastien Mériot
c94811e63d fix(inception): Zen1/2 results based on kernel mitigations 2023-08-25 18:50:53 +02:00
Sébastien Mériot
3e67047c73 feat(inception): README 2023-08-25 18:50:53 +02:00
Sébastien Mériot
ecee75716e feat(inception): kernel checks + sbpb support detection 2023-08-25 18:50:53 +02:00
Sébastien Mériot
fb6933dc64 feat(inception): Zen1/2 IBPB and SMT checks 2023-08-25 18:50:53 +02:00
Stéphane Lesimple
dc6921a1ac feat(inception): handle sysfs interface 2023-08-25 18:50:53 +02:00
Sébastien Mériot
3167762cfd feat(inception): start supporting AMD inception 2023-08-25 18:50:53 +02:00
Stéphane Lesimple
44223c5308 fix: bsd: kernel version detection 2023-08-11 18:41:35 +02:00
Stéphane Lesimple
dbe208fc48 enh: downfall: detect kernel mitigation without sysfs 2023-08-11 18:10:27 +02:00
Stéphane Lesimple
aca4e2a9b1 enh: move root warning to the bottom 2023-08-11 18:10:27 +02:00
Sébastien Mériot
c1c1ac4dbb feat(downfall): detection of the kernel mitigation relying on dmesg 2023-08-10 11:14:40 +02:00
Stéphane Lesimple
ba0daa6769 feat: downfall: add kernel soft mitigation support check 2023-08-10 11:14:40 +02:00
Sébastien Mériot
227c0aab1e feat(downfall): add downfall checks 2023-08-10 11:14:40 +02:00
Stéphane Lesimple
8ba3751cf7 fwdb: update to latest Intel ucode versions 2023-08-09 10:35:08 +02:00
Stéphane Lesimple
d013c0a7d2 doc: add kernel src as additional ucode version source 2023-08-01 10:22:15 +02:00
Stéphane Lesimple
cbe8ba10ce fix: inteldb: cpuid 0x00090660 and 0x000A0680 2023-07-30 13:21:38 +02:00
Stéphane Lesimple
9c2587bca5 enh: when CPUID can't be read, built it by ourselves 2023-07-30 12:21:12 +02:00
Stéphane Lesimple
2a5ddc87bf feat: add Intel known affected processors DB 2023-07-30 12:21:12 +02:00
Stéphane Lesimple
2ef6c1c80e enh: factorize file download func 2023-07-28 20:03:16 +02:00
Stéphane Lesimple
3c224018f4 chore: update disclaimer and FAQ 2023-07-28 20:03:16 +02:00
Stéphane Lesimple
b8f8c81d51 release v0.46 2023-07-26 18:07:02 +02:00
Stéphane Lesimple
f34dd5fa7b enh: assume CPU is immune to Zenbleed regardless of vendor except AMD
This contradicts our usual "if we don't know, consider vulnerable" motto,
but as this vuln is extremely specific (which is not the case for the Spectre
range of vulnerabilities, for example), this is the correct approach here.
2023-07-26 17:54:44 +02:00
Stéphane Lesimple
c0869d7341 enh: zenbleed: give a manual mitigation in --explain 2023-07-26 16:38:02 +02:00
Stéphane Lesimple
e99a548dcc fix: fms2cpuid was incorrect for families > 0xF 2023-07-26 14:33:11 +02:00
Stéphane Lesimple
3d475dfaec feat: fwdb: add linux-firmware as AMD source, update fwdb accordingly 2023-07-26 13:57:05 +02:00
Stéphane Lesimple
cba5010c2a chore: fix typo 2023-07-26 13:57:05 +02:00
Stéphane Lesimple
c5661f098f enh: add --explain text for Zenbleed 2023-07-26 10:56:45 +02:00
Stéphane Lesimple
6844c01242 enh: add zenbleed support to the --variant option 2023-07-26 10:46:38 +02:00
ShadowCurse
0811f28ac6 fix: arm is not affected by zenbleed 2023-07-25 19:59:59 +02:00
Stéphane Lesimple
9bb79a18eb feat: add Zenbleed (CVE-2023-20593) and update fwdb to v270+i20230614 2023-07-25 17:54:59 +02:00
George Cherian
0d93c6ffb4 feat: arm: add Neoverse-N2 and Neoverse-V2
Signed-off-by: George Cherian <george.cherian@marvell.com>
2023-06-18 12:19:02 +02:00
Stéphane Lesimple
6a61df200e update: fwdb to v266+i20230512 2023-05-13 10:27:03 +02:00
ShadowCurse
e4b313fe79 feat: arm: add Neoverse-V1 2023-04-22 11:17:06 +02:00
Stéphane Lesimple
a2843575be fix: docker: adding missing utils (fixes #433) 2023-02-24 21:35:55 +01:00
Hilton Chain
60c71ccb7a Add support for Guix System kernel. 2023-02-24 20:58:45 +01:00
Stéphane Lesimple
48abeb5950 fix: bad exitcode with --update-fwdb due to trap exit 2023-02-24 20:57:43 +01:00
Stéphane Lesimple
3c988cc73a fix: rewrite SQL to be sqlite3 >= 3.41 compatible
closes #443
2023-02-24 20:54:40 +01:00
glitsj16
bea5cfc3b8 Fix typo: /devnull file created in filesystem 2023-02-24 19:42:16 +01:00
Stéphane Lesimple
b68ebe67f2 fix: fwdb: ignore MCEdb versions where an official Intel version exists (fixes #430) 2022-03-30 09:10:55 +02:00
Stéphane Lesimple
a6c943d38f release v0.45 2022-03-27 12:41:17 +02:00
Stéphane Lesimple
dd162301ff chore: update fwdb to v222+i20220208 2022-03-27 12:38:44 +02:00
Stéphane Lesimple
5f6471d9a4 feat: set default TMPDIR for Android (#415) 2022-03-27 12:31:05 +02:00
Stéphane Lesimple
2a5b965b98 feat: add --allow-msr-write, no longer write by default (#385), detect when writing is denied 2022-03-24 12:37:19 +01:00
Stéphane Lesimple
ee266d43b7 chore: fix indentation 2022-03-21 22:22:33 +01:00
Stéphane Lesimple
b61baa90df feat: bsd: for unimplemented CVEs, at least report when CPU is not affected 2022-03-21 22:22:33 +01:00
Stéphane Lesimple
a98d92f8bc chore: wording: model not vulnerable -> model not affected 2022-03-21 22:22:33 +01:00
Stéphane Lesimple
b7c8c4115a feat: implement detection for MCEPSC under BSD 2022-03-21 22:22:33 +01:00
Stéphane Lesimple
4e7c52767d chore: update Intel Family 6 models 2022-03-21 22:22:33 +01:00
Stéphane Lesimple
8473d9ba6b chore: ensure vars are set before being dereferenced (set -u compat) 2022-03-21 22:22:33 +01:00
Stéphane Lesimple
0af4830224 fix: is_ucode_blacklisted: fix some model names 2022-03-21 22:22:33 +01:00
Stéphane Lesimple
81a4329d71 feat: add --cpu, apply changes to (read|write)_msr, update fwdb to v221+i20220208 2022-03-21 22:22:33 +01:00
Stéphane Lesimple
3679776f3c chore: only attempt to load msr and cpuid module once 2022-03-21 22:22:33 +01:00
Stéphane Lesimple
ba131fcd2f chore: read_cpuid: use named constants 2022-03-21 22:22:33 +01:00
Stéphane Lesimple
ae6bc31c2c feat: hw check: add IPRED, RRSBA, BHI features check 2022-03-21 22:22:33 +01:00
Stéphane Lesimple
6d7a6b3666 feat: add subleaf != 0 support for read_cpuid 2022-03-21 22:22:33 +01:00
Stéphane Lesimple
16f2160be5 chore: fwdb: update to v220+i20220208 2022-03-17 19:39:39 +01:00
Aditya-Tolikar
7cad9301b3 typo
'A' is more 'X' *than 'B'.
Previously: 'A' is more 'X' that 'B'.
2022-03-17 19:26:12 +01:00
Stéphane Lesimple
580549812a fix: retpoline: detection on 5.15.28+ (#420) 2022-03-17 19:25:24 +01:00
Stéphane Lesimple
a485c7882a doc: readme: make the FAQ entry more visible 2021-05-25 13:22:54 +02:00
Stéphane Lesimple
7d13f7a0ef doc: add an FAQ entry about CVE support 2021-05-25 13:17:03 +02:00
Stéphane Lesimple
226b2375ab chore: speculative execution -> transient execution 2021-05-25 12:39:51 +02:00
Stéphane Lesimple
052a3e66d1 doc: more FAQ and README 2021-05-25 12:31:30 +02:00
Stéphane Lesimple
05d862709d fix: has_vmm false positive with pcp
Fix by matching the full procname with pgrep (-x),
so that the 'pmdakvm' process doesn't match.

Closes #394
2021-05-25 12:31:07 +02:00
Stéphane Lesimple
3846913899 fix: refuse to run under MacOS and ESXi 2021-05-24 22:42:23 +02:00
Stéphane Lesimple
a87ace1f98 doc: add an FAQ.md and update the README.md accordingly 2021-05-24 22:27:46 +02:00
Stéphane Lesimple
0ba71a443e fix: mcedb: v191 changed the MCE table format
Also update the builtin db to v191+i20210217

Closes #400
2021-05-24 12:55:44 +02:00
Stéphane Lesimple
3a486e9985 arm64: variant 4: detect ssbd mitigation from kernel img, system.map or kconfig 2021-04-02 15:38:31 +02:00
Stéphane Lesimple
23564cda5d fix: variant4: added case where prctl ssbd status is tagged as 'unknown' 2021-04-02 15:38:31 +02:00
Stéphane Lesimple
0ea21d09bd fix: extract_kernel: don't overwrite kernel_err if already set
Fixes #395
2021-04-02 15:33:02 +02:00
Stéphane Lesimple
08e30e156d chore: readme: framapic is gone, host the screenshots on GitHub 2021-02-22 21:22:11 +01:00
Zhiyuan Dai
6d35e780f4 arm64: phytium: Add CPU Implementer Phytium
This patch adds 0x70 check for phytium implementer id in function
parse_cpu_details. Also adds that Phytium Soc is not vulnerable to variant 3/3a
2021-01-13 19:14:09 +01:00
Stéphane Lesimple
4ec3154be0 chore: replace 'Vulnerable to' by 'Affected by' in the hw section
This seems to be less confusing, suggested by #356
2020-11-10 18:56:25 +01:00
Stéphane Lesimple
843f26630d feat: arm: add Cortex A77 and Neoverse-N1 (fixes #371) 2020-11-10 18:36:42 +01:00
Stéphane Lesimple
7fc2ec65b9 bump to v0.44 2020-11-09 18:41:43 +01:00
Stéphane Lesimple
c8cdfd54da chore: fwdb: update to v165.20201021+i20200616 2020-11-08 21:25:18 +01:00
Stéphane Lesimple
f0c33c7a32 fix: fwdb: use the commit date as the intel fwdb version
fixes #379
2020-11-08 21:25:18 +01:00
Stéphane Lesimple
9e874397da chore: fwdb: update to v163.20200930+i20200904 2020-10-05 20:06:49 +02:00
Stéphane Lesimple
76cb73f3cb fix: fwdb: update Intel's repository URL 2020-10-05 20:06:49 +02:00
Stéphane Lesimple
90f23d286e chore: update fwdb to v160.20200912+i20200722 2020-09-14 21:45:09 +02:00
Stéphane Lesimple
e41e311a7f feat: add zstd kernel decompression (#370) 2020-09-14 21:42:55 +02:00
Stéphane Lesimple
1f75f01630 fwdb: update MCEdb to v148 & Intel firmwares to 2020-04-27 2020-06-13 18:11:12 +02:00
Stéphane Lesimple
14a53b19da chore: add CVE to the README 2020-06-10 00:07:14 +02:00
Stéphane Lesimple
d8f0ddd7a5 chore: fix indentation 2020-06-10 00:07:14 +02:00
Agata Gruza
62d3448a54 Added support for SRBDS related vulnerabilities 2020-06-10 00:07:14 +02:00
Stéphane Lesimple
cb6d139629 chore: tests: now expect 15 CVEs instead of 14 (fix) 2020-06-09 22:56:25 +02:00
Stéphane Lesimple
7e2db09ed9 chore: tests: now expect 15 CVEs instead of 14 2020-06-09 22:51:50 +02:00
Stéphane Lesimple
33cf1cde79 enh: arm: add experimental support for binary arm images 2020-06-06 17:29:32 +02:00
Stéphane Lesimple
4a3006e196 fix: arm64: cve-2017-5753: kernels 4.19+ use a different nospec macro 2020-06-06 17:29:32 +02:00
Stéphane Lesimple
36f98eff95 fwdb: update MCEdb to v147 & Intel firmwares to 2020-04-27 2020-05-31 13:03:58 +02:00
xaitax
fa7b8f9567 Typo 2020-05-08 16:17:09 +02:00
Stéphane Lesimple
3beefc2587 enh: rsb filling: no longer need the 'strings' tool to check for kernel support in live mode 2020-03-10 22:29:54 +01:00
Stéphane Lesimple
27c36fdb80 fwdb: update to v135.20200303+i20200205 2020-03-10 22:29:39 +01:00
Matt Christian
3d21dae168 Fixes for FreeBSD to parse CPU info. 2020-02-06 19:56:35 +01:00
Stéphane Lesimple
7d2a510146 chore: update fwdb to v132.20200108+i20191124 2020-02-01 18:58:25 +01:00
Stéphane Lesimple
a1a35c9b35 chore: github: add check run on pull requests 2020-01-10 13:19:36 +01:00
Stéphane Lesimple
eec77e1ab9 fix: fwdb update: remove Intel extract tempdir on exit 2019-12-10 20:21:52 +01:00
Stéphane Lesimple
5633d374de fix: has_vmm: ignore kernel threads when looking for a hypervisor (fixes #278) 2019-12-10 19:10:45 +01:00
Stéphane Lesimple
a343bccb49 bump to v0.43 2019-12-08 15:37:17 +01:00
Stéphane Lesimple
1f604c119b fix var typo 2019-12-08 15:25:54 +01:00
Stéphane Lesimple
bfed3187a6 fix: variant3a: Silvermont CPUs are not vulnerable to variant 3a 2019-12-08 14:39:31 +01:00
Stéphane Lesimple
0cd7e1164f feat: detect vanilla 5.4+ locked down mode 2019-12-06 23:03:36 +01:00
Stéphane Lesimple
71129d6b48 fix: tsx: rtm feature bit is in EBX(11) 2019-12-02 19:07:10 +01:00
Stéphane Lesimple
6e799e8b01 fix: mcepsc: fix logic error on non-speculative CPUs that prevented detection of MCEPSC immunity 2019-11-25 23:03:04 +01:00
Stéphane Lesimple
4993b04922 fix: taa: CPUs having TAA_NO bit set are not vulnerable 2019-11-25 21:14:54 +01:00
Stéphane Lesimple
4fc2afe1bc feat: add TSX_CTRL MSR detection in hardware info 2019-11-25 20:58:49 +01:00
Stéphane Lesimple
bd47275501 feat: add detection of iTLB Multihit vuln/mitigation (CVE-2018-12207) 2019-11-25 19:13:09 +01:00
Stéphane Lesimple
8ddf6b2d6d enh: replace shell wildcard by a find to avoid potiental error (list of args too long) 2019-11-24 17:26:13 +01:00
Stéphane Lesimple
16b6490ffc chore: avoid ${var:-]} syntax, badly confusing vim's syntax highlighter 2019-11-24 17:26:13 +01:00
Stéphane Lesimple
18df38fae6 fix: sgx: on locked down kernels, fallback to CPUID bit for detection
on locked down kernels (Fedora / Red Hat feature that prevents writing
to MSRs from userspace, even if root), we can't write to FLUSH_CMD MSR
to verify that it's present. So fallback to checking the existence of
the L1D flush CPUID feature bit to infer that the microcode has been
updated in a recent enough version that also mitigates SGX (fixes for
both issues have been included in the same microcode updates for all
Intel CPUs)
2019-11-24 17:26:01 +01:00
Stéphane Lesimple
a306757c22 fix: detect Red Hat locked down kernels (impacts MSR writes) 2019-11-24 17:26:01 +01:00
Stéphane Lesimple
e01f97ee75 fix: fwdb: don't use local db if it's older than our builtin version 2019-11-24 17:25:41 +01:00
Stéphane Lesimple
fa7f814f4f chore: rename mcedb cmdline parameters to fwdb 2019-11-24 17:25:41 +01:00
Stéphane Lesimple
bb32a16a86 update fwdb to v130.20191104+i20191027 2019-11-24 17:25:41 +01:00
Stéphane Lesimple
8c84c0ba17 enh: fwdb: use both Intel GitHub repo and MCEdb to build our database 2019-11-24 17:25:41 +01:00
Stéphane Lesimple
6abe1bc62b enh: kernel decompression: better tolerance over missing tools
fixes #297
2019-11-23 16:43:00 +01:00
Stéphane Lesimple
5ca7fe91ff fix: pteinv: don't check kernel image if not available 2019-11-23 14:01:56 +01:00
Stéphane Lesimple
4ba68fba74 fix: silence useless error from grep (fixes #322) 2019-11-23 13:51:00 +01:00
Stéphane Lesimple
59ad312773 fix: msr: fix msr module detection under Ubuntu 19.10 (fixes #316) 2019-11-19 22:35:08 +01:00
Stéphane Lesimple
418533c47e chore: remove LICENSE file, SPDX id is enough 2019-11-18 11:28:20 -08:00
Stéphane Lesimple
3e757b6177 chore: add github check workflow 2019-11-18 11:28:20 -08:00
Stéphane Lesimple
f724f94085 enh: kernel: autodetect customized arch kernels from cmdline 2019-11-17 13:36:52 -08:00
Stéphane Lesimple
dcf540888d enh: mock: implement reading from /proc/cmdline 2019-11-17 13:36:52 -08:00
Stéphane Lesimple
9911c243b2 feat: use --live with --kernel/--config/--map to override file detection in live mode 2019-11-17 13:36:52 -08:00
Stéphane Lesimple
cb279a49ec enh(taa): more complete version 2019-11-13 01:07:10 +01:00
Stéphane Lesimple
c100ce4c0d mcedb: update from v112 to v130 2019-11-12 21:19:03 +01:00
Stéphane Lesimple
4741b06160 fix: batch mode for TAA 2019-11-12 21:16:21 +01:00
Stéphane Lesimple
e0a1c2ec77 fix shellcheck warnings 2019-11-12 20:06:12 +01:00
Agata Gruza
c18b88d745 Fixing typo 2019-11-12 19:40:47 +01:00
Agata Gruza
d623524342 Added support for TAA related vulnerabilities 2019-11-12 19:40:47 +01:00
Stéphane Lesimple
f5ec320fe5 enh: rework the vuln logic of MDS with --paranoid (fixes #307) 2019-09-22 04:02:33 +02:00
Stéphane Lesimple
cc224c0522 fix: mocking value for read_msr
we were returning the mocking value before actually setting it.
also remove spaces around the returned value (no behavior change)
2019-09-22 01:38:18 +02:00
Corey Wright
0518604fe6 Use kernel_err to avoid misreporting missing Linux kernel image
When checking for CVE-2017-5715 (i.e. `check_CVE_2017_5715_linux()`),
if we can't inspect (with `readelf`) or decompress the Linux kernel
image, then we report there is no kernel image (i.e. `we need the
kernel image` or `kernel image missing`, respectively), which confuses
users when the associated file exists.

Instead use `kernel_err` to provide a correct and detailed description
of the problem (e.g. `missing '...' tool, please install it, usually
it's in the '...' package`), so the user can take the prescribed
action.
2019-09-22 01:09:58 +02:00
Erik Zettel
d57fecec91 spectre-meltdown-checker.sh: fix typos 2019-09-20 23:50:52 +02:00
Stéphane Lesimple
f835f4d07d Explain that Enhanced IBRS is better for performance than classic IBRS 2019-08-16 12:53:39 +02:00
Agata Gruza
482d6c200a Enhanced IBRS capabilities
There are two flavors of IBRS: plain and enhanced. This patch tells which flavor of IBRS is in use.
2019-08-16 12:53:39 +02:00
David Guglielmi
91d0699029 update MCEdb from v111 to v112 2019-06-03 22:49:03 +02:00
Stéphane Lesimple
fcc4ff4de2 update MCEdb from v110 to v111, bump to v0.42 2019-05-24 22:49:45 +02:00
Stéphane Lesimple
0bd38ddda0 enh: -v -v now implies --dump-mock-data 2019-05-24 11:36:39 +02:00
Stéphane Lesimple
e83dc818cd feat(mds): implement FreeBSD mitigation detection 2019-05-24 11:17:04 +02:00
Stéphane Lesimple
d69ea67101 feat(mock): add --dump-mock-data 2019-05-24 10:49:40 +02:00
Stéphane Lesimple
dfe0d10f2a fix(mds): remove useless display of MD_CLEAR info in non-hw section 2019-05-24 10:20:48 +02:00
Stéphane Lesimple
58a5acfdbb fix(bsd): read_msr returned data in an incorrect format 2019-05-24 09:33:56 +02:00
Stéphane Lesimple
ccb4dbef7c enh(mock): avoid reading the sysfs interface outside sys_interface_check() for higher mocking coverage 2019-05-24 09:28:18 +02:00
Stéphane Lesimple
afbb26277f feat(mock): add mocking functionality to help reproducing issues under specific CPUs 2019-05-24 09:28:18 +02:00
Stéphane Lesimple
77b34d48c6 fix(mds): check MDS_NO bit in is_cpu_mds_free() 2019-05-24 09:28:18 +02:00
Stéphane Lesimple
497efe6a82 fix(l1tf): RDCL_NO bit didn't take precedence for vulnerability check on some Intel CPUs 2019-05-24 09:28:18 +02:00
Stéphane Lesimple
62b46df4e7 fix(l1tf): remove libvirtd from hypervisor detection (#278) 2019-05-18 14:22:42 +02:00
Stéphane Lesimple
7d1f269bed fix(mds): AMD confirms they're not vulnerable 2019-05-16 11:31:28 +02:00
Erich Ritz
4f9ca803c8 Fix help text (#285)
* fix --help message

Commit 7b72c20f89 added help text for the
--cve switch, and the "can be specified multiple times" note got
associated with the --cve switch instead of staying with the --variant
switch.  Restore the line to belong to the --variant switch help
message.

* Add new variants to error message

Commit 8e870db4f5 added new variants but
did not add them to the error message that listed the allowable
variants.  Add them now.
2019-05-15 19:34:51 +02:00
Stéphane Lesimple
5788cec18b fix(mds): ARM and CAVIUM are not thought to be vulnerable 2019-05-15 10:56:49 +02:00
Stéphane Lesimple
ae56ec0bc5 bump to v0.41 2019-05-15 09:57:28 +02:00
Stéphane Lesimple
871443c9db fix typos in README 2019-05-15 00:28:55 +02:00
Stéphane Lesimple
8fd4e3ab01 fix(xen): remove xenbus and xenwatch as they also exist in domU 2019-05-15 00:23:05 +02:00
Stéphane Lesimple
de793a7204 feat(mds): more verbose info about kernel support and microcode support for mitigation 2019-05-15 00:21:08 +02:00
Stéphane Lesimple
11790027d3 feat(mds): add alias ZombieLoad for CVE-2018-12130 2019-05-14 21:42:36 +02:00
Stéphane Lesimple
5939c38c5c update mcedb from v109 to v110 to better detect MDS microcodes 2019-05-14 20:31:27 +02:00
Stéphane Lesimple
db7d3206fd feat(mds): add detection of availability of MD_CLEAR instruction 2019-05-14 20:30:47 +02:00
Stéphane Lesimple
1d13a423b8 adjust README 2019-05-14 20:16:01 +02:00
Agata Gruza
8e870db4f5 Added support for MDS related vulnerabilities (#282) 2019-05-14 19:21:20 +02:00
Stéphane Lesimple
d547ce4ab4 fix(ssb): fix error when no process uses prctl to set ssb mitigation
fixes #281
2019-05-13 15:35:58 +02:00
Stéphane Lesimple
d187827841 enh(vmm): add Xen daemons detection 2019-05-08 20:44:54 +02:00
Hans-Joachim Kliemeck
2e304ec617 enh(xen): improvements for xen systems (#270)
* add mitigation detection for l1tf for xen based systems
* add information for hardware mitigation
* add xen support for meltdown
2019-05-07 20:35:52 +02:00
Stéphane Lesimple
fcc04437e8 update builtin MCEdb from v96 to v109 2019-05-07 20:29:59 +02:00
Stéphane Lesimple
d31a9810e6 enhance previous commit logic 2019-05-05 20:09:53 +02:00
Stéphane Lesimple
4edb867def fix(vmm): revert to checking the running processes to detect a hypervisor
More information available on #278
2019-05-05 20:04:25 +02:00
Stéphane Lesimple
1264b1c7a3 chore: more shellcheck 0.6 fixes 2019-05-05 18:34:09 +02:00
Stéphane Lesimple
7beca1ac50 fix: invalid names in json batch mode (fixes #279) 2019-05-05 18:15:41 +02:00
David
8ad10e15d3 chore: Comply with Shellcheck SC2209 (#280) 2019-05-05 17:31:18 +02:00
Stéphane Lesimple
bfa4de96e6 enh(l1tf): in paranoid mode, assume we're running a hypervisor unless stated otherwise
This change ensures we check for SMT and advise the user to disable it for maximum security.
Doing this, we'll help users mitigate a whole range of vulnerabilities taking advantage of SMT to attack purely from userland other userland processes, as seen in CVE-2018-5407 (also see #261)
2019-04-21 14:05:43 +02:00
Stéphane Lesimple
b022b27a51 feat(ssbd): in live mode, report whether the mitigation is active (fix #210) 2019-04-20 20:27:45 +02:00
Dario Faggioli
c4bae6ee6a IBRS kernel reported active even if sysfs has "IBRS_FW" only (#275) (#276)
On a (pre-SkyLake) system, where /sys/.../vulnerabilities/spectre_v2 is
"Mitigation: Full generic retpoline, IBPB: conditional, IBRS_FW, RSB filling"

the tool, incorrectly, reports, a couple of lines above:
* IBRS enabled and active:  YES  (for kernel and firmware code)

Use '\<IBRS\>', as suggested by @jirislaby, in upstream issue #275
(https://github.com/speed47/spectre-meltdown-checker/issues/275) when
checking whether IBRS is enabled/active for the kernel.

With that, the output becomes:
* IBRS enabled and active:  YES  (for firmware code only)

which is actually the case.

I double checked that, if the same kernel is used on a post-SkyLake
hardware, which on openSUSE uses IBRS as, even with this change, the
tool (this time correctly) reports:
* IBRS enabled and active:  YES  (for kernel and firmware code)
2019-04-20 14:04:29 +02:00
Stéphane Lesimple
23e7db044e fix(bsd): load vmm if not already loaded, fixes #274
As we read sysctl values under the vmm hierarchy, the modules needs to be loaded,
so if not already done, we load it before testing for CVE-2018-3620 and CVE-2018-3646
2019-04-19 19:47:04 +02:00
Stéphane Lesimple
fc4981bb94 update MCEDB from v84 to v96 2019-01-20 19:52:46 +01:00
Dajiang Zhong
419508758e add spectre and meltdown mitigation technologies checking for Hygon CPU (#271)
* add spectre and meltdown mitigation technologies checking for Hygon CPU

* update microarhitecture name for Hygon CPU family 24 with moksha
2019-01-20 19:32:36 +01:00
Stéphane Lesimple
d7d2e6934b fix: typo in bare metal detection (fixes #269) 2018-12-12 00:24:17 +01:00
Jan
b0083d918e Remove unneeded volumes in Dockerfile (#266) 2018-12-10 19:42:13 +01:00
Lily Wilson
904a83c675 Fix Arch kernel image detection (#268)
currently, the script tries to use the wrong kernel image on Arch if an
alternative kernel (hardened, zen, or lts) is in use. Fortunately, all
the Arch kernel packages place a symlink to the kernel image as /usr/lib/modules/$(uname -r)/vmlinuz, so simply removing the guess for Arch fixes the issue.
2018-12-10 19:36:58 +01:00
Rob Gill
906f54cf9d Improved hypervisor detection (#259)
* Code consistency

``` opt_batch_format="text" ``` replaced by ``` opt_batch_format='text' ```
```nrpe_vuln='"" ``` replaced by ``` nrpe_vuln='' ``` , as used by other parse options

Redundant ``` ! -z ``` replaced by ``` -n ```, as used elsewhere

Signed-off-by: Rob Gill <rrobgill@protonmail.com>

* Improved hypervisor detection

Tests for presence of hypervisor flag in /proc/cpuino
Tests for evidence of hypervisor in dmesg

Signed-off-by: Rob Gill <rrobgill@protonmail.com>

* formatting fix

Signed-off-by: Rob Gill <rrobgill@protonmail.com>

* Set $l1d_mode to -1 in cases where cpu/vulnerabilities/l1tf is not available

(prevents invalid number error when evaluating [ "$l1d_mode" -ge 1 ])

Signed-off-by: Rob Gill <rrobgill@protonmail.com>

* Update Intel Atom 6 cpu names to align with kernel

Update processor names of atom 6 family processors to align with those from kernel as of October 2018.
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/arch/x86/include/asm/intel-family.h?id=f2c4db1bd80720cd8cb2a5aa220d9bc9f374f04e
Update list of known immune processors from
https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/commit/arch/x86/kernel/cpu/common.c?id=f2c4db1bd80720cd8cb2a5aa220d9bc9f374f04e

* Fix unset $l1d_mode

Another instance of unset l1d_mode causing error "./spectre-meltdown-checker.sh: 3867: [: Illegal number:"

* chore: update readme with brief summary of L1tfs

L1tf mitigation and impact details from

https://www.kernel.org/doc/html/latest/admin-guide/l1tf.html and https://blogs.oracle.com/oraclesecurity/intel-l1tf

* typo
2018-12-10 19:33:07 +01:00
Brett T. Warden
c45a06f414 Warn on missing kernel info (#265)
Missing kernel information can cause all sorts of false positives or
negatives. This is worth at least a warning, and repeating immediately
following the status.
2018-11-25 18:37:03 +01:00
Brett T. Warden
4a6fa070a4 Fix misdetection of files under Clear Linux (#264) 2018-11-25 18:14:04 +01:00
Stéphane Lesimple
c705afe764 bump to v0.40 2018-10-03 20:56:46 +02:00
Stanislav Kholmanskikh
401ccd4b14 Correct aarch64 KPTI dmesg message
As it's seen in unmap_kernel_at_el0 (both the function definition
and its usage in arm64_features[]) from arch/arm64/kernel/cpufeature.c
the kernel reports this string:

CPU features: detected: Kernel page table isolation (KPTI)

or (before commit e0f6429dc1c0 ("arm64: cpufeature: Remove redundant "feature"
in reports")):

CPU features: detected feature: Kernel page table isolation (KPTI)

if KPTI is enabled on the system.

So on let's adjust check_variant3_linux() to make it grep these
strings if executed on an aarch64 platform.

Tested on a Cavium ThunderX2 machine.

Signed-off-by: Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com>
2018-10-03 20:49:55 +02:00
Stanislav Kholmanskikh
55120839dd Fix a typo in check_variant3_linux()
Signed-off-by: Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com>
2018-10-03 20:49:55 +02:00
Stéphane Lesimple
f5106b3c02 update MCEDB from v83 to v84 (no actual change) 2018-09-30 16:57:35 +02:00
Stéphane Lesimple
68289dae1e feat: add --update-builtin-mcedb to update the DB inside the script 2018-09-30 16:56:58 +02:00
Stéphane Lesimple
3b2d529654 feat(l1tf): read & report ARCH_CAPABILITIES bit 3 (SKIP_VMENTRY_L1DFLUSH) 2018-09-29 13:16:07 +02:00
Stéphane Lesimple
cbb18cb6b6 fix(l1tf): properly detect status under Red Hat/CentOS kernels 2018-09-29 13:01:13 +02:00
Stéphane Lesimple
299103a3ae some fixes when script is not started as root 2018-09-29 13:01:13 +02:00
Stéphane Lesimple
dc5402b349 chore: speed optimization of hw check and indentation fixes 2018-09-29 13:01:13 +02:00
Stéphane Lesimple
90c2ae5de2 feat: use the MCExtractor DB as the reference for the microcode versions
Use platomav's MCExtractor DB as the reference to decide whether our CPU microcode is the latest or not.
We have a builtin version of the DB in the script, but an updated version can be fetched and stored locally with --update-mcedb
2018-09-29 13:01:13 +02:00
Michael Lass
53d6a44754 Fix detection of CVE-2018-3615 (L1TF_SGX) (#253)
* Add another location of Arch Linux ARM kernel

* Fix detection of CVE-2018-3615

We change the value of variantl1tf in the line directly before so its
value will never be "immune". Instead we can directly use the value of
variantl1tf to initialize variantl1tf_sgx.
2018-09-29 11:35:10 +02:00
Stéphane Lesimple
297d890ce9 fix ucode version check regression introduced by fbbb19f under BSD 2018-09-23 15:00:39 +02:00
Stéphane Lesimple
0252e74f94 feat(bsd): implement CVE-2018-3620 and CVE-2018-3646 mitigation detection 2018-09-22 12:26:56 +02:00
Nicolas Sauzede
fbbb19f244 Fix cases where a CPU ucode version is not found in $procfs/cpuinfo. (#246)
* Fix cases where a CPU ucode version is not found in $procfs/cpuinfo.

When running whithin a virtual machine, it seems like $procfs/cpuinfo doesn't contain
a 'microcode' line, which triggers a script runtime error.
Fall back to '0x0' in this case, as other part of the script seems to already this
as a default value anyway.

* Double quote to prevent globbing and word splitting.
2018-09-19 22:00:59 +02:00
Stéphane Lesimple
1571a56ce2 feat: add L1D flush cpuid feature bit detection 2018-09-19 09:05:23 +02:00
Stéphane Lesimple
3cf9141601 fix: don't display summary if no CVE was tested (e.g. --hw-only) 2018-09-19 09:04:52 +02:00
Stéphane Lesimple
bff38f1b26 BSD: add not-implemented-yet notice for Foreshadow-NG 2018-09-18 22:06:01 +02:00
Stéphane Lesimple
b419fe7c63 feat(variant4): properly detect SSBD under BSD 2018-09-18 22:00:32 +02:00
alexvong1995
f193484a4a chore: fix deprecated SPDX license identifier (#249) (#251)
The SPDX license identifier 'GPL-3.0' has been deprecated according to
<https://spdx.org/licenses/GPL-3.0.html>.
2018-09-18 20:00:53 +02:00
Laszlo Toth
349d77b3b6 Fix kernel detection when /lib/kernel exists on a distro (#252)
Commit b48b2177b7 ("feat: Add Clear Linux Distro (#244)") broke kernel
detection for distros using that directory for other purposes than
storing the kernel image.

Example:
 # pacman -Qo /lib/kernel
/usr/lib/kernel/ is owned by mkinitcpio 24-2
/usr/lib/kernel/ is owned by systemd 239.2-1

Signed-off-by: Laszlo Toth <laszlth@gmail.com>
2018-09-18 20:00:20 +02:00
Stéphane Lesimple
e589ed7f02 fix: don't test SGX again in check_CVE_2018_3615, already done by is_cpu_vulnerable 2018-09-17 22:28:04 +02:00
Stéphane Lesimple
ae1206288f fix: remove some harcoded /proc paths, use $procfs instead 2018-09-17 22:26:20 +02:00
Stéphane Lesimple
b44d2b5470 chore: remove 'experimental' notice of Foreshadow from README 2018-09-17 21:48:20 +02:00
Stéphane Lesimple
7b72c20f89 feat(l1tf): explode L1TF in its 3 distinct CVEs 2018-09-17 21:44:48 +02:00
Luis Ponce
b48b2177b7 feat: Add Clear Linux Distro (#244)
Add path of Clear Linux kernel binary and kernel config file.
2018-09-15 15:51:49 +02:00
Pierre Gaxatte
8f31634df6 feat(batch): Add a batch short option for one line result (#243)
When using this script on a large amount a machine (via clustershell or
instance) it can be easier to have a very short result on one line
showing only the vulnerabilities
2018-09-15 15:45:10 +02:00
Luis Ponce
96798b1932 chore: add SPDX GPL-3.0 license identifier (#245)
The spectre-meltdown-checker.sh file is missing licensing information.
The SPDX identifier is a legally binding shorthand, which can be
used instead of the full boiler plate text.
2018-09-15 15:33:41 +02:00
Stéphane Lesimple
687ce1a7fa fix: load cpuid module if absent even when /dev/cpu/0/cpuid is there 2018-09-08 23:15:50 +02:00
Stéphane Lesimple
80e0db7cc4 fix: don't show erroneous ucode version when latest version is unknown (fixes #238) 2018-08-28 20:51:46 +02:00
David Guglielmi
e8890ffac6 feat(config): support for genkernel kernel config file (#239)
Add support for distributions using genkernel.
2018-08-28 20:24:37 +02:00
Stéphane Lesimple
b2f64e1132 fix README after merge 2018-08-18 12:09:34 +02:00
unrealization
42a3a61f1d Slightly improved Docker configuration (#230)
* Listed the required volumes in the Dockerfile.

* Added docker-compose.yml for convenience as users won't need to manually
specify volumes and stuff when running through docker-compose.

Adjusted README.md to reflect this change.
2018-08-18 12:06:16 +02:00
Karsten Weiss
afb36c519d Fix typo: 'RBS filling' => 'RSB filling' (#237) 2018-08-18 12:05:17 +02:00
Stéphane Lesimple
0009c0d473 fix: --batch now implies --no-color to avoid colored warnings 2018-08-18 12:04:18 +02:00
Stéphane Lesimple
dd67fd94d7 feat: add FLUSH_CMD MSR availability detection (part of L1TF mitigation) 2018-08-16 19:05:09 +02:00
Stéphane Lesimple
339ad31757 fix: add missing l1tf CPU vulnerability display in hw section 2018-08-16 15:19:29 +02:00
Stéphane Lesimple
794c5be1d2 feat: add optional git describe support to display inter-release version numbers 2018-08-16 15:18:47 +02:00
Stéphane Lesimple
a7afc585a9 fix several incorrect ucode version numbers 2018-08-16 10:51:55 +02:00
Stéphane Lesimple
fc1dffd09a feat: implement detection of latest known versions of intel microcodes 2018-08-15 12:53:49 +02:00
Stéphane Lesimple
e942616189 feat: initial support for L1TF 2018-08-15 12:05:08 +02:00
Stéphane Lesimple
360be7b35f fix: hide arch_capabilities_msr_not_read warning under !intel 2018-08-13 15:42:56 +02:00
Stéphane Lesimple
5f59257826 bump to v0.39 2018-08-13 15:33:03 +02:00
Stéphane Lesimple
92d59cbdc1 chore: adjust some comments, add 2 missing inits 2018-08-11 10:31:10 +02:00
Stéphane Lesimple
4747b932e7 feat: add detection of RSBA feature bit and adjust logic accordingly 2018-08-10 10:26:23 +02:00
Stéphane Lesimple
860023a806 fix: ARCH MSR was not read correctly, preventing proper SSB_NO and RDCL_NO detection 2018-08-10 10:26:23 +02:00
Stéphane Lesimple
ab67a9221d feat: read/write msr now supports msr-tools or perl as dd fallback 2018-08-10 10:26:23 +02:00
0x9fff00
f4592bf3a8 Add Arch armv5/armv7 kernel image location (#227) 2018-08-09 22:13:30 +02:00
Stéphane Lesimple
be15e47671 chore: setting master to v0.38+ 2018-08-09 14:25:22 +02:00
Nathan Parsons
d3481d9524 Add support for the kernel being within a btrfs subvolume (#226)
- /boot may be within a named root subvolume (eg. "/@/boot")
- /boot may be in its own subvolume (eg. "/@boot")
2018-08-09 14:00:35 +02:00
Stéphane Lesimple
21af561148 bump to v0.38 2018-08-07 10:55:50 +02:00
Stéphane Lesimple
cb740397f3 feat(arm32): add spectrev1 mitigation detection 2018-08-07 10:42:03 +02:00
Stéphane Lesimple
84195689af change: default to --no-explain, use --explain to get detailed mitigation help 2018-08-04 16:31:41 +02:00
Stéphane Lesimple
b637681fa8 fix: debug output: msg inaccuracy for ARM checks 2018-08-04 16:19:54 +02:00
Stéphane Lesimple
9316c30577 fix: armv8: models < 0xd07 are not vulnerable 2018-08-04 16:19:54 +02:00
Lily Wilson
f9dd9d8cb9 add guess for archlinuxarm aarch64 kernel image on raspberry pi 3 (#222) 2018-08-01 00:15:52 +02:00
Stéphane Lesimple
0f0d103a89 fix: correctly init capabilities_ssb_no var in all cases 2018-07-26 10:18:14 +02:00
Stéphane Lesimple
b262c40541 fix: remove spurious character after an else statement 2018-07-25 21:55:50 +02:00
Stéphane Lesimple
cc2910fbbc fix: read_cpuid: don't use iflag=skip_bytes for compat with old dd versions
This closes #215 #199 #193
2018-07-23 09:12:30 +02:00
manish jaggi
30c4a1f6d2 arm64: cavium: Add CPU Implementer Cavium (#216)
This patch adds 0x43 check for cavium implementor id in function
parse_cpu_details. Also adds that Cavium Soc is not vulnerable to variant 3/3a

Signed-off-by: Manish Jaggi <manish.jagg@cavium.com>
2018-07-22 19:06:19 +02:00
Stéphane Lesimple
cf06636a3f fix: prometheus output: use printf for proper \n interpretation (#204) 2018-06-21 23:35:51 +02:00
Stéphane Lesimple
60077c8d12 fix(arm): rewrite vuln logic from latest arm statement for Cortex A8 to A76 2018-06-21 23:24:18 +02:00
Rob Gill
c181978d7c fix(arm): Updated arm cortex status (#209)
* Cortex A8 Vulnerable

Arm Cortex A8 is vulnerable to variants 1 & 2  (https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability)

Part number is 0xc08 (https://developer.arm.com/docs/ddi0344/b/system-control-coprocessor/system-control-coprocessorregisters/c0-main-id-register)

False negative reported by @V10lator in #206

* ARM Cortex A12 Vulnerable to 1&2

https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability

* A76 vulnerable to variant 4

All arch 8 cortex A57-A76 are vulnerable to variant 4.

https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability

* Whitelist variant4 nonvuln Arms

* ARM Cortex Whitelist & Cumulative Blacklist

Applies all information about vulnerabilities of ARM Cortex processors (from https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability).

Whitelist & blacklist approach, using both vulnerable and non vulnerable status for each identified CPU, with vulnerabilities tracked cumulatively for multi CPU systems.
2018-06-16 12:14:39 +02:00
Jan
9a6406a9a2 chore: add docker support (#203) 2018-06-14 20:25:35 +02:00
Rob Gill
5962d20ba7 fix(variant4): whitelist from common.c::cpu_no_spec_store_bypass (#202)
* variant4 from common.c::cpu_no_spec_store_bypass

Variant 4 - Add function to 'whitelist' the hand-full of CPUs unaffected by speculative store bypass. 

This would allow improved determination of variant 4 status ( #189 ) of immune CPUs while waiting for the 4.17/stable patches to be backported to distro kernels.

Source of cpu list : https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c#n945)
Modeled after is_cpu_specex_free()

* amd families fix

amd families are reported by parse_cpu_details() in decimal

* remove duplicates

Only list processors which speculate and are immune to variant 4.
Avoids duplication with non-speculating CPUs listed in is_cpu_specex_free()
2018-05-27 15:14:29 +02:00
Rob Gill
17a3488505 fix(help): add missing references to variants 3a & 4 (#201) 2018-05-24 16:35:57 +02:00
Stéphane Lesimple
e54e8b3e84 chore: remove warning in README, fix display indentation 2018-05-24 16:32:53 +02:00
Stéphane Lesimple
39c778e3ac fix(amd): AMD families 0x15-0x17 non-arch MSRs are a valid way to control SSB 2018-05-23 23:08:07 +02:00
Stéphane Lesimple
2cde6e4649 feat(ssbd): add detection of proper CPUID bits on AMD 2018-05-23 22:50:52 +02:00
Stéphane Lesimple
f4d51e7e53 fix(variant4): add another detection way for Red Hat kernel 2018-05-23 22:47:54 +02:00
Stéphane Lesimple
85d46b2799 feat(variant4): add more detailed explanations 2018-05-23 21:08:58 +02:00
Stéphane Lesimple
61e02abd0c feat(variant3a): detect up to date microcode 2018-05-23 21:08:08 +02:00
Stéphane Lesimple
114756fab7 fix(amd): not vulnerable to variant3a 2018-05-23 20:38:43 +02:00
Rob Gill
ea75969eb7 fix(help): Update variant options in usage message (#200) 2018-05-22 15:54:25 +02:00
Stéphane Lesimple
ca391cbfc9 fix(variant2): correctly detect IBRS/IBPB in SLES kernels 2018-05-22 12:06:46 +02:00
Stéphane Lesimple
68af5c5f92 feat(variant4): detect SSBD-aware kernel 2018-05-22 12:05:46 +02:00
Stéphane Lesimple
19be8f79eb doc: update README with some info about variant3 and variant4 2018-05-22 09:43:29 +02:00
Stéphane Lesimple
f75cc0bb6f feat(variant4): add sysfs mitigation hint and some explanation about the vuln 2018-05-22 09:39:11 +02:00
Stéphane Lesimple
f33d65ff71 feat(variant3a): add information about microcode-sufficient mitigation 2018-05-22 09:38:29 +02:00
Stéphane Lesimple
725eaa8bf5 feat(arm): adjust vulnerable ARM CPUs for variant3a and variant4 2018-05-22 09:19:29 +02:00
Stéphane Lesimple
c6ee0358d1 feat(variant4): report SSB_NO CPUs as not vulnerable 2018-05-22 09:18:30 +02:00
Stéphane Lesimple
22d0b203da fix(ssb_no): rename ssbd_no to ssb_no and fix shift 2018-05-22 00:38:31 +02:00
Stéphane Lesimple
3062a8416a fix(msg): add missing words 2018-05-22 00:10:08 +02:00
Stéphane Lesimple
6a4318addf feat(variant3a/4): initial support for 2 new CVEs 2018-05-22 00:06:56 +02:00
Stéphane Lesimple
c19986188f fix(variant2): adjust detection for SLES kernels 2018-05-19 09:53:12 +02:00
Rob Gill
7e4899bcb8 ibrs can't be enabled on no ibrs cpu (#195)
* ibrs can't be enabled on no ibrs cpu

If the cpu is identified, and does not support SPEC_CTRL or IBRS, then ibrs can't be enabled, even if supported by the kernel.
Instead of reporting IBRS enabled and active UNKNOWN, report IBRS enabled and active NO.
2018-05-17 15:39:48 +02:00
rrobgill
5cc77741af Update spectre-meltdown-checker.sh 2018-05-05 13:00:44 +02:00
rrobgill
1c0f6d9580 cpuid and msr module check
This adds a check before loading the cpuid and msr modules under linux, ensuring they are not unloaded in exit_cleanup() if they were initially present.
2018-05-05 13:00:44 +02:00
Onno Zweers
4acd0f647a Suggestion to change VM to a CPU with IBRS capability 2018-04-20 20:35:12 +02:00
Stéphane Lesimple
fb52dbe7bf set master branch to v0.37+ 2018-04-20 20:34:42 +02:00
Stéphane Lesimple
edebe4dcd4 bump to v0.37 2018-04-18 23:51:45 +02:00
Stéphane Lesimple
83ea78f523 fix: arm: also detect variant 1 mitigation when using native objdump 2018-04-17 18:50:32 +02:00
Stéphane Lesimple
602b68d493 fix(spectrev2): explain that retpoline is possible for Skylake+ if there is RSB filling, even if IBRS is still better 2018-04-16 09:27:28 +02:00
Stéphane Lesimple
97bccaa0d7 feat: rephrase IBPB warning when only retpoline is enabled in non-paranoid mode 2018-04-16 09:13:25 +02:00
Stéphane Lesimple
68e619b0d3 feat: show RSB filling capability for non-Skylake in verbose mode 2018-04-16 09:08:25 +02:00
Stéphane Lesimple
a6f4475cee feat: make IBRS_FW blue instead of green 2018-04-16 09:07:54 +02:00
Stéphane Lesimple
223f5028df feat: add --paranoid to choose whether we require IBPB 2018-04-15 23:05:30 +02:00
Stéphane Lesimple
c0108b9690 fix(spectre2): don't explain how to fix when NOT VULNERABLE 2018-04-15 20:55:55 +02:00
Stéphane Lesimple
a3016134bd feat: make RSB filling support mandatory for Skylake+ CPUs 2018-04-15 20:55:31 +02:00
Stéphane Lesimple
59d85b39c9 feat: detect RSB filling capability in the kernel 2018-04-15 20:55:01 +02:00
Stéphane Lesimple
baaefb0c31 fix: remove shellcheck warnings 2018-04-11 22:24:03 +02:00
Igor Lubashev
d452aca03a fix: invalid bash syntax when ibpb_enabled or ibrs_enabled are empty 2018-04-11 10:29:42 +02:00
Stéphane Lesimple
10b8d94724 feat: detect latest Red Hat kernels' RO ibpb_enabled knob 2018-04-10 22:51:45 +02:00
Stéphane Lesimple
8606e60ef7 refactor: no longer display the retoline-aware compiler test when we can't tell for sure 2018-04-10 22:51:45 +02:00
Stéphane Lesimple
6a48251647 fix: regression in 51aeae25, when retpoline & ibpb are enabled 2018-04-10 22:51:45 +02:00
Stéphane Lesimple
f4bf5e95ec fix: typos 2018-04-10 22:51:45 +02:00
Stéphane Lesimple
60eac1ad43 feat: also do PTI performance check with (inv)pcid for BSD 2018-04-10 22:51:45 +02:00
Stéphane Lesimple
b3cc06a6ad fix regression introduced by 82c25dc 2018-04-10 22:51:45 +02:00
Stéphane Lesimple
5553576e31 feat(amd/zen): re-introduce IBRS for AMD except ZEN family 2018-04-10 22:51:45 +02:00
Stéphane Lesimple
e16ad802da feat(ibpb=2): add detection of SMT before concluding the system is not vulnerable 2018-04-10 22:51:45 +02:00
Stéphane Lesimple
29c294edff feat(bsd): explain how to mitigate variant2 2018-04-10 22:51:45 +02:00
Stéphane Lesimple
59714011db refactor: IBRS_ALL & RDCL_NO are Intel-only 2018-04-10 22:51:45 +02:00
Stéphane Lesimple
51e8261a32 refactor: separate hw checks for Intel & AMD 2018-04-10 22:49:28 +02:00
Stéphane Lesimple
2a4bfad835 refactor: add is_amd and is_intel funcs 2018-04-10 22:49:28 +02:00
Stéphane Lesimple
7e52cea66e feat(spectre2): refined how status of this vuln is decided and more precise explanations on how to fix 2018-04-10 22:49:28 +02:00
Benjamin Bouvier
417d7aab91 Fix trailing whitespace and mixed indent styles; 2018-04-10 22:42:47 +02:00
Sylvestre Ledru
67bf761029 Fix some user facing typos with codespell -w -q3 . 2018-04-08 18:44:13 +02:00
Stéphane Lesimple
0eabd266ad refactor: decrease default verbosity for some tests 2018-04-05 22:20:16 +02:00
Stéphane Lesimple
b77fb0f226 fix: don't override ibrs/ibpb results with later tests 2018-04-05 22:04:20 +02:00
Stéphane Lesimple
89c2e0fb21 fix(amd): show cpuinfo and ucode details 2018-04-05 21:39:27 +02:00
Stéphane Lesimple
b88f32ed95 feat: print raw cpuid, and fetch ucode version under BSD 2018-04-05 00:07:12 +02:00
Stéphane Lesimple
7a4ebe8009 refactor: rewrite read_cpuid to get more common code parts between BSD and Linux 2018-04-05 00:06:24 +02:00
Stéphane Lesimple
0919f5c236 feat: add explanations of what to do when a vulnerability is not mitigated 2018-04-05 00:03:04 +02:00
Stéphane Lesimple
de02dad909 feat: rework Spectre V2 mitigations detection w/ latest vanilla & Red Hat 7 kernels 2018-04-05 00:01:54 +02:00
Stéphane Lesimple
07484d0ea7 add dump of variables at end of script in debug mode 2018-04-04 23:58:15 +02:00
Stéphane Lesimple
a8b557b9e2 fix(cpu): skip CPU checks if asked to (--no-hw) or if inspecting a kernel of another architecture 2018-04-03 19:36:28 +02:00
Stéphane Lesimple
619b2749d8 fix(sysfs): only check for sysfs for spectre2 when in live mode 2018-04-03 19:32:36 +02:00
Stéphane Lesimple
94857c983d update readme 2018-04-03 16:00:36 +02:00
Stéphane Lesimple
056ed00baa feat(arm): detect spectre variant 1 mitigation 2018-04-03 15:52:25 +02:00
Stéphane Lesimple
aef99d20f3 fix(pti): when PTI activation is unknown, don't say we're vulnerable 2018-04-03 12:45:17 +02:00
Stéphane Lesimple
e2d7ed2243 feat(arm): support for variant2 and meltdown mitigation detection 2018-04-01 17:50:18 +02:00
Stéphane Lesimple
eeaeff8ec3 set version to v0.36+ for master branch between releases 2018-04-01 17:45:01 +02:00
Stéphane Lesimple
f5269a362a feat(bsd): add retpoline detection for BSD 2018-04-01 17:42:29 +02:00
Stéphane Lesimple
f3883a37a0 fix(xen): adjust message for DomUs w/ sysfs 2018-03-31 13:44:04 +02:00
Stéphane Lesimple
b6fd69a022 release: v0.36 2018-03-27 23:08:38 +02:00
Stéphane Lesimple
7adb7661f3 enh: change colors and use red only to report vulnerability 2018-03-25 18:15:08 +02:00
Stéphane Lesimple
c7892e3399 update README.md 2018-03-25 14:18:39 +02:00
Stéphane Lesimple
aa74315df4 feat: speed up kernel version detection 2018-03-25 13:42:19 +02:00
Stéphane Lesimple
0b8a09ec70 fix: mis adjustments for BSD compat 2018-03-25 13:26:00 +02:00
Stéphane Lesimple
b42d8f2f27 fix(write_msr): use /dev/zero instead of manually echoing zeroes 2018-03-25 12:53:50 +02:00
Stéphane Lesimple
f191ec7884 feat: add --hw-only to only show CPU microcode/cpuid/msr details 2018-03-25 12:48:37 +02:00
Stéphane Lesimple
28da7a0103 misc: message clarifications 2018-03-25 12:48:03 +02:00
Stéphane Lesimple
ece25b98a1 feat: implement support for NetBSD/FreeBSD/DragonFlyBSD 2018-03-25 12:28:02 +02:00
Stéphane Lesimple
889172dbb1 feat: add special extract_vmlinux mode for old RHEL kernels 2018-03-25 11:55:44 +02:00
Stéphane Lesimple
37ce032888 fix: bypass MSR/CPUID checks for non-x86 CPUs 2018-03-25 11:55:44 +02:00
Stéphane Lesimple
701cf882ad feat: more robust validation of extracted kernel image 2018-03-25 11:55:44 +02:00
Stéphane Lesimple
6a94c3f158 feat(extract_vmlinux): look for ELF magic in decompressed blob and cut at found offset 2018-03-25 11:55:42 +02:00
Stéphane Lesimple
2d993812ab feat: add --prefix-arch for cross-arch kernel inspection 2018-03-25 11:55:10 +02:00
Stéphane Lesimple
4961f8327f fix(ucode): fix blacklist detection for some ucode versions 2018-03-19 12:09:39 +01:00
Alex
ecdc448531 Check MSR in each CPU/Thread (#136) 2018-03-17 17:17:15 +01:00
Stéphane Lesimple
12ea49fe0c fix(kvm): properly detect PVHVM mode (fixes #163) 2018-03-16 18:29:58 +01:00
Stéphane Lesimple
053f1613de fix(doc): use https:// URLs in the script comment header 2018-03-16 18:24:59 +01:00
Stéphane Lesimple
bda18d04a0 fix: pine64: re-add vmlinuz location and some error checks 2018-03-10 16:02:44 +01:00
Stéphane Lesimple
2551295541 doc: use https URLs 2018-03-10 15:20:07 +01:00
Stéphane Lesimple
d5832dc1dc feat: add ELF magic detection on kernel image blob for some arm64 systems 2018-03-10 14:57:25 +01:00
Stéphane Lesimple
d2f46740e9 feat: enhance kernel image version detection for some old kernels 2018-03-10 14:57:25 +01:00
Sam Morris
2f6a6554a2 Produce output for consumption by prometheus-node-exporter
A report of all vulnerable machines to be produced with a query such as:

    spexec_vuln_status{status!="OK"}
2018-02-27 11:08:39 +01:00
Stéphane Lesimple
30842dd9c0 release: bump to v0.35 2018-02-16 10:35:49 +01:00
Stéphane Lesimple
b4ac5fcbe3 feat(variant2): better explanation when kernel supports IBRS but CPU does not 2018-02-16 10:34:01 +01:00
Stéphane Lesimple
fef380d66f feat(readme): add quick run section 2018-02-15 21:19:49 +01:00
Stéphane Lesimple
55a6fd3911 feat(variant1): better detection for Red Hat/Ubuntu patch 2018-02-15 21:19:49 +01:00
Sylvestre Ledru
35c8a63de6 Remove the color in the title 2018-02-15 20:21:00 +01:00
Stéphane Lesimple
5f914e555e fix(xen): declare Xen's PTI patch as a valid mitigation for variant3 2018-02-14 14:24:55 +01:00
Stéphane Lesimple
66dce2c158 fix(ucode): update blacklisted ucodes list from latest Intel info 2018-02-14 14:14:16 +01:00
Calvin Walton
155cac2102 Teach checker how to find kernels installed by systemd kernel-install 2018-02-10 20:51:33 +01:00
Stéphane Lesimple
22cae605e1 fix(retpoline): remove the "retpoline enabled" test
This test worked for some early versions of the retpoline
implementation in vanilla kernels, but the corresponding
flag has been removed from /proc/cpuinfo in latest kernels.
The full information is available in /sys instead, which
was already implemented in the script.
2018-02-09 20:12:33 +01:00
Stéphane Lesimple
eb75e51975 fix(ucode): update list of blacklisted ucodes from 2018-02-08 Intel document
Removed 2 ucodes and added 2 other ones
2018-02-09 19:56:27 +01:00
積丹尼 Dan Jacobson
253e180807 Update spectre-meltdown-checker.sh
Dots better than colon for indicating waiting.
2018-02-06 19:02:56 +01:00
Stéphane Lesimple
5d6102a00e enh: show kernel version in offline mode 2018-02-02 11:27:04 +01:00
Stéphane Lesimple
a2dfca671e feat: detect disrepancy between found kernel image and running kernel 2018-02-02 11:13:54 +01:00
Stéphane Lesimple
36bd80d75f enh: speedup by not decompressing kernel on --sysfs-only 2018-02-02 11:13:31 +01:00
Stéphane Lesimple
1834dd6201 feat: add skylake era cpu detection routine 2018-02-02 11:12:10 +01:00
Stéphane Lesimple
3d765bc703 enh: lazy loading of cpu informations 2018-02-02 11:11:51 +01:00
Stéphane Lesimple
07afd95b63 feat: better cleanup routine on exit & interrupt 2018-02-02 11:09:36 +01:00
Stéphane Lesimple
b7a10126d1 fix: ARM CPU display name & detection
Fix ARM CPU display name, and properly
detect known vulnerable ARM CPUs when
multiple different model cores are
present (mostly Android phones)
2018-02-02 11:00:23 +01:00
Stéphane Lesimple
6346a0deaa fix: --no-color workaround for android's sed 2018-02-02 10:59:49 +01:00
Stéphane Lesimple
8106f91981 release: bump to v0.34 2018-01-31 16:28:54 +01:00
Stéphane Lesimple
b1fdf88f28 enh: display ucode info even when not blacklisted 2018-01-31 16:21:32 +01:00
Stéphane Lesimple
4d29607630 cleanup: shellcheck pass 2018-01-31 16:15:20 +01:00
Stéphane Lesimple
0267659adc cleanup: remove superseded atom detection code
This is now handled properly by checking the CPU
vendor, family, model instead of looking for the
commercial name of the CPU in /proc/cpuinfo
2018-01-31 16:15:20 +01:00
Stéphane Lesimple
247b176882 feat: detect known speculative-execution free CPUs
Based on a kernel patch that has been merged to Linus' tree.
Some of the detections we did by grepping the model name
will probably no longer be needed.
2018-01-31 16:15:20 +01:00
Stéphane Lesimple
bcae8824ec refacto: create a dedicated func to read cpuid bits 2018-01-31 16:15:20 +01:00
Stéphane Lesimple
71e7109c22 refacto: move cpu discovery bits to a dedicated function 2018-01-31 16:15:20 +01:00
Stéphane Lesimple
aa18b51e1c fix(variant1): smarter lfence check
Instead of just counting the number of LFENCE
instructions, now we're only counting the those
that directly follow a jump instruction.
2018-01-31 14:34:54 +01:00
Stéphane Lesimple
b738ac4bd7 fix: regression introduced by previous commit
449: ./spectre-meltdown-checker.sh: 3: parameter not set
This happened only on blacklisted microcodes, fixed by
adding set +u before the return
2018-01-31 12:13:50 +01:00
Stéphane Lesimple
799ce3eb30 update blacklisted ucode list from kernel source 2018-01-31 11:26:23 +01:00
Stéphane Lesimple
f1e18c136f doc(disclaimer): Spectre affects all software
Add a paragraph in the disclaimer stating that this tool focuses
on the kernel side of things, and that for Spectre, any software
might be vulnerable.
2018-01-30 14:37:52 +01:00
Stéphane Lesimple
e05ec5c85f feat(variant1): detect vanilla mitigation
Implement detection of mitigation for Variant 1 that is
being pushed on vanilla kernel.
Current name of the patch:
"spectre variant1 mitigations for tip/x86/pti" (v6)
Also detect some distros that already backported this
patch without modifying the vulnerabilities sysfs hierarchy.
This detection is more reliable than the LFENCE one, trust
it and skip the LFENCE heuristic if a match is found.
2018-01-30 12:55:34 +01:00
Stéphane Lesimple
6e544d6055 fix(cpu): Pentium Exxxx are vulnerable to Meltdown 2018-01-29 11:18:15 +01:00
Stéphane Lesimple
90a65965ff adjust: show how to enable IBRS/IBPB in -v only 2018-01-29 11:06:15 +01:00
Stéphane Lesimple
9b53635eda refacto: fix shellcheck warnings for better compat
Now `shellcheck -s sh` no longer shows any warnings.
This should improve compatibility with exotic shells
as long as they're POSIX compliant.
2018-01-29 10:34:08 +01:00
Joseph Mulloy
7404929661 Fix printing of microcode to use cpuinfo values
The values used should be the ones that come from cpuinfo instead of
the test values. The following line will print the last tuple tested
instead of the actual values of the CPU.

Line 689: _debug "is_ucode_blacklisted: no ($model/$stepping/$ucode)"
2018-01-26 18:23:18 +01:00
Stéphane Lesimple
bf46fd5d9b update: new screenshots for README.md 2018-01-26 15:15:24 +01:00
Stéphane Lesimple
0798bd4c5b fix: report arch_capabilities as NO when no MSR
When the arch_capabilities MSR is not there, it means
that all the features it might advertise can be considered
as NO instead of UNKNOWN
2018-01-26 14:55:01 +01:00
Stéphane Lesimple
42094c4f8b release: v0.33 2018-01-26 14:20:29 +01:00
Stéphane Lesimple
03d2dfe008 feat: add blacklisted Intel ucode detection
Some Intel microcodes are known to cause instabilities
such as random reboots. Intel advises to revert to a
previous version if a newer one that fixes those issues
is not available. Detect such known bad microcodes.
2018-01-26 14:19:54 +01:00
Stéphane Lesimple
9f00ffa5af fix: fallback to UNKNOWN when we get -EACCES
For detection of IBRS_ALL and RDCL_NO, fallback to
UNKNOWN when we were unable to read the CPUID or MSR.
2018-01-26 14:16:34 +01:00
Matthieu Cerda
7f0d80b305 xen: detect if the host is a Xen Dom0 or PV DomU (fixes #83) 2018-01-25 11:04:30 +01:00
Stéphane Lesimple
d1c1f0f0f0 fix(batch): fix regression introduced by acf12a6
In batch mode, $echo_cmd was not initialized early
enough, and caused this error:
./spectre-meltdown-checker.sh: 899: ./spectre-meltdown-checker.sh: -ne: not found
Fix it by initing echo_cmd unconditionally at the start
2018-01-24 17:57:19 +01:00
Stéphane Lesimple
acf12a6d2d feat(cpu) add STIBP, RDCL_NO, IBRS_ALL checks
Move all the CPU checks to their own section,
for clarity. We now check for IBRS, IBPB, STIBP,
RDCL_NO and IBRS_ALL. We also show whether the
system CPU is vulnerable to the three variants,
regardless of the fact that mitigations are in
place or not, which is determined in each vuln-
specific section.
2018-01-24 14:44:16 +01:00
Stéphane Lesimple
b45e40bec8 feat(stibp): add STIBP cpuid feature check 2018-01-24 12:19:02 +01:00
Stéphane Lesimple
3c1d452c99 fix(cpuid): fix off-by-one SPEC_CTRL bit check 2018-01-24 12:18:56 +01:00
Stéphane Lesimple
53b9eda040 fix: don't make IBPB mandatory when it's not there
On some kernels there could be IBRS support but not
IBPB support, in that case, don't report VULN just
because IBPB is not enabled when IBRS is
2018-01-24 09:04:25 +01:00
Stéphane Lesimple
3b0ec998b1 fix(cosmetic): tiny msg fixes 2018-01-24 09:04:25 +01:00
Stéphane Lesimple
d55bafde19 fix(cpu): trust is_cpu_vulnerable even w/ debugfs
For variant3 under AMD, the debugfs vulnerabilities hierarchy
flags the system as Vulnerable, which is wrong. Trust our own
is_cpu_vulnerable() func in that case
2018-01-24 09:04:25 +01:00
Stéphane Lesimple
147462c0ab fix(variant3): do our checks even if sysfs is here 2018-01-24 09:04:25 +01:00
Stéphane Lesimple
ddc7197b86 fix(retpoline): retpoline-compiler detection
When kernel is not compiled with retpoline option, doesn't
have the sysfs vulnerability hierarchy and our heuristic to
detect a retpoline-aware compiler didn't match, change result
for retpoline-aware compiler detection from UNKNOWN to NO.
When CONFIG_RETPOLINE is not set, a retpoline-aware compiler
won't produce different asm than a standard one anyway.
2018-01-24 09:04:25 +01:00
Stéphane Lesimple
e7aa3b9d16 feat(retpoline): check if retpoline is enabled
Before we would just check if retpoline was compiled
in, now we also check that it's enabled at runtime
(only in live mode)
2018-01-24 09:04:25 +01:00
Stéphane Lesimple
ff5c92fa6f feat(sysfs): print details even with sysfs
Before, when the /sys kernel vulnerability interface
was available, we would bypass all our tests and just
print the output of the vulnerability interface. Now,
we still rely on it when available, but we run our
checks anyway, except for variant 1 where the current
method of mitigation detection doesn't add much value
to the bare /sys check
2018-01-24 09:04:25 +01:00
Stéphane Lesimple
443d9a2ae9 feat(ibpb): now also check for IBPB on variant 2
In addition to IBRS (and microcode support), IBPB
must be used to mitigate variant 2, if retpoline
support is not available. The vulnerability status
of a system will be defined as "non vulnerable"
if IBRS and IBPB are both enabled, or if IBPB
is enabled with a value of 2 for RedHat kernels,
see https://access.redhat.com/articles/3311301
2018-01-24 09:04:25 +01:00
Stéphane Lesimple
3e454f1817 fix(offline): report unknown when too few info
In offline mode, in the worst case where an invalid
config file is given, and we have no vmlinux image
nor System.map, the script was reporting Variant 2
and Variant 3 as vulnerable in the global status.
Replace this by a proper pair of UNKNOWNs
2018-01-23 22:20:34 +01:00
Stéphane Lesimple
c8a25c5d97 feat: detect invalid kconfig files 2018-01-23 21:48:19 +01:00
Stéphane Lesimple
40381349ab fix(dmesg): detect when dmesg is truncated
To avoid false negatives when looking for a message
in dmesg, we were previously also grepping in known
on-disk archives of dmesg (dmesg.log, kern.log).
This in turn caused false positives because we have no
guarantee that we're grepping the dmesg of the current
running kernel. Hence we now only look in the live
`dmesg`, detect if it has been truncated, and report
it to the user.
2018-01-21 16:26:08 +01:00
Stéphane Lesimple
0aa5857a76 fix(cpu): Pentium Exxxx series are not vulnerable
Pentium E series are not in the vulnerable list from
Intel, and Spectre2 PoC reportedly doesn't work on
an E5200
2018-01-21 16:13:17 +01:00
Stéphane Lesimple
b3b7f634e6 fix(display): use text-mode compatible colors
in text-mode 80-cols TERM=linux terminals, colors
were not displaying properly, one had to use
--no-color to be able to read some parts of the
text.
2018-01-21 12:32:22 +01:00
84 changed files with 16376 additions and 1976 deletions

185
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,185 @@
name: build
on:
push:
branches:
- test
- source
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
persist-credentials: true
- name: install prerequisites
run: sudo apt-get update && sudo apt-get install -y shellcheck shfmt jq sqlite3 iucode-tool make
- name: update Intel model list
run: ./scripts/update_intel_models.sh
- name: build and check
run: |
make build fmt-check shellcheck
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')
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)
if [ "$nb" -ne "$expected" ]; then
echo "Invalid number of CVEs reported: $nb instead of $expected"
exit 1
else
echo "OK $nb CVEs reported"
fi
- name: check docker run execution
run: |
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)
if [ "$nb" -ne "$expected" ]; then
echo "Invalid number of CVEs reported: $nb instead of $expected"
exit 1
else
echo "OK $nb CVEs reported"
fi
- name: check fwdb update (separated)
run: |
cd dist
nbtmp1=$(find /tmp 2>/dev/null | wc -l)
./spectre-meltdown-checker.sh --update-fwdb; ret=$?
if [ "$ret" != 0 ]; then
echo "Non-zero return value: $ret"
exit 1
fi
nbtmp2=$(find /tmp 2>/dev/null | wc -l)
if [ "$nbtmp1" != "$nbtmp2" ]; then
echo "Left temporary files!"
exit 1
fi
if ! [ -e ~/.mcedb ]; then
echo "No .mcedb file found after updating fwdb"
exit 1
fi
- name: check fwdb update (builtin)
run: |
cd dist
nbtmp1=$(find /tmp 2>/dev/null | wc -l)
./spectre-meltdown-checker.sh --update-builtin-fwdb; ret=$?
if [ "$ret" != 0 ]; then
echo "Non-zero return value: $ret"
exit 1
fi
nbtmp2=$(find /tmp 2>/dev/null | wc -l)
if [ "$nbtmp1" != "$nbtmp2" ]; then
echo "Left temporary files!"
exit 1
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/
mkdir -p .github
rsync -vaP --delete $tmpdir/.github/ .github/
git add --all
echo =#=#= DIFF CACHED
git diff --cached
echo =#=#= STATUS
git status
echo =#=#= COMMIT
git config --global user.name "github-actions[bot]"
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
git log ${{ github.ref }} -1 --format=format:'%s%n%n built from commit %H%n dated %ai%n by %an (%ae)%n%n %b'
git log ${{ github.ref }} -1 --format=format:'%s%n%n built from commit %H%n dated %ai%n by %an (%ae)%n%n %b' | git commit -F -
git push

1
.github/workflows/expected_cve_count vendored Normal file
View File

@@ -0,0 +1 @@
32

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
spectre-meltdown-checker.sh

877
DEVELOPMENT.md Normal file
View File

@@ -0,0 +1,877 @@
# Project Overview
spectre-meltdown-checker is a single self-contained shell script (`spectre-meltdown-checker.sh`) that detects system vulnerability to several transient execution CPU CVEs (Spectre, Meltdown, and related). It supports Linux and BSD (FreeBSD, NetBSD, DragonFlyBSD) on x86, amd64, ARM, and ARM64.
The script must stay POSIX-compatible, and not use features only available in specific shells such as `bash` or `zsh`. The `local` keyword is accepted however.
## Project Mission
This tool exists to give system administrators simple, actionable answers to two questions:
1. **Am I vulnerable?**
2. **What do I have to do to mitigate these vulnerabilities on my system?**
The script does not run exploits and cannot guarantee security. It reports whether a system is **affected**, **vulnerable**, or **mitigated** against known transient execution vulnerabilities, and provides detailed insight into the prerequisites for full mitigation (microcode, kernel, hypervisor, etc.).
### Why this tool still matters
Even though the Linux `sysfs` hierarchy (`/sys/devices/system/cpu/vulnerabilities/`) now reports mitigation status for most vulnerabilities, this script provides value beyond what `sysfs` offers:
- **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.
- **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.
### Terminology
These terms have precise meanings throughout the codebase and output:
- **Affected**: The CPU hardware, as shipped from the factory, is known to be concerned by a vulnerability. Says nothing about whether the vulnerability is currently exploitable.
- **Vulnerable**: The system uses an affected CPU *and* has no (or insufficient) mitigations in place, meaning the vulnerability can be exploited.
- **Mitigated**: A previously vulnerable system has all required layers updated so the vulnerability cannot be exploited.
## Branch Model
The project uses 4 branches organized in two pipelines (production and dev/test). Developers work on the source branches; CI builds the monolithic script and pushes it to the corresponding output branch.
| Branch | Contents | Pushed by |
|--------|----------|-----------|
| **`test`** | Dev/test source (split files + Makefile) | Developers |
| **`test-build`** | Monolithic test script (built artifact) | CI from `test` |
| **`source`** | Production source (split files + Makefile) | Developers |
| **`source-build`** | Monolithic test script (built artifact) | CI from `source` |
| **`master`** | Monolithic production script (built artifact) | PR by developers from `source-build` |
- **`source`** and **`test`** contain the split source files and the Makefile. These are the branches developers commit to.
- **`master`**, **`source-build`** and **`test-build`** contain only the monolithic `spectre-meltdown-checker.sh` built by CI. Nobody commits to these directly.
- **`master`** is the preexisting production branch that users pull from. It cannot be renamed.
- **`test-build`** is a testing branch that users can pull from to test pre-release versions.
- **`source-build`** is a preprod branch to prepare the artifact before merging to **`master`**.
Typical workflow:
1. Feature/fix branches are created from `test` and merged back into `test`.
2. CI builds the script and pushes it to `test-build` for testing.
3. When ready for release, `test` is merged into `source`.
4. CI builds the script and pushes it to `source-build` for production.
5. Developer creates a PR from `source-build` to `master`.
## Versioning
The project follows semantic versioning in the format `X.Y.Z`:
- **X** = the current year, in `YY` format.
- **Y** = the number of CVEs supported by the script, which corresponds to the number of files under `src/vulns/`.
- **Z** = `MMDDVAL`, where `MMDD` is the UTC build date and `VAL` is a 3-digit value (000999) that increases monotonically throughout the day, computed as `seconds_since_midnight_UTC * 1000 / 86400`.
The version is patched automatically by `build.sh` into the `VERSION=` variable of the assembled script. The source file (`src/libs/001_core_header.sh`) carries a placeholder value that is overwritten at build time.
## Linting and Testing
```bash
# Assemble the final script
make build
# Lint the generated script
make fmt-check shellcheck
# Run the script (requires root for full results)
sudo ./spectre-meltdown-checker.sh
# Run specific tests that we might have just added (variant name)
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
# Update microcode firmware database
sudo ./spectre-meltdown-checker.sh --update-fwdb
# Docker
docker-compose build && docker-compose run --rm spectre-meltdown-checker
```
There is no separate test suite. CI (`.github/workflows/check.yml`) runs shellcheck, tab-indentation checks, a live execution test validating 19 CVEs, Docker builds, and a firmware DB update test that checks for temp file leaks.
## Architecture
The entire tool is a single bash script with no external script dependencies. Key structural sections:
- **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.
## Key Design Principles
These rules are non-negotiable and govern how every part of the script is written:
### 1. Production-safe
It must always be okay to run this script in a production environment.
- **1a. Non-destructive**: Never modify the system. If the script loads a kernel module it needs (e.g. `cpuid`, `msr`), it must unload it on exit.
- **1b. Report only**: Never attempt to "fix" or "mitigate" any vulnerability, or modify any configuration. The script reports status and leaves all decisions to the sysadmin.
- **1c. No exploit execution**: Never run any kind of exploit or proof-of-concept. This would violate rule 1a, could cause unpredictable system behavior, and may produce wrong conclusions (especially for Spectre-class PoCs that require very specific build options and prerequisites).
### 2. Never hardcode kernel versions
Never look at the kernel version string to determine whether it supports a mitigation. This would defeat the script's purpose: it must detect mitigations in unknown, vendor-patched, or backported kernels. Similarly, do not blindly trust what `sysfs` reports when it is possible to verify directly.
### 3. Never hardcode microcode versions (with one exception)
Never look at the microcode version to determine whether it has the proper mitigation mechanisms. Instead, probe for the mechanisms themselves (CPUID bits, MSR values), as the kernel would.
**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)
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
The script can analyze a non-running kernel via `--kernel`, `--config`, `--map` flags, allowing verification before deployment.
## CVE Inclusion Criteria
A vulnerability should be supported by this tool when mitigating it requires **kernel modifications**, **microcode modifications**, or **both**.
A vulnerability is **out of scope** when:
- Mitigation is handled entirely by a driver or userspace software update (e.g. CVE-2019-14615, which requires an Intel driver update).
- The vulnerability is a regression from a bad backport and cannot be detected without hardcoding kernel versions (violates rule 2).
- The vendor has determined it is not a new attack and issued no kernel or microcode changes, leaving nothing for the script to check.
- The industry has collectively decided not to address the vulnerability (no mitigations exist), leaving nothing to verify.
When evaluating whether to add a new CVE, check the [information-tagged issues](https://github.com/speed47/spectre-meltdown-checker/issues?q=is%3Aissue+label%3Ainformation) for prior discussion and precedent.
## POSIX Compliance
The script must run on both Linux and BSD systems (FreeBSD, NetBSD, DragonFlyBSD). This means all external tool invocations must use only POSIX-specified options. Many tools have GNU extensions that are not available on BSD, or BSD extensions that are not available on GNU/Linux. When in doubt, test on both.
Common traps to avoid:
| Tool | Non-portable usage | Portable alternative |
|------|--------------------|----------------------|
| `sed` | `-r` (GNU extended regex flag) | `-E` (accepted by both GNU and BSD) |
| `grep` | `-P` (Perl regex, GNU only) | Use `awk` or rework the pattern |
| `sort` | `-V` (version sort, GNU only) | Extract numeric fields and compare with `awk` or shell arithmetic |
| `cut` | `-w` (whitespace delimiter, BSD only) | `awk '{print $N}'` |
| `stat` | `-c %Y` (GNU format) | Try GNU first, fall back to BSD: `stat -c %Y ... 2>/dev/null \|\| stat -f %m ...` |
| `date` | `-d @timestamp` (GNU only) | Try GNU first, fall back to BSD: `date -d @ts ... 2>/dev/null \|\| date -r ts ...` |
| `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.
## Return Codes
0 = not vulnerable, 2 = vulnerable, 3 = unknown, 255 = error
## Variable naming conventions
This script uses the following naming rules for variables:
`UPPER_SNAKE_CASE` : Constants and enums (e.g. READ_MSR_RET_OK, EAX), declared with `readonly` on the assignment line (e.g. `readonly FOO="bar"`).
When they're used as values affected to "Out-parameters" of a function, they should follow the `<FUNC>_RET_*` pattern.
Such variables should be declared right above the definition of the function they're dedicated to.
Other general constants go at the top of the file, below the `VERSION` affectation.
`opt_*` : Command-line options set during argument parsing (e.g. opt_verbose, opt_batch).
`cpu_*` : CPU identification/state filled by parse_cpu_details() (e.g. cpu_family, cpu_model).
`cap_*` : CPU capability flags read from hardware/firmware (e.g. cap_verw_clear, cap_rdcl_no).
All `cap_*` variables are set in `check_cpu()`. They come in two flavors:
- **Immunity bits** (`cap_*_no`): The CPU vendor declares this hardware is not affected by a vulnerability.
The `_no` suffix mirrors the vendor's own bit naming (e.g. RDCL_NO, GDS_NO, TSA_SQ_NO).
These are consumed in `is_cpu_affected()` to mark a CPU as immune.
- **Mitigation bits** (all other `cap_*`): Microcode or hardware provides a mechanism to work around
a vulnerability the CPU *does* have (e.g. cap_verw_clear, cap_ibrs, cap_ssbd).
These are consumed in `check_CVE_*_linux()` functions to assess mitigation status.
`affected_*` : Per-CVE vulnerability status from is_cpu_affected() (e.g. affected_l1tf).
`ret_<func>_*` : "Out-parameters" set by a function for its caller (e.g. ret_read_cpuid_value, ret_read_msr_msg).
The <func> matches the function name so ownership is obvious, these variables can't be written
to by any other function than <func>, nor by toplevel.
`g_*` : Other global (i.e. non-`local`) variables that don't match cases previously described.
`<name>` : Scratch/temporary variables inside functions (e.g. core, msg, col).
These must be declared as `local`. These must not match any naming pattern above.
Any variable that is only used in the scope of a given function falls in this category.
Additionally, all vars must start with a [a-z] character, never by an underscore.
## Function naming conventions
Functions follow two naming tiers:
`public_function` : Top-level functions called directly from the main flow or from other public functions.
Examples: `parse_cpu_details`, `read_cpuid`, `check_CVE_2017_5754`.
`_private_function` : Utility/helper functions that exist solely to factorize code shared by other functions.
These must never be called directly from the top-level main flow.
Examples: `_echo`, `_emit_json`, `_cve_registry_field`.
## How to Implement a New CVE Check
Adding a new CVE follows a fixed pattern. Every check uses the same three-function structure and the same decision algorithm. This section walks through both.
### Prerequisites
Before writing code, verify the CVE meets the inclusion criteria (see "CVE Inclusion Criteria" above). The vulnerability must require kernel and/or microcode changes to mitigate.
### 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:
- **Line 1**: vim modeline (`# vim: set ts=4 sw=4 sts=4 et:`)
- **Line 2**: 31 `#` characters (`###############################`)
- **Line 3**: `# CVE-YYYY-NNNNN, Alias1, Alias2, Complete Name` — the CVE number followed by
all known aliases and the complete name as listed in the `dist/README.md` top table.
- **Line 4**: empty
The file must contain exactly three functions:
```sh
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-YYYY-NNNNN, Short Name, Complete Name
check_CVE_YYYY_NNNNN() {
check_cve 'CVE-YYYY-NNNNN'
}
check_CVE_YYYY_NNNNN_linux() {
# ... (see Step 3)
}
check_CVE_YYYY_NNNNN_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
}
```
The entry point calls `check_cve`, which prints the CVE header and dispatches to `_linux()` or `_bsd()` based on `$g_os`. If BSD mitigations are not yet understood, use the stub above - it correctly reports UNK rather than a false OK.
### Step 2: Register the CVE in the CPU Affection Logic
In `src/libs/200_cpu_affected.sh`, add an `affected_yourname` variable and populate it inside `is_cpu_affected()`. The variable follows the whitelist principle: **assume affected (`1`) unless you can prove the CPU is immune (`0`)**. Two kinds of evidence can prove immunity:
- **Static identifiers**: CPU vendor, family, model, stepping - these identify the hardware design.
- **Hardware immunity `cap_*` bits**: CPUID or MSR bits that the CPU vendor defines to explicitly declare "this hardware is not affected" (e.g. `cap_rdcl_no` for Meltdown, `cap_ssb_no` for Variant 4, `cap_gds_no` for Downfall, `cap_tsa_sq_no`/`cap_tsa_l1_no` for TSA). These are read in `check_cpu()` and stored as `cap_*` globals.
Never use microcode version strings.
When populating the CPU model list, use the **most recent version** of the Linux kernel source as the authoritative reference. The relevant lists are typically found in `arch/x86/kernel/cpu/common.c` (`cpu_vuln_blacklist`) or in the vulnerability-specific mitigation source file. Cross-reference the kernel list with the vendor's published advisory to catch any models the kernel hasn't added yet. Always document the kernel commit hash(es) you based the list on in a comment above the model checks, so future maintainers can diff against newer kernels.
**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:
**Phase 1 - Initialize and check sysfs:**
```sh
check_CVE_YYYY_NNNNN_linux() {
local status sys_interface_available msg
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "$VULN_SYSFS_BASE/vuln_name"; then
sys_interface_available=1
status=$ret_sys_interface_check_status
fi
```
`sys_interface_check` reads `/sys/devices/system/cpu/vulnerabilities/<name>` and parses the kernel's own assessment into `ret_sys_interface_check_status` (OK/VULN/UNK) and `ret_sys_interface_check_fullmsg`. If the sysfs file doesn't exist (older kernel, or the CVE predates kernel awareness), it returns false and `sys_interface_available` stays 0.
**Phase 2 - Custom detection (kernel + runtime):**
Guarded by `if [ "$opt_sysfs_only" != 1 ]; then` so users who trust sysfs can skip it.
This is where the real detection lives. Check for mitigations at each layer:
- **Kernel support**: Determine whether the kernel carries the mitigation code. Three sources of evidence are available, and any one of them is sufficient:
- **Kernel image** (`$g_kernel`): Search for strings or symbols that prove the mitigation code is compiled in.
```sh
if grep -q 'mitigation_string' "$g_kernel"; then
kernel_mitigated="found mitigation evidence in kernel image"
fi
```
Guard with `if [ -n "$g_kernel_err" ]; then` first - the kernel image may be unavailable.
- **Kernel config** (`$opt_config`): Look for the `CONFIG_*` option that enables the mitigation.
```sh
if [ -n "$opt_config" ] && grep -q '^CONFIG_MITIGATION_NAME=y' "$opt_config"; then
kernel_mitigated="found mitigation config option enabled"
fi
```
- **System.map** (`$opt_map`): Look for function names directly linked to the mitigation.
```sh
if [ -n "$opt_map" ] && grep -q 'mitigation_function_name' "$opt_map"; then
kernel_mitigated="found mitigation function in System.map"
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.
**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:
```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
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"
fi
```
- **Microcode capabilities**: Check CPUID bits or MSR flags that indicate the CPU firmware supports the mitigation. Never compare microcode version numbers directly.
Close the `opt_sysfs_only` block with the forced-sysfs fallback:
```sh
elif [ "$sys_interface_available" = 0 ]; then
msg="/sys vulnerability interface use forced, but it's not available!"
status=UNK
fi
```
**Phase 3 - CPU affection gate:**
```sh
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
```
If the CPU is not affected, nothing else matters - report OK and return. This overrides any sysfs or custom detection result.
**Phase 4 - Final status determination:**
For affected CPUs, combine the evidence from Phase 2 into a final verdict. The dispatch
works through `msg`: if Phase 1 (sysfs) or a sysfs override set `msg` to non-empty, use
it directly; otherwise run own logic or fall back to the raw sysfs result.
```sh
elif [ -z "$msg" ]; then
# msg is empty: sysfs either wasn't available, or gave a standard
# response that wasn't overridden. Use our own logic when we have it.
if [ "$opt_sysfs_only" != 1 ]; then
# --- own logic using Phase 2 variables ---
if [ "$microcode_ok" = 1 ] && [ -n "$kernel_mitigated" ]; then
pvulnstatus "$cve" OK "Both kernel and microcode mitigate the vulnerability"
else
pvulnstatus "$cve" VULN "Neither kernel nor microcode mitigate the vulnerability"
explain "Remediation advice here..."
fi
else
# --sysfs-only: Phase 2 variables are unset, fall back to the
# raw sysfs result (status + fullmsg were set in Phase 1).
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
fi
else
# msg was explicitly set - either by the "sysfs not available" elif
# above, or by a sysfs override in Phase 1. Use it as-is.
pvulnstatus "$cve" "$status" "$msg"
fi
}
```
The `opt_sysfs_only` guard inside the `[ -z "$msg" ]` branch is **critical**: without it,
`--sysfs-only` mode would fall into own-logic with all Phase 2 variables unset, producing
wrong results. The `else` at line `pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"`
is safe because it is only reachable when sysfs was available (if it wasn't, the "sysfs not
available" `elif` at the end of Phase 2 would have set `msg`, sending us to the other branch).
The exact combination logic depends on the CVE. Some require **both** microcode and kernel fixes (report VULN if either is missing). Others are mitigated by **either** layer alone (report OK if one is present). Some also require SMT to be disabled - check with `is_cpu_smt_enabled()`.
**Sysfs overrides:** When the kernel's sysfs reporting is known to be incorrect for certain
messages (e.g. old kernels misclassifying a partial mitigation as fully mitigated), add an
override in Phase 1 after `sys_interface_check` returns. The override sets both `status` and
`msg`, which routes Phase 4 to the `else` branch - bypassing own logic entirely. This is
correct because the override and own logic will always agree on the verdict. Example:
```sh
if sys_interface_check "$VULN_SYSFS_BASE/vuln_name"; then
sys_interface_available=1
status=$ret_sys_interface_check_status
# Override: old kernels (before <commit>) incorrectly reported this as mitigated
if echo "$ret_sys_interface_check_fullmsg" | grep -qi 'Mitigation:.*partial mitigation.*missing piece'; then
status=VULN
msg="Vulnerable: partial mitigation, missing piece (your kernel incorrectly reports this as mitigated, it was fixed in more recent kernels)"
fi
fi
```
When adding a sysfs override, also add an `explain` call in the `else` branch of Phase 4
(where `msg` is non-empty) to tell the user why the kernel says "Mitigated" while the script
reports vulnerable. Additionally, in Phase 2, add a kernel-image grep to inform the user
whether their kernel has the corrected reporting (the post-fix kernel will contain the new
vulnerability string in its image).
**Kernel source inventory:** Before writing any code, audit the kernel source history for
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`.
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
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
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
CPU is affected by the vulnerability (i.e. whether it sets the `X86_BUG_*` flag). This
is what the script must replicate in `is_cpu_affected()`. The kernel typically uses a
combination of:
- **Model blacklists/whitelists**: explicit lists of CPU vendor/family/model/stepping
values (e.g. `cpu_vuln_blacklist[]` in `arch/x86/kernel/cpu/common.c`). These lists
can change between kernel versions — models may be added when new errata surface
(e.g. client Skylake was initially missing from GDS and added in a follow-up commit).
- **MSR/CPUID immunity bits**: hardware bits that the CPU vendor defines to declare
"this hardware is not affected" (e.g. `ARCH_CAP_GDS_NO`, `ARCH_CAP_RDCL_NO`). These
bits are already read in `check_cpu()` and stored as `cap_*_no` globals.
- **Feature dependencies**: some vulnerabilities only apply when a specific CPU feature
is present (e.g. GDS requires AVX because GATHER instructions need it; TAA requires
TSX). If the feature is absent or disabled, the CPU is immune.
- **Vendor scoping**: most vulnerabilities are vendor-specific (Intel-only, AMD-only),
but some span multiple vendors. Document which vendors are checked.
The inventory must trace how this logic evolved across kernel versions, because models
are sometimes added in follow-up commits (as with Skylake for GDS) and the script must
include the most complete and up-to-date list. Document every commit that changed the
model list or the affection conditions.
The script may run on any kernel — from early release candidates that first introduced
support, through every stable release, up to the latest mainline, as well as vendor kernels
(RHEL, SUSE, Ubuntu, etc.). The inventory must catalogue every variant across all of these,
including:
- Messages/configs/functions that only existed briefly between two commits in the same
release cycle.
- Format changes (e.g. field reordering, renamed labels, renamed Kconfig symbols).
- New states added in later kernels (e.g. new flush modes, new mitigation strategies).
- Reporting corrections where a later kernel changed its assessment of what counts as
mitigated (e.g. a message that said `"Mitigation: ..."` in kernel A is reclassified as
`"Vulnerable: ..."` in kernel B under the same conditions).
- Functions that were added, renamed, or split across commits (e.g. a single
`gds_mitigation_update()` later split into `gds_select_mitigation()` +
`gds_apply_mitigation()`).
- CPU model list changes (models added or removed from the vulnerability blacklist in
follow-up commits or stable backports).
Document all discovered variants as comments in the CVE file, grouped by the kernel commit
that introduced or changed them, so future readers can understand the evolution at a glance.
See `src/vulns/CVE-2018-3646.sh` (Phase 1 comment block) for a reference example.
This inventory matters because later kernels may have a different — and more accurate — view
of what is vulnerable versus mitigated for a given vulnerability, as understanding progresses
over time. The script must be able to reach the same conclusions as the most recent kernel,
even when running under an old kernel that misreports a vulnerability as mitigated. This is
exactly what sysfs overrides (described above) are for: when the inventory reveals that an
old kernel's message is now known to be wrong, add an override in Phase 1 to correct the
status, and use the Phase 2 kernel-image grep to tell the user whether their kernel has the
corrected reporting.
**How to build the inventory - git blame walkback method:**
The goal is to find every commit that changed the sysfs output strings, Kconfig symbols,
mitigation function names, or CPU affection logic for a given vulnerability. The method uses
`git blame` iteratively, walking backwards through history until the vulnerability's support
no longer exists.
1. **Locate the relevant code.** Most vulnerability code lives in two files:
`arch/x86/kernel/cpu/bugs.c` (mitigation logic and sysfs reporting) and
`arch/x86/kernel/cpu/common.c` (CPU affection detection). Find:
- The `*_show_state()` function for the vulnerability (e.g. `l1tf_show_state()`,
`mds_show_state()`) and the corresponding `case X86_BUG_*` in `cpu_show_common()`.
Both paths can produce messages: the show_state function handles the mitigated cases,
while `cpu_show_common()` handles `"Not affected"` (common to all bugs) and
`"Vulnerable"` (fallthrough). Some vulnerabilities also use string arrays (e.g.
`l1tf_vmx_states[]`, `spectre_v1_strings[]`) — include those in the audit.
- The `*_select_mitigation()` and `*_apply_mitigation()` functions (or a single
`*_update_mitigation()` in older code). These are the function names that appear in
System.map and can be checked via `$opt_map`.
- The `Kconfig` entries: search `arch/x86/Kconfig` (and `arch/x86/Kconfig.cpu` or
similar) for `CONFIG_*` symbols related to the mitigation. Note every name variant
across kernel versions.
- The **CPU affection detection** in `arch/x86/kernel/cpu/common.c`: find where
`X86_BUG_<name>` is set. This typically involves a lookup in `cpu_vuln_blacklist[]`
(or `cpu_vuln_whitelist[]`) combined with checks on `IA32_ARCH_CAPABILITIES` MSR
bits and CPU feature flags. Document:
- The complete model list (vendor, family, model, stepping ranges).
- Which `ARCH_CAP_*` bits grant immunity (e.g. `ARCH_CAP_GDS_NO`).
- Which CPU features are prerequisites (e.g. AVX for GDS, TSX for TAA).
- Any other conditions (hypervisor detection, microcode version checks, etc.).
- How this logic evolved: models added/removed in follow-up commits.
2. **Blame the current code.** Run `git blame` on the relevant line range:
```
git blame -L<start>,<end> arch/x86/kernel/cpu/bugs.c
```
For each line that contributes to the sysfs output (format strings, string arrays, enum
lookups, conditional branches that select different messages), note the commit hash.
3. **Walk back one commit at a time.** For each commit found in step 2, check the state of
the file **before** that commit to see what changed:
```
git show <commit>^:arch/x86/kernel/cpu/bugs.c | grep -n -A10 '<function_name>'
```
Compare the output strings, format patterns, and conditional logic with the version after
the commit. Record any differences: added/removed/renamed states, reordered fields,
changed conditions.
4. **Repeat until the vulnerability disappears.** Take the oldest commit found and check the
parent. Eventually you reach a version where the `case X86_BUG_*` for this vulnerability
does not exist - that is the boundary.
5. **Watch for non-obvious string changes.** Some commits change the output without touching
the format strings themselves:
- **Condition changes**: A commit may change *when* a branch is taken (e.g. switching from
`cpu_smt_control == CPU_SMT_ENABLED` to `sched_smt_active()`), which changes which
message appears for the same hardware state, even though the strings are identical.
- **Enum additions**: A new entry in a string array (e.g. adding `"flush not necessary"` to
`l1tf_vmx_states[]`) adds a new possible message without changing the format string.
- **Early returns**: Adding or removing an early-return path changes which messages are
reachable (e.g. returning `L1TF_DEFAULT_MSG` for `FLUSH_AUTO` before reaching the VMX
format string).
- **Mechanical changes**: `sprintf` → `sysfs_emit`, `const` qualifications, whitespace
reformats - these do not change strings and can be noted briefly or omitted.
6. **Cross-check with `git log`.** After the blame walkback, run a targeted `git log` to
confirm no commits were missed:
```
git log --all --oneline -- arch/x86/kernel/cpu/bugs.c | xargs -I{} \
sh -c 'git show {} -- arch/x86/kernel/cpu/bugs.c | grep -q "<vuln_name>" && echo {}'
```
Any commit that touches lines mentioning the vulnerability name should already be in
your inventory. If one is missing, inspect it.
7. **Audit the stable tree.** After completing the mainline inventory, repeat the process on
the linux-stable repository (`~/linux-stable`). Stable/LTS branches can carry backports
that differ from mainline in subtle ways:
- **Partial backports**: A stable branch may backport the mitigation but not the VMX
reporting, producing a simpler set of messages than mainline (e.g. 4.4.y has l1tf's
`"PTE Inversion"` but no VMX flush state reporting at all).
- **Stable-only commits**: Maintainers sometimes make stable-specific changes that never
existed in mainline (e.g. renaming a string to match upstream without backporting the
full commit that originally renamed it).
- **Backport batching**: Multiple mainline commits may land in the same stable release,
meaning intermediate formats (that existed briefly between mainline commits) may never
have shipped in any stable release. Note this when it happens - it narrows the set of
messages that real-world kernels can produce, but the script should still handle the
intermediate formats since someone could be running a mainline rc kernel.
- **Missing backports**: Some stable branches reach EOL before a fix is backported (e.g.
the `sched_smt_active()` change was not backported to 4.17.y or 4.18.y). This doesn't
change the strings but can change which message appears for the same hardware state.
Check each LTS/stable branch that was active when the vulnerability's sysfs support was
introduced. A quick way to identify relevant branches:
```
cd ~/linux-stable
for branch in $(git branch -r | grep 'linux-'); do
count=$(git show "$branch:arch/x86/kernel/cpu/bugs.c" 2>/dev/null | grep -c '<vuln_name>')
[ "$count" -gt 0 ] && echo "$branch: $count matches"
done
```
Then for each branch with matches, show the output function and compare it with mainline.
Document stable-specific differences in a separate `--- stable backports ---` section of
the inventory comment.
**Comment format in CVE files:**
The inventory comment goes in Phase 1, right after `sys_interface_check` returns successfully.
Group entries chronologically by commit, newest last. For each commit, show the hash, the
kernel version it appeared in, and the exact message(s)/config(s)/function(s) it introduced
or changed. Use `+` to indicate incremental additions to an enum or format. Example:
```sh
# Kernel source inventory for <vuln>, traced via git blame:
#
# --- sysfs messages ---
# all versions:
# "Not affected" (cpu_show_common, <commit>)
# "Vulnerable" (cpu_show_common fallthrough, <commit>)
#
# <commit> (<version>, <what changed>):
# "Mitigation: <original message>"
# <commit> (<version>, <what changed>):
# "Mitigation: <new message format>"
# <field>: value1 | value2 | value3
# <commit> (<version>, <what changed>):
# <field>: + value4
#
# all messages start with either "Not affected", "Mitigation", or "Vulnerable"
#
# --- Kconfig symbols ---
# <commit> (<version>): CONFIG_ORIGINAL_NAME (y/n)
# <commit> (<version>): renamed to CONFIG_NEW_NAME
# <commit> (<version>): replaced by CONFIG_ANOTHER_NAME (on/off, no force)
# vendor kernels: CONFIG_VENDOR_SPECIFIC_NAME (RHEL 8.x)
#
# --- kernel functions (for $opt_map / System.map) ---
# <commit> (<version>): <vuln>_mitigation_update()
# <commit> (<version>): split into <vuln>_select_mitigation() + <vuln>_apply_mitigation()
#
# --- CPU affection logic (for is_cpu_affected) ---
# <commit> (<version>, initial model list):
# Intel: MODEL_A, MODEL_B, MODEL_C (all steppings)
# Intel: MODEL_D (stepping 0x0 - 0x5 only)
# <commit> (<version>, added missing models):
# Intel: + MODEL_E, MODEL_F
# immunity: ARCH_CAP_<NAME>_NO (bit NN of IA32_ARCH_CAPABILITIES)
# feature dependency: requires <FEATURE> (if absent, CPU is immune)
# vendor scope: Intel only (no AMD/Hygon/other entries)
```
The final line of the sysfs section (`all messages start with ...`) is a summary that helps
verify the grep patterns used to derive `status` from the message are complete.
### Cross-Cutting Features
Several command-line options affect the logic inside `_linux()` checks. New CVE implementations must account for them where relevant.
#### `--explain` (`opt_explain`)
When the user passes `--explain`, the `explain()` function prints actionable "How to fix" remediation advice. Call `explain` whenever reporting a VULN status, so the user knows what concrete steps to take:
```sh
pvulnstatus "$cve" VULN "Neither kernel nor microcode mitigate the vulnerability"
explain "Update your kernel to a version that includes the mitigation, and update your CPU microcode. If you are using a distro, make sure you are up to date."
```
The text should be specific: mention kernel parameters to set (`nosmt`), sysctl knobs to toggle, or which component needs updating. If SMT must be disabled, say so explicitly. Multiple `explain` calls can be made for different failure paths, each tailored to the specific gap found. `explain` is a no-op when `--explain` was not passed, so it is always safe to call.
#### `--paranoid` (`opt_paranoid`)
Paranoid mode raises the bar for what counts as "mitigated". In normal mode, conditional mitigations or partial defenses may be accepted as sufficient. In paranoid mode, only the **maximum security configuration** qualifies as OK.
The most common effect is requiring SMT (Hyper-Threading) to be disabled. For example, MDS and TAA mitigations are considered incomplete in paranoid mode if SMT is still enabled, because a sibling thread could still exploit the vulnerability:
```sh
if [ "$opt_paranoid" != 1 ] || [ "$kernel_smt_allowed" = 0 ]; then
pvulnstatus "$cve" OK "Microcode and kernel mitigate the vulnerability"
else
pvulnstatus "$cve" VULN "Mitigation is active but SMT must be disabled for full protection"
fi
```
Other paranoid-mode effects include requiring unconditional (rather than conditional) L1D flushing, or requiring TSX to be fully disabled. When implementing a new CVE, consider whether there is a stricter configuration that paranoid mode should enforce and add the appropriate `opt_paranoid` branches.
#### `--vmm` (`opt_vmm`)
The `--vmm` option tells the script whether the system is a hypervisor host running untrusted virtual machines. It accepts three values: `auto` (default, auto-detect by looking for `qemu`/`kvm`/`xen` processes), `yes` (force hypervisor mode), or `no` (force non-hypervisor mode). The result is stored in `g_has_vmm` by the `check_has_vmm()` function.
Some vulnerabilities (e.g. L1TF/CVE-2018-3646, ITLBMH/CVE-2018-12207) only matter - or require additional mitigations - when the host is running a hypervisor with untrusted guests. If `g_has_vmm` is 0, the system can be reported as not vulnerable to these VMM-specific aspects:
```sh
if [ "$g_has_vmm" = 0 ]; then
pvulnstatus "$cve" OK "this system is not running a hypervisor"
else
# check hypervisor-specific mitigations (L1D flushing, EPT, etc.)
fi
```
CVEs that need VMM context should call `check_has_vmm` early in their `_linux()` function. Note the interaction with paranoid mode: when `--paranoid` is active and `--vmm` was not explicitly set, the script assumes a hypervisor is present (`g_has_vmm=2`), erring on the side of caution.
### Step 4: Wire Up and Test
1. **Add the CVE to `CVE_REGISTRY`** in `src/libs/002_core_globals.sh` with the correct fields: `CVE-YYYY-NNNNN|JSON_KEY|affected_var_suffix|Complete Name and Aliases`. This is the single source of truth for CVE metadata — it drives `cve2name()`, `is_cpu_affected()`, and the supported CVE list.
2. **Add a `--variant` alias** in `src/libs/230_util_optparse.sh`: add a new `case` entry mapping a short name (e.g. `rfds`, `downfall`) to `opt_cve_list="$opt_cve_list CVE-YYYY-NNNNN"`, and add that short name to the `help)` echo line. The CVE is already selectable via `--cve CVE-YYYY-NNNNN` (this is handled generically by the existing `--cve` parsing code), but the `--variant` alias provides the user-friendly short name.
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.
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.
### Key Rules to Remember
- **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`.
- **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
Every function must have a documentation header immediately above its definition. The format is:
```sh
# <short description of what the function does>
# Sets: <comma-separated list of global variables written by this function>
# Returns: <return value constants or description>
<function_name>()
{
```
**Header lines** (all optional except the description):
| Line | When to include | Example |
|--------------|-----------------|---------|
| Description | Always | `# Read CPUID register value across one or all cores` |
| `# Args:` | When the function takes positional parameters | `# Args: $1=msr_address $2=cpu_index(optional, default 0)` |
| `# Sets:` | When the function writes any `ret_*` or other global variable | `# Sets: ret_read_cpuid_value, ret_read_cpuid_msg` |
| `# Returns:` | When the function uses explicit return codes (constants) | `# Returns: READ_CPUID_RET_OK \| READ_CPUID_RET_ERR \| READ_CPUID_RET_KO` |
| `# Callers:` | **Required** for `_private` (underscore-prefixed) functions | `# Callers: pvulnstatus, pstatus` |
**Rules:**
- The `# Sets:` line is critical - it makes global side effects explicit so any reviewer can immediately see what a function mutates.
- The `# Callers:` line is required for all `_`-prefixed functions. It documents which functions depend on this helper, making it safe to refactor.
- Keep descriptions to one line when possible. If more context is needed, add continuation comment lines before the structured lines.
- Parameter documentation uses `$1=name` format. Append `(optional, default X)` for optional parameters.
- **Exception**: `check_CVE_*` functions (`check_CVE_YYYY_NNNNN`, `_linux`, `_bsd`) are exempt from the documentation header requirement. They are self-explanatory, take no arguments, and live in dedicated `src/vulns/CVE-YYYY-NNNNN.sh` files whose line-3 header already describes the vulnerability.
**Full example:**
```sh
# Read a single MSR register on one CPU core
# Args: $1=msr_address $2=cpu_index(optional, default 0)
# Sets: ret_read_msr_value, ret_read_msr_msg
# Returns: READ_MSR_RET_OK | READ_MSR_RET_ERR | READ_MSR_RET_KO
read_msr()
{
```
**Private function example:**
```sh
# Emit a single CVE result as a JSON object to the batch output buffer
# Args: $1=cve_id $2=status $3=message
# Callers: _record_result
_emit_json()
{
```

674
LICENSE
View File

@@ -1,674 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

23
Makefile Normal file
View File

@@ -0,0 +1,23 @@
SHFMT := shfmt
SHFMT_OPTS := -i 4 -ci -ln bash
OUTPUT := spectre-meltdown-checker.sh
SRC_FILES := $(shell find src -name '*.sh' -type f) build.sh
.PHONY: all build shellcheck fmt fmt-check
all: build shellcheck fmt-check
build:
@./build.sh $(OUTPUT)
shellcheck: $(OUTPUT)
@echo Running shellcheck...
@shellcheck $(OUTPUT)
fmt:
$(SHFMT) -w $(SHFMT_OPTS) $(SRC_FILES)
fmt-check:
@echo Checking formatting...
@$(SHFMT) -d $(SHFMT_OPTS) $(SRC_FILES)

View File

@@ -1,45 +0,0 @@
Spectre & Meltdown Checker
==========================
A simple shell script to tell if your Linux installation is vulnerable against the 3 "speculative execution" CVEs that were made public early 2018.
Without options, it'll inspect your currently running kernel.
You can also specify a kernel image on the command line, if you'd like to inspect a kernel you're not running.
The script will do its best to detect mitigations, including backported non-vanilla patches, regardless of the advertised kernel version number.
## Example of script output
![checker](https://framapic.org/6O4v4AAwMenv/M6J4CFWwsB3z.png)
## Quick summary of the CVEs
**CVE-2017-5753** bounds check bypass (Spectre Variant 1)
- Impact: Kernel & all software
- Mitigation: recompile software *and* kernel with a modified compiler that introduces the LFENCE opcode at the proper positions in the resulting code
- Performance impact of the mitigation: negligible
**CVE-2017-5715** branch target injection (Spectre Variant 2)
- Impact: Kernel
- Mitigation 1: new opcode via microcode update that should be used by up to date compilers to protect the BTB (by flushing indirect branch predictors)
- Mitigation 2: introducing "retpoline" into compilers, and recompile software/OS with it
- Performance impact of the mitigation: high for mitigation 1, medium for mitigation 2, depending on your CPU
**CVE-2017-5754** rogue data cache load (Meltdown)
- Impact: Kernel
- Mitigation: updated kernel (with PTI/KPTI patches), updating the kernel is enough
- Performance impact of the mitigation: low to medium
## Disclaimer
This tool does its best to determine whether your system is immune (or has proper mitigations in place) for the collectively named "speculative execution" vulnerabilities. It doesn't attempt to run any kind of exploit, and can't guarantee that your system is secure, but rather helps you verifying whether your system has the known correct mitigations in place.
However, some mitigations could also exist in your kernel that this script doesn't know (yet) how to detect, or it might falsely detect mitigations that in the end don't work as expected (for example, on backported or modified kernels).
Your system exposure also depends on your CPU. As of now, AMD and ARM processors are marked as immune to some or all of these vulnerabilities (except some specific ARM models). All Intel processors manufactured since circa 1995 are thought to be vulnerable. Whatever processor one uses, one might seek more information from the manufacturer of that processor and/or of the device in which it runs.
The nature of the discovered vulnerabilities being quite new, the landscape of vulnerable processors can be expected to change over time, which is why this script makes the assumption that all CPUs are vulnerable, except if the manufacturer explicitly stated otherwise in a verifiable public announcement.
This tool has been released in the hope that it'll be useful, but don't use it to jump to conclusions about your security.

60
build.sh Executable file
View File

@@ -0,0 +1,60 @@
#!/bin/sh
# vim: set ts=4 sw=4 sts=4 et:
# Assemble spectre-meltdown-checker.sh from src/ fragments.
# Usage: ./build.sh [output_file]
# default output: spectre-meltdown-checker.sh
set -e
SRCDIR="$(dirname "$0")/src"
OUTPUT="${1:-$(dirname "$0")/spectre-meltdown-checker.sh}"
SECTIONS="
libs/*.sh
vulns-helpers/*.sh
vulns/*.sh
main.sh
db/*.sh
"
first=1
for pattern in $SECTIONS; do
# shellcheck disable=SC2086
for file in "$SRCDIR"/$pattern; do
[ -f "$file" ] || continue
# source file marker
relpath="${file#"$SRCDIR"/}"
if [ "$first" = 1 ]; then
# first file (001_core_header.sh): emit verbatim, keeps shebang
cat "$file"
first=0
else
# separator blank line + source marker between fragments
echo ""
echo "# >>>>>> $relpath <<<<<<"
echo ""
# strip accidental shebang on line 1
{
IFS= read -r line
case "$line" in
'#!'*) ;; # skip shebang
*) printf '%s\n' "$line" ;;
esac
cat
} <"$file"
fi
done
done >"$OUTPUT"
chmod +x "$OUTPUT"
# Patch VERSION= with semantic version: X.Y.Z
# X=YY, Y=number of CVE files in src/vulns/, Z=MMDDVAL
# VAL is a 3-digit (000-999) value derived from seconds since midnight UTC
cve_count=$(find "$SRCDIR/vulns" -maxdepth 1 -name '*.sh' -type f | wc -l | tr -d ' ')
epoch=$(date -u +%s)
secs_since_midnight=$((epoch % 86400))
val=$(printf '%03d' $((secs_since_midnight * 1000 / 86400)))
version="$(date -u +%y).${cve_count}.$(date -u +%m%d)${val}"
sed -i "s/^VERSION=.*/VERSION='${version}'/" "$OUTPUT"
echo "Assembled $OUTPUT ($(wc -l <"$OUTPUT") lines, version $version)"

7
dist/Dockerfile vendored Normal file
View File

@@ -0,0 +1,7 @@
FROM alpine:latest
RUN apk --update --no-cache add kmod binutils grep perl zstd wget sharutils unzip sqlite procps coreutils iucode-tool gzip xz bzip2 lz4
COPY spectre-meltdown-checker.sh /
ENTRYPOINT ["/spectre-meltdown-checker.sh"]

321
dist/README.md vendored Normal file
View File

@@ -0,0 +1,321 @@
Spectre & Meltdown Checker
==========================
A self-contained shell script to assess your system's resilience against the several [transient execution](https://en.wikipedia.org/wiki/Transient_execution_CPU_vulnerability) CVEs that were published since early 2018, and give you guidance as to how to mitigate them.
## CVE list
CVE | Name | Aliases
--- | ---- | -------
[CVE-2017-5753](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5753) | Bounds Check Bypass | Spectre V1
[CVE-2017-5715](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715) | Branch Target Injection | Spectre V2
[CVE-2017-5754](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5754) | Rogue Data Cache Load | Meltdown
[CVE-2018-3640](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-3640) | Rogue System Register Read | Variant 3a
[CVE-2018-3639](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-3639) | Speculative Store Bypass | Variant 4, SSB
[CVE-2018-3615](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-3615) | L1 Terminal Fault | Foreshadow (SGX)
[CVE-2018-3620](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-3620) | L1 Terminal Fault | Foreshadow-NG (OS/SMM)
[CVE-2018-3646](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-3646) | L1 Terminal Fault | Foreshadow-NG (VMM)
[CVE-2018-12126](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-12126) | Microarchitectural Store Buffer Data Sampling | MSBDS, Fallout
[CVE-2018-12127](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-12127) | Microarchitectural Load Port Data Sampling | MLPDS, RIDL
[CVE-2018-12130](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-12130) | Microarchitectural Fill Buffer Data Sampling | MFBDS, ZombieLoad
[CVE-2018-12207](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-12207) | Machine Check Exception on Page Size Changes | iTLB Multihit, No eXcuses
[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
[CVE-2023-20569](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-20569) | Return Address Security | Inception, SRSO
[CVE-2023-20588](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-20588) | AMD Division by Zero Speculative Data Leak | DIV0
[CVE-2023-20593](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-20593) | Cross-Process Information Leak | Zenbleed
[CVE-2023-23583](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-23583) | Redundant Prefix Issue | Reptar
[CVE-2023-28746](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-28746) | Register File Data Sampling | RFDS
[CVE-2024-28956](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-28956) | Indirect Target Selection | ITS
[CVE-2024-36350](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-36350) | Transient Scheduler Attack, Store Queue | TSA-SQ
[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
## Am I at risk?
Depending on your situation, the table below answers whether an attacker in a given position can extract data from a given target.
The "Userland → Kernel" column also applies within a VM (VM userland vs. VM kernel), since the same CPU mechanisms are at play regardless of virtualization.
Vulnerability | Userland → Kernel | Userland → Userland | VM → Host | VM → VM | Mitigation
------------ | :---------------: | :-----------------: | :-------: | :-----: | ----------
CVE-2017-5753 (Spectre V1) | 💥 | 💥 | 💥 | 💥 | Recompile everything with LFENCE
CVE-2017-5715 (Spectre V2) | 💥 | 💥 | 💥 | 💥 | Microcode + kernel update (or retpoline)
CVE-2017-5754 (Meltdown) | 💥 | ✅ | ✅ | ✅ | Kernel update
CVE-2018-3640 (Variant 3a) | 💥 | ✅ | ✅ | ✅ | Microcode update
CVE-2018-3639 (Variant 4, SSB) | ✅ | 💥 | ✅ | ✅ | Microcode + kernel update
CVE-2018-3615 (Foreshadow, SGX) | ✅ (3) | ✅ (3) | ✅ (3) | ✅ (3) | Microcode update
CVE-2018-3620 (Foreshadow-NG, OS/SMM) | 💥 | ✅ | ✅ | ✅ | Kernel update
CVE-2018-3646 (Foreshadow-NG, VMM) | ✅ | ✅ | 💥 | 💥 | Kernel update (or disable EPT/SMT)
CVE-2018-12126 (MSBDS, Fallout) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
CVE-2018-12127 (MLPDS, RIDL) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
CVE-2018-12130 (MFBDS, ZombieLoad) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
CVE-2018-12207 (iTLB Multihit, No eXcuses) | ✅ | ✅ | ☠️ | ✅ | Hypervisor update (or disable hugepages)
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)
CVE-2023-20569 (Inception, SRSO) | 💥 | ✅ | 💥 | ✅ | Microcode + kernel update
CVE-2023-20588 (DIV0) | 💥 | 💥 (1) | 💥 | 💥 (1) | Kernel update (+ disable SMT)
CVE-2023-20593 (Zenbleed) | 💥 | 💥 | 💥 | 💥 | Microcode update (or kernel workaround)
CVE-2023-23583 (Reptar) | ☠️ | ☠️ | ☠️ | ☠️ | Microcode update
CVE-2023-28746 (RFDS) | 💥 | ✅ | 💥 | ✅ | Microcode + kernel update
CVE-2024-28956 (ITS) | 💥 | ✅ | 💥 (4) | ✅ | Microcode + kernel update
CVE-2024-36350 (TSA-SQ) | 💥 | 💥 (1) | 💥 | 💥 (1) | Microcode + kernel update
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.
> ✅ Not affected in this scenario.
> ☠️ Denial of service (system crash or unpredictable behavior), no data leak.
> (1) Cross-process leakage requires SMT (Hyper-Threading) to be active — attacker and victim must share a physical core.
> (2) Only leaks RDRAND/RDSEED output, not arbitrary memory; still allows recovering cryptographic material from any victim.
> (3) CVE-2018-3615 (Foreshadow SGX) inverts the normal trust model: the OS reads SGX enclave data. It is irrelevant unless the system runs SGX enclaves, and the attacker must already have OS-level access.
> (4) VM→Host leakage applies only to certain affected CPU models (Skylake-X, Kaby Lake, Comet Lake). Ice Lake, Tiger Lake, and Rocket Lake are only affected for native (user-to-kernel) attacks, not guest-to-host.
## Detailed CVE descriptions
<details>
<summary>Unfold for more detailed CVE descriptions</summary>
**CVE-2017-5753 — Bounds Check Bypass (Spectre Variant 1)**
An attacker can train the branch predictor to mispredict a bounds check, causing the CPU to speculatively access out-of-bounds memory. This affects all software, including the kernel, because any conditional bounds check can potentially be exploited. Mitigation requires recompiling software and the kernel with a compiler that inserts LFENCE instructions (or equivalent speculation barriers like `array_index_nospec`) at the proper positions. The performance impact is negligible because the barriers only apply to specific, targeted code patterns.
**CVE-2017-5715 — Branch Target Injection (Spectre Variant 2)**
An attacker can poison the Branch Target Buffer (BTB) to redirect speculative execution of indirect branches in the kernel, leaking kernel memory. Two mitigation strategies exist: (1) microcode updates providing IBRS (Indirect Branch Restricted Speculation), which flushes branch predictor state on privilege transitions — this has a medium to high performance cost, especially on older hardware; or (2) retpoline, a compiler technique that replaces indirect branches with a construct the speculator cannot exploit — this has a lower performance cost but requires recompiling the kernel and sensitive software.
**CVE-2017-5754 — Rogue Data Cache Load (Meltdown)**
On affected Intel processors, a user process can speculatively read kernel memory despite lacking permission. The CPU eventually raises a fault, but the data leaves observable traces in the cache. Mitigation is entirely kernel-side: Page Table Isolation (PTI/KPTI) unmaps most kernel memory from user-space page tables, so there is nothing to speculatively read. The performance impact is low to medium, mainly from the increased TLB pressure caused by switching page tables on every kernel entry and exit.
**CVE-2018-3640 — Rogue System Register Read (Variant 3a)**
Similar to Meltdown but targeting system registers: an unprivileged process can speculatively read privileged system register values (such as Model-Specific Registers) and exfiltrate them via a side channel. Mitigation requires a microcode update only — no kernel changes are needed. Performance impact is negligible.
**CVE-2018-3639 — Speculative Store Bypass (Variant 4)**
The CPU may speculatively load a value from memory before a preceding store to the same address completes, reading stale data. This primarily affects software using JIT compilation (e.g. JavaScript engines, eBPF), where an attacker can craft code that exploits the store-to-load dependency. No known exploitation against the kernel itself has been demonstrated. Mitigation requires a microcode update (providing the SSBD mechanism) plus a kernel update that allows affected software to opt in to the protection via prctl(). The performance impact is low to medium, depending on how frequently the mitigation is activated.
**CVE-2018-3615 — L1 Terminal Fault (Foreshadow, SGX)**
The original Foreshadow attack targets Intel SGX enclaves. When a page table entry's Present bit is cleared, the CPU may still speculatively use the physical address in the entry to fetch data from the L1 cache, bypassing SGX protections. An attacker can extract secrets (attestation keys, sealed data) from SGX enclaves. Mitigation requires a microcode update that includes modifications to SGX behavior. Performance impact is negligible.
**CVE-2018-3620 — L1 Terminal Fault (Foreshadow-NG, OS/SMM)**
A generalization of Foreshadow beyond SGX: unprivileged user-space code can exploit the same L1TF mechanism to read kernel memory or System Management Mode (SMM) memory. Mitigation requires a kernel update that implements PTE inversion — marking non-present page table entries with invalid physical addresses so the L1 cache cannot contain useful data at those addresses. Performance impact is negligible because PTE inversion is a one-time change to the page table management logic with no runtime overhead.
**CVE-2018-3646 — L1 Terminal Fault (Foreshadow-NG, VMM)**
A guest VM can exploit L1TF to read memory belonging to the host or other guests, because the hypervisor's page tables may have non-present entries pointing to valid host physical addresses still resident in L1. Mitigation options include: flushing the L1 data cache on every VM entry (via a kernel update providing L1d flush support), disabling Extended Page Tables (EPT), or disabling Hyper-Threading (SMT) to prevent a sibling thread from refilling the L1 cache during speculation. The performance impact ranges from low to significant depending on the chosen mitigation, with L1d flushing on VM entry being the most practical but still measurable on VM-heavy workloads.
**CVE-2018-12126 — Microarchitectural Store Buffer Data Sampling (MSBDS, Fallout)**
**CVE-2018-12127 — Microarchitectural Load Port Data Sampling (MLPDS, RIDL)**
**CVE-2018-12130 — Microarchitectural Fill Buffer Data Sampling (MFBDS, ZombieLoad)**
**CVE-2019-11091 — Microarchitectural Data Sampling Uncacheable Memory (MDSUM, RIDL)**
These four CVEs are collectively known as "MDS" (Microarchitectural Data Sampling) vulnerabilities. They exploit different CPU internal buffers — store buffer, fill buffer, load ports, and uncacheable memory paths — that can leak recently accessed data across privilege boundaries during speculative execution. An unprivileged attacker can observe data recently processed by the kernel or other processes. Mitigation requires a microcode update (providing the MD_CLEAR mechanism) plus a kernel update that uses VERW to clear affected buffers on privilege transitions. Disabling Hyper-Threading (SMT) provides additional protection because sibling threads share these buffers. The performance impact is low to significant, depending on the frequency of kernel transitions and whether SMT is disabled.
**CVE-2018-12207 — Machine Check Exception on Page Size Changes (iTLB Multihit, No eXcuses)**
A malicious guest VM can trigger a machine check exception (MCE) — crashing the entire host — by creating specific conditions in the instruction TLB involving page size changes. This is a denial-of-service vulnerability affecting hypervisors running untrusted guests. Mitigation requires either disabling hugepage use in the hypervisor or updating the hypervisor to avoid the problematic iTLB configurations. The performance impact ranges from low to significant depending on the approach: disabling hugepages can substantially impact memory-intensive workloads.
**CVE-2019-11135 — TSX Asynchronous Abort (TAA, ZombieLoad V2)**
On CPUs with Intel TSX, a transactional abort can leave data from the line fill buffers in a state observable through side channels, similar to the MDS vulnerabilities but triggered through TSX. Mitigation requires a microcode update plus kernel support to either clear affected buffers or disable TSX entirely (via the TSX_CTRL MSR). The performance impact is low to significant, similar to MDS, with the option to eliminate the attack surface entirely by disabling TSX at the cost of losing transactional memory support.
**CVE-2020-0543 — Special Register Buffer Data Sampling (SRBDS, CROSSTalk)**
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.
**CVE-2022-29901 — Arbitrary Speculative Code Execution with Return Instructions (Retbleed Intel, RSBA)**
On Intel Skylake through Rocket Lake processors with RSB Alternate Behavior (RSBA), return instructions can be speculatively redirected via the Branch Target Buffer when the Return Stack Buffer underflows, bypassing retpoline mitigations. Mitigation requires either Enhanced IBRS (eIBRS, via microcode update) or a kernel compiled with IBRS-on-entry support (Linux 5.19+). Call depth tracking (stuffing) is an alternative mitigation available from Linux 6.2+. Plain retpoline does NOT mitigate this vulnerability on RSBA-capable CPUs. Performance impact is medium to high.
**CVE-2022-40982 — Gather Data Sampling (GDS, Downfall)**
The AVX GATHER instructions can leak data from previously used vector registers across privilege boundaries through the shared gather data buffer. This affects any software using AVX2 or AVX-512 on vulnerable Intel processors. Mitigation is provided by a microcode update that clears the gather buffer, or alternatively by disabling the AVX feature entirely. Performance impact is negligible for most workloads but can be significant (up to 50%) for AVX-heavy applications such as HPC and AI inference.
**CVE-2023-20569 — Return Address Security (Inception, SRSO)**
On AMD Zen 1 through Zen 4 processors, an attacker can manipulate the return address predictor to redirect speculative execution on return instructions, leaking kernel memory. Mitigation requires both a kernel update (providing SRSO safe-return sequences or IBPB-on-entry) and a microcode update (providing SBPB on Zen 3/4, or IBPB support on Zen 1/2 — which additionally requires SMT to be disabled). Performance impact ranges from low to significant depending on the chosen mitigation and CPU generation.
**CVE-2023-20588 — AMD Division by Zero Speculative Data Leak (DIV0)**
On AMD Zen 1 processors, a #DE (divide-by-zero) exception can leave stale quotient data from a previous division in the divider unit, observable by a subsequent division via speculative side channels. This can leak data across any privilege boundary, including between SMT sibling threads sharing the same physical core. Mitigation requires a kernel update (Linux 6.5+) that adds a dummy division (`amd_clear_divider()`) on every exit to userspace and before VMRUN, preventing stale data from persisting. No microcode update is needed. Disabling SMT provides additional protection because the kernel mitigation does not cover cross-SMT-thread leaks. Performance impact is negligible.
**CVE-2023-20593 — Cross-Process Information Leak (Zenbleed)**
A bug in AMD Zen 2 processors causes the VZEROUPPER instruction to incorrectly zero register files during speculative execution, leaving stale data from other processes observable in vector registers. This can leak data across any privilege boundary, including from the kernel and other processes, at rates up to 30 KB/s per core. Mitigation is available either through a microcode update that fixes the bug, or through a kernel workaround that sets the FP_BACKUP_FIX bit (bit 9) in the DE_CFG MSR, disabling the faulty optimization. Either approach alone is sufficient. Performance impact is negligible.
**CVE-2023-23583 — Redundant Prefix Issue (Reptar)**
A bug in Intel processors causes unexpected behavior when executing instructions with specific redundant REX prefixes. Depending on the circumstances, this can result in a system crash (MCE), unpredictable behavior, or potentially privilege escalation. Any software running on an affected CPU can trigger the bug. Mitigation requires a microcode update. Performance impact is low.
**CVE-2023-28746 — Register File Data Sampling (RFDS)**
On certain Intel Atom and hybrid processors (Goldmont, Goldmont Plus, Tremont, Gracemont, and the Atom cores of Alder Lake and Raptor Lake), the register file can retain stale data from previous operations that is accessible via speculative execution, allowing an attacker to infer data across privilege boundaries. Mitigation requires both a microcode update (providing the RFDS_CLEAR capability) and a kernel update (CONFIG_MITIGATION_RFDS, Linux 6.9+) that uses the VERW instruction to clear the register file on privilege transitions. CPUs with the RFDS_NO capability bit are not affected. Performance impact is low.
**CVE-2024-28956 — Indirect Target Selection (ITS)**
On certain Intel processors (Skylake-X stepping 6+, Kaby Lake, Comet Lake, Ice Lake, Tiger Lake, Rocket Lake), an attacker can train the indirect branch predictor to speculatively execute a targeted gadget in the kernel, bypassing eIBRS protections. The Branch Target Buffer (BTB) uses only partial address bits to index indirect branch targets, allowing user-space code to influence kernel-space speculative execution. Some affected CPUs (Ice Lake, Tiger Lake, Rocket Lake) are only vulnerable to native user-to-kernel attacks, not guest-to-host (VMX) attacks. Mitigation requires both a microcode update (IPU 2025.1 / microcode-20250512+, which fixes IBPB to fully flush indirect branch predictions) and a kernel update (CONFIG_MITIGATION_ITS, Linux 6.15+) that aligns branch/return thunks or uses RSB stuffing. Performance impact is low.
**CVE-2024-36350 — Transient Scheduler Attack, Store Queue (TSA-SQ)**
On AMD Zen 3 and Zen 4 processors, the CPU's transient scheduler may speculatively retrieve stale data from the store queue during certain timing windows, allowing an attacker to infer data from previous store operations across privilege boundaries. The attack can also leak data between SMT sibling threads. Mitigation requires both a microcode update (exposing the VERW_CLEAR capability) and a kernel update (CONFIG_MITIGATION_TSA, Linux 6.16+) that uses the VERW instruction to clear CPU buffers on user/kernel transitions and before VMRUN. The kernel also clears buffers on idle when SMT is active. Performance impact is low to medium.
**CVE-2024-36357 — Transient Scheduler Attack, L1 (TSA-L1)**
On AMD Zen 3 and Zen 4 processors, the CPU's transient scheduler may speculatively retrieve stale data from the L1 data cache during certain timing windows, allowing an attacker to infer data in the L1D cache across privilege boundaries. Mitigation requires the same microcode and kernel updates as TSA-SQ: a microcode update exposing VERW_CLEAR and a kernel update (CONFIG_MITIGATION_TSA, Linux 6.16+) that clears CPU buffers via VERW on privilege transitions. Performance impact is low to medium.
**CVE-2025-40300 — VM-Exit Stale Branch Prediction (VMScape)**
After a guest VM exits to the host, stale branch predictions from the guest can influence host-side speculative execution before the kernel returns to userspace, allowing a local attacker to leak host kernel memory. This affects Intel processors from Sandy Bridge through Arrow Lake/Lunar Lake, AMD Zen 1 through Zen 5 families, and Hygon family 0x18. Only systems running a hypervisor with untrusted guests are at risk. Mitigation requires a kernel update (CONFIG_MITIGATION_VMSCAPE, Linux 6.18+) that issues IBPB before returning to userspace after a VM exit. No specific microcode update is required beyond existing IBPB support. Performance impact is low.
**CVE-2024-45332 — Branch Privilege Injection (BPI)**
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
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.
## 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))
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).
Other operating systems such as MacOS, Windows, ESXi, etc. [will never be supported](doc/FAQ.md#why-is-my-os-not-supported).
Supported architectures:
- `x86` (32 bits)
- `amd64`/`x86_64` (64 bits)
- `ARM` and `ARM64`
- other architectures will work, but mitigations (if they exist) might not always be detected
## Frequently Asked Questions (FAQ)
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.
## Running the script
### Direct way (recommended)
- 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
```
- Inspect the script. You never blindly run scripts you downloaded from the Internet, do you?
```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
```
### Using a docker container
<details>
<summary>Unfold for instructions</summary>
Using `docker compose`:
```shell
docker compose build
docker compose run --rm spectre-meltdown-checker
```
Note that on older versions of docker, `docker-compose` is a separate command, so you might
need to replace the two `docker compose` occurences above by `docker-compose`.
Using `docker build` directly:
```shell
docker build -t spectre-meltdown-checker .
docker run --rm --privileged -v /boot:/boot:ro -v /dev/cpu:/dev/cpu:ro -v /lib/modules:/lib/modules:ro spectre-meltdown-checker
```
</details>
## Example of script output
- AMD EPYC-Milan running under Debian Trixie
![alt text](https://raw.githubusercontent.com/speed47/spectre-meltdown-checker/refs/heads/test/img/smc_amd_epyc_milan.jpg)

145
dist/doc/FAQ.md vendored Normal file
View File

@@ -0,0 +1,145 @@
# Questions
- [What to expect from this tool?](#what-to-expect-from-this-tool)
- [Why was this script written in the first place?](#why-was-this-script-written-in-the-first-place)
- [Why are those vulnerabilities so different than regular CVEs?](#why-are-those-vulnerabilities-so-different-than-regular-cves)
- [What do "affected", "vulnerable" and "mitigated" mean exactly?](#what-do-affected-vulnerable-and-mitigated-mean-exactly)
- [What are the main design decisions regarding this script?](#what-are-the-main-design-decisions-regarding-this-script)
- [Everything is indicated in `sysfs` now, is this script still useful?](#everything-is-indicated-in-sysfs-now-is-this-script-still-useful)
- [How does this script work?](#how-does-this-script-work)
- [Which BSD OSes are supported?](#which-bsd-oses-are-supported)
- [Why is my OS not supported?](#why-is-my-os-not-supported)
- [The tool says there is an updated microcode for my CPU, but I don't have it!](#the-tool-says-there-is-an-updated-microcode-for-my-cpu-but-i-dont-have-it)
- [The tool says that I need a more up-to-date microcode, but I have the more recent version!](#the-tool-says-that-i-need-a-more-up-to-date-microcode-but-i-have-the-more-recent-version)
- [Which rules are governing the support of a CVE in this tool?](#which-rules-are-governing-the-support-of-a-cve-in-this-tool)
# Answers
## What to expect from this tool?
This tool does its best to determine where your system stands on each of the collectively named [transient execution](https://en.wikipedia.org/wiki/Transient_execution_CPU_vulnerability) vulnerabilities (also sometimes called "speculative execution" vulnerabilities) that were made public since early 2018. It doesn't attempt to run any kind of exploit, and can't guarantee that your system is secure, but rather helps you verifying if your system is affected, and if it is, checks whether it has the known mitigations in place to avoid being vulnerable.
Some mitigations could also exist in your kernel that this script doesn't know (yet) how to detect, or it might falsely detect mitigations that in the end don't work as expected (for example, on backported or modified kernels).
Please also note that for Spectre vulnerabilities, all software can possibly be exploited, this tool only verifies that the kernel (which is the core of the system) you're using has the proper protections in place. Verifying all the other software is out of the scope of this tool. As a general measure, ensure you always have the most up to date stable versions of all the software you use, especially for those who are exposed to the world, such as network daemons and browsers.
This tool has been released in the hope that it'll be useful, but don't use it to jump to definitive conclusions about your security: hardware vulnerabilities are [complex beasts](#why-are-those-vulnerabilities-so-different-than-regular-cves), and collective understanding of each vulnerability is evolving with time.
## Why was this script written in the first place?
The first commit of this script is dated *2018-01-07*, only 4 days after the world first heard about the Meltdown and the Spectre attacks. With those attacks disclosure, a _whole new range of vulnerabilities_ that were previously thought to be mostly theoretical and only possible in very controlled environments (labs) - hence of little interest for most except researchers - suddenly became completely mainstream and apparently trivial to conduct on an immensely large number of systems.
On the few hours and days after that date, the whole industry went crazy. Proper, verified information about these vulnerabilities was incredibly hard to find, because before this, even the CPU vendors never had to deal with managing security vulnerabilities at scale, as software vendors do since decades. There were a lot of FUD, and the apparent silence of the vendors was enough for most to fear the worst. The whole industry had everything to learn about this new type of vulnerabilities. However, most systems administrators had a few simple questions:
- Am **I** vulnerable? And if yes,
- What do I have to do to mitigate these vulnerabilities on **my** system?
Unfortunately, answering those questions was very difficult (and still is to some extent), even if the safe answer to the first question was "you probably are". This script was written to try to give simple answers to those simple questions, and was made to evolve as the information about these vulnerabilities became available. On the first few days, there was several new versions published **per day**.
## Why are those vulnerabilities so different than regular CVEs?
Those are hardware vulnerabilities, while most of the CVEs we see everyday are software vulnerabilities. A quick comparison would be:
Software vulnerability:
- Can be fixed? Yes.
- How to fix? Update the software (or uninstall it!)
Hardware vulnerability:
- Can be fixed? No, only mitigated (or buy new hardware!)
- How to ~~fix~~ mitigate? In the worst case scenario, 5 "layers" need to be updated: the microcode/firmware, the host OS kernel, the hypervisor, the VM OS kernel, and possibly all the software running on the machine. Sometimes only a subset of those layers need to be updated. In yet other cases, there can be several possible mitigations for the same vulnerability, implying different layers. Yes, it can get horribly complicated.
A more detailed video explanation is available here: https://youtu.be/2gB9U1EcCss?t=425
## What do "affected", "vulnerable" and "mitigated" mean exactly?
- **Affected** means that your CPU's hardware, as it went out of the factory, is known to be concerned by a specific vulnerability, i.e. the vulnerability applies to your hardware model. Note that it says nothing about whether a given vulnerability can actually be used to exploit your system. However, an unaffected CPU will never be vulnerable, and doesn't need to have mitigations in place.
- **Vulnerable** implies that you're using an **affected** CPU, and means that a given vulnerability can be exploited on your system, because no (or insufficient) mitigations are in place.
- **Mitigated** implies that a previously **vulnerable** system has followed all the steps (updated all the required layers) to ensure a given vulnerability cannot be exploited. About what "layers" mean, see [the previous question](#why-are-those-vulnerabilities-so-different-than-regular-cves).
## What are the main design decisions regarding this script?
There are a few rules that govern how this tool is written.
1) It should be okay to run this script in a production environment. This implies, but is not limited to:
* 1a. Never modify the system it's running on, and if it needs to e.g. load a kernel module it requires, that wasn't loaded before it was launched, it'll take care to unload it on exit
* 1b. Never attempt to "fix" or "mitigate" any vulnerability, or modify any configuration. It just reports what it thinks is the status of your system. It leaves all decisions to the sysadmin.
* 1c. Never attempt to run any kind of exploit to tell whether a vulnerability is mitigated, because it would violate 1a), could lead to unpredictable system behavior, and might even lead to wrong conclusions, as some PoC must be compiled with specific options and prerequisites, otherwise giving wrong information (especially for Spectre). If you want to run PoCs, do it yourself, but please read carefully about the PoC and the vulnerability. PoCs about a hardware vulnerability are way more complicated and prone to false conclusions than PoCs for software vulnerabilities.
2) Never look at the kernel version to tell whether it supports mitigation for a given vulnerability. This implies never hardcoding version numbers in the script. This would defeat the purpose: this script should be able to detect mitigations in unknown kernels, with possibly backported or forward-ported patches. Also, don't believe what `sysfs` says, when possible. See the next question about this.
3) Never look at the microcode version to tell whether it has the proper mechanisms in place to support mitigation for a given vulnerability. This implies never hardcoding version numbers in the script. Instead, look for said mechanisms, as the kernel would do.
4) When a CPU is not known to be explicitly unaffected by a vulnerability, make the assumption that it is. This strong design choice has it roots in the early speculative execution vulnerability days (see [this answer](#why-was-this-script-written-in-the-first-place)), and is still a good approach as of today.
## Everything is indicated in `sysfs` now, is this script still useful?
A lot as changed since 2018. Nowadays, the industry adapted and this range of vulnerabilities is almost "business as usual", as software vulnerabilities are. However, due to their complexity, it's still not as easy as just checking a version number to ensure a vulnerability is closed.
Granted, we now have a standard way under Linux to check whether our system is affected, vulnerable, mitigated against most of these vulnerabilities. By having a look at the `sysfs` hierarchy, and more precisely the `/sys/devices/system/cpu/vulnerabilities/` folder, one can have a pretty good insight about its system state for each of the listed vulnerabilities. Note that the output can be a little different with some vendors (e.g. Red Hat has some slightly different output than the vanilla kernel for some vulnerabilities), but it's still a gigantic leap forward, given where we were in 2018 when this script was started, and it's very good news. The kernel is the proper place to have this because the kernel knows everything about itself (the mitigations it might have), and the CPU (its model, and microcode features that are exposed). Note however that some vulnerabilities are not reported through this file hierarchy at all, such as Zenbleed.
However I see a few reasons why this script might still be useful to you, and that's why its development has not halted when the `sysfs` hierarchy came out:
- A given version of the kernel doesn't have knowledge about the future. To put it in another way: a given version of the kernel only has the understanding of a vulnerability available at the time it was compiled. Let me explain this: when a new vulnerability comes out, new versions of the microcode and kernels are released, with mitigations in place. With such a kernel, a new `sysfs` entry will appear. However, after a few weeks or months, corner cases can be discovered, previously-thought unaffected CPUs can turn out to be affected in the end, and sometimes mitigations can end up being insufficient. Of course, if you're always running the latest kernel version from kernel.org, this issue might be limited for you. The spectre-meltdown-checker script doesn't depend on a kernel's knowledge and understanding of a vulnerability to compute its output. That is, unless you tell it to (using the `--sysfs-only` option).
- Mitigating a vulnerability completely can sometimes be tricky, and have a lot of complicated prerequisites, depending on your kernel version, CPU vendor, model and even sometimes stepping, CPU microcode, hypervisor support, etc. The script gives a very detailed insight about each of the prerequisites of mitigation for every vulnerability, step by step, hence pointing out what is missing on your system as a whole to completely mitigate an issue.
- 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).
- Educational purposes: the script gives interesting insights about a vulnerability, and how the different parts of the system work together to mitigate it.
There are probably other reasons, but that are the main ones that come to mind. In the end, of course, only you can tell whether it's useful for your use case ;)
## How does this script work?
On one hand, the script gathers information about your CPU, and the features exposed by its microcode. To do this, it uses the low-level CPUID instruction (through the `cpuid` kernel module under Linux, and the `cpucontrol` tool under BSD), and queries to the MSR registers of your CPU (through the `msr` kernel module under Linux, and the `cpucontrol` tool under BSD).
On another hand, the script looks into the kernel image your system is running on, for clues about the mitigations it supports. Of course, this is very specific for each operating system, even if the implemented mitigation is functionally the same, the actual code is completely specific. As you can imagine, the Linux kernel code has a few in common with a BSD kernel code, for example. Under Linux, the script supports looking into the kernel image, and possibly the System.map and kernel config file, if these are available. Under BSD, it looks into the kernel file only.
Then, for each vulnerability it knows about, the script decides whether your system is [affected, vulnerable, and mitigated](#what-do-affected-vulnerable-and-mitigated-mean-exactly) against it, using the information it gathered about your hardware and your kernel.
## Which BSD OSes are supported?
For the BSD range of operating systems, the script will work as long as the BSD you're using supports `cpuctl` and `linprocfs`. This is not the case for OpenBSD for example. Known BSD flavors having proper support are: FreeBSD, NetBSD, DragonflyBSD. Derivatives of those should also work. To know why other BSDs will likely never be supported, see [why is my OS not supported?](#why-is-my-os-not-supported).
## Why is my OS not supported?
This tool only supports Linux, and [some flavors of BSD](#which-bsd-oses-are-supported). Other OSes will most likely never be supported, due to [how this script works](#how-does-this-script-work). It would require implementing these OSes specific way of querying the CPU. It would also require to get documentation (if available) about how this OS mitigates each vulnerability, down to this OS kernel code, and if documentation is not available, reverse-engineer the difference between a known old version of a kernel, and a kernel that mitigates a new vulnerability. This means that all the effort has to be duplicated times the number of supported OSes, as everything is specific, by construction. It also implies having a deep understanding of every OS, which takes years to develop. However, if/when other tools appear for other OSes, that share the same goal of this one, they might be listed here as a convenience.
## The tool says there is an updated microcode for my CPU, but I don't have it!
Even if your operating system is fully up to date, the tool might still tell you that there is a more recent microcode version for your CPU. Currently, it uses (and merges) information from 4 sources:
- The official [Intel microcode repository](https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files)
- The awesome platomav's [MCExtractor database](https://github.com/platomav/MCExtractor) for non-Intel CPUs
- The official [linux-firmware](https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git) repository for AMD
- Specific Linux kernel commits that sometimes hardcode microcode versions, such as for [Zenbleed](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=522b1d69219d8f083173819fde04f994aa051a98) or for the bad [Spectre](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/intel.c#n141) microcodes
Generally, it means a more recent version of the microcode has been seen in the wild. However, fully public availability of this microcode might be limited yet, or your OS vendor might have chosen not to ship this new version (yet), maybe because it's currently being tested, or for other reasons. This tool can't tell you when or if this will be the case. You should ask your vendor about it. Technically, you can still go and upgrade your microcode yourself, and use this tool to confirm whether you did it successfully. Updating the microcode for you is out of the scope of this tool, as this would violate [rule 1b](#what-are-the-main-design-decisions-regarding-this-script).
## The tool says that I need a more up-to-date microcode, but I have the more recent version!
This can happen for a few reasons:
- Your CPU is no longer supported by the vendor. In that case, new versions of the microcode will never be published, and vulnerabilities requiring microcode features will never be fixed. On most of these vulnerabilities, you'll have no way to mitigate the issue on a vulnerable system, appart from buying a more recent CPU. Sometimes, you might be able to mitigate the issue by disabling a CPU feature instead (often at the cost of speed). When this is the case, the script will list this as one of the possible mitigations for the vulnerability.
- The vulnerability is recent, and your CPU has not yet received a microcode update for the vendor. Often, these updates come in batches, and it can take several batches to cover all the supported CPUs.
In both cases, you can contact your vendor to know whether there'll be an update or not, and if yes, when. For Intel, at the time this FAQ entry was written, such guidance was [available here](https://software.intel.com/content/www/us/en/develop/topics/software-security-guidance/processors-affected-consolidated-product-cpu-model.html).
## Which rules are governing the support of a CVE in this tool?
On the early days, it was easy: just Spectre and Meltdown (hence the tool name), because that's all we had. Now that this range of vulnerability is seeing a bunch of newcomers every year, this question is legitimate.
To stick with this tool's goal, a good indication as to why a CVE should be supported, is when mitigating it requires either kernel modifications, microcode modifications, or both.
Counter-examples include (non-exhaustive list):
- [CVE-2019-14615](https://github.com/speed47/spectre-meltdown-checker/issues/340), mitigating this issue is done by updating the Intel driver. This is out of the scope of this tool.
- [CVE-2019-15902](https://github.com/speed47/spectre-meltdown-checker/issues/304), this CVE is due to a bad backport in the stable kernel. If the faulty backport was part of the mitigation of another supported CVE, and this bad backport was detectable (without hardcoding kernel versions, see [rule 2](#why-are-those-vulnerabilities-so-different-than-regular-cves)), it might have been added as a bullet point in the concerned CVE's section in the tool. However, this wasn't the case.
- The "[Take A Way](https://github.com/speed47/spectre-meltdown-checker/issues/344)" vulnerability, AMD said that they believe this is not a new attack, hence there were no microcode and no kernel modification made. As there is nothing to look for, this is out of the scope of this tool.
- [CVE-2020-0550](https://github.com/speed47/spectre-meltdown-checker/issues/347), the vendor thinks this is hardly exploitable in the wild, and as mitigations would be too performance impacting, as a whole the industry decided to not address it. As there is nothing to check for, this is out of the scope of this tool.
- [CVE-2020-0551](https://github.com/speed47/spectre-meltdown-checker/issues/348), the industry decided to not address it, as it is believed mitigations for other CVEs render this attack practically hard to make, Intel just released an updated SDK for SGX to help mitigate the issue, but this is out of the scope of this tool.
Look for the [information](https://github.com/speed47/spectre-meltdown-checker/issues?q=is%3Aissue+is%3Aopen+label%3Ainformation) tag in the issues list for more examples.

309
dist/doc/UNSUPPORTED_CVE_LIST.md vendored Normal file
View File

@@ -0,0 +1,309 @@
# Unsupported CVEs
This document lists transient execution CVEs that have been evaluated and determined to be **out of scope** for this tool. See the [Which rules are governing the support of a CVE in this tool?](dist/FAQ.md#which-rules-are-governing-the-support-of-a-cve-in-this-tool) section in the FAQ for the general policy.
CVEs are grouped by reason for exclusion:
- [Already covered by an existing CVE check](#already-covered-by-an-existing-cve-check) — subvariants or subsets whose mitigations are already detected under a parent CVE.
- [No kernel or microcode mitigations to check](#no-kernel-or-microcode-mitigations-to-check) — no fix has been issued, or the mitigation is not detectable by this tool.
- [Not a transient/speculative execution vulnerability](#not-a-transientspeculative-execution-vulnerability) — wrong vulnerability class entirely.
---
# Already covered by an existing CVE check
These CVEs are subvariants or subsets of vulnerabilities already implemented in the tool. Their mitigations are detected as part of the parent CVE's checks.
## CVE-2018-3693 — Bounds Check Bypass Store (Spectre v1.1)
- **Issue:** [#236](https://github.com/speed47/spectre-meltdown-checker/issues/236)
- **Red Hat advisory:** [Speculative Store Bypass / Bounds Check Bypass (CVE-2018-3693)](https://access.redhat.com/solutions/3523601)
- **CVSS:** 5.6 (Medium)
- **Covered by:** CVE-2017-5753 (Spectre V1)
A subvariant of Spectre V1 where speculative store operations can write beyond validated buffer boundaries before the bounds check resolves, allowing an attacker to alter cache state and leak information via side channels.
**Why out of scope:** The mitigations are identical to CVE-2017-5753 (Spectre V1): `lfence` instructions after bounds checks and `array_index_nospec()` barriers in kernel code. There is no separate sysfs entry, no new CPU feature flag, and no distinct microcode change. This tool's existing CVE-2017-5753 checks already detect these mitigations (`__user pointer sanitization`, `usercopy/swapgs barriers`), so CVE-2018-3693 is fully covered as part of Spectre V1.
## CVE-2018-15572 — SpectreRSB (Return Stack Buffer)
- **Issue:** [#224](https://github.com/speed47/spectre-meltdown-checker/issues/224)
- **Research paper:** [Spectre Returns! Speculation Attacks using the Return Stack Buffer (WOOT'18)](https://arxiv.org/abs/1807.07940)
- **Kernel fix:** [commit fdf82a7856b3](https://github.com/torvalds/linux/commit/fdf82a7856b32d905c39afc85e34364491e46346) (Linux 4.18.1)
- **CVSS:** 6.5 (Medium)
- **Covered by:** CVE-2017-5715 (Spectre V2)
The `spectre_v2_select_mitigation` function in the Linux kernel before 4.18.1 did not always fill the RSB upon a context switch, allowing userspace-to-userspace SpectreRSB attacks on Skylake+ CPUs where an empty RSB falls back to the BTB.
**Why out of scope:** This CVE is a Spectre V2 mitigation gap (missing RSB filling on context switch), not a distinct hardware vulnerability. It is already fully covered by this tool's CVE-2017-5715 (Spectre V2) checks, which detect whether the kernel performs RSB filling on CPUs vulnerable to RSB underflow (Skylake+ and RSBA-capable CPUs). A missing RSB fill is flagged as a caveat ("RSB filling missing on Skylake+") in the Spectre V2 verdict.
## CVE-2019-1125 — Spectre SWAPGS gadget
- **Issue:** [#301](https://github.com/speed47/spectre-meltdown-checker/issues/301)
- **Kernel fix:** [commit 18ec54fdd6d1](https://github.com/torvalds/linux/commit/18ec54fdd6d18d92025af097cd042a75cf0ea24c) (Linux 5.3)
- **CVSS:** 5.6 (Medium)
- **Covered by:** CVE-2017-5753 (Spectre V1)
A Spectre V1 subvariant where the `SWAPGS` instruction can be speculatively executed on x86 CPUs, allowing an attacker to leak kernel memory via a side channel on the GS segment base value.
**Why out of scope:** This is a Spectre V1 subvariant whose mitigation (SWAPGS barriers) shares the same sysfs entry as CVE-2017-5753. This tool's existing CVE-2017-5753 checks already detect SWAPGS barriers: a mitigated kernel reports `"Mitigation: usercopy/swapgs barriers and __user pointer sanitization"`, while a kernel lacking the fix reports `"Vulnerable: __user pointer sanitization and usercopy barriers only; no swapgs barriers"`. CVE-2019-1125 is therefore fully covered as part of Spectre V1.
## CVE-2021-26341 — AMD Straight-Line Speculation (direct branches)
- **Bulletin:** [AMD-SB-1026](https://www.amd.com/en/resources/product-security/bulletin/amd-sb-1026.html)
- **Affected CPUs:** AMD Zen 1, Zen 2
- **CVSS:** 6.5 (Medium)
- **Covered by:** CVE-0000-0001 (SLS supplementary check)
AMD Zen 1/Zen 2 CPUs may transiently execute instructions beyond unconditional direct branches (JMP, CALL), potentially allowing information disclosure via side channels.
**Why out of scope:** This is the AMD-specific direct-branch subset of the broader Straight-Line Speculation (SLS) class. The kernel mitigates it via `CONFIG_MITIGATION_SLS` (formerly `CONFIG_SLS`), which enables the GCC flag `-mharden-sls=all` to insert INT3 after unconditional control flow instructions. Since this is a compile-time-only mitigation with no sysfs interface, no MSR, and no per-CVE CPU feature flag, it cannot be checked using the standard CVE framework. A supplementary SLS check is available via `--extra` mode, which covers this CVE's mitigation as well.
## CVE-2020-13844 — ARM Straight-Line Speculation
- **Advisory:** [ARM Developer Security Update (June 2020)](https://developer.arm.com/Arm%20Security%20Center/Speculative%20Processor%20Vulnerability)
- **Affected CPUs:** Cortex-A32, A34, A35, A53, A57, A72, A73, and broadly all speculative Armv8-A cores
- **CVSS:** 5.5 (Medium)
- **Covered by:** CVE-0000-0001 (SLS supplementary check)
ARM processors may speculatively execute instructions past unconditional control flow changes (RET, BR, BLR). GCC and Clang support `-mharden-sls=all` for aarch64, but the Linux kernel never merged the patches to enable it: a `CONFIG_HARDEN_SLS_ALL` series was submitted in 2021 but rejected upstream.
**Why out of scope:** This is the ARM-specific subset of the broader Straight-Line Speculation (SLS) class. The supplementary SLS check available via `--extra` mode detects affected ARM CPU models and reports that no kernel mitigation is currently available.
## CVE-2024-2201 — Native BHI (Branch History Injection without eBPF)
- **Issue:** [#491](https://github.com/speed47/spectre-meltdown-checker/issues/491)
- **Research:** [InSpectre Gadget / Native BHI (VUSec)](https://www.vusec.net/projects/native-bhi/)
- **Intel advisory:** [Branch History Injection (Intel)](https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/branch-history-injection.html)
- **Affected CPUs:** Intel CPUs with eIBRS (Ice Lake+, 10th gen+, and virtualized Intel guests)
- **CVSS:** 4.7 (Medium)
- **Covered by:** CVE-2017-5715 (Spectre V2)
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.
## CVE-2020-0549 — L1D Eviction Sampling (CacheOut)
- **Issue:** [#341](https://github.com/speed47/spectre-meltdown-checker/issues/341)
- **Advisory:** [INTEL-SA-00329](https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/l1d-eviction-sampling.html)
- **Affected CPUs:** Intel Skylake through 10th gen (Tiger Lake+ not affected)
- **CVSS:** 6.5 (Medium)
- **Covered by:** CVE-2018-12126 / CVE-2018-12127 / CVE-2018-12130 / CVE-2019-11091 (MDS) and CVE-2018-3646 (L1TF)
An Intel-specific data leakage vulnerability where L1 data cache evictions can be exploited in combination with MDS or TAA side channels to leak data across security boundaries.
**Why out of scope:** The June 2020 microcode update that addresses this CVE does not introduce any new MSR bits or CPUID flags — it reuses the existing MD_CLEAR (`CPUID.7.0:EDX[10]`) and L1D_FLUSH (`MSR_IA32_FLUSH_CMD`, 0x10B) infrastructure already deployed for MDS and L1TF. The Linux kernel has no dedicated sysfs entry in `/sys/devices/system/cpu/vulnerabilities/` for this CVE; instead, it provides an opt-in per-task L1D flush via `prctl(PR_SPEC_L1D_FLUSH)` and the `l1d_flush=on` boot parameter, which piggyback on the same L1D flush mechanism checked by the existing L1TF and MDS vulnerability modules. In practice, a system with up-to-date microcode and MDS/L1TF mitigations in place is already protected against L1D Eviction Sampling.
## CVE-2025-20623 — Shared Microarchitectural Predictor State (10th Gen Intel)
- **Advisory:** [INTEL-SA-01247](https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-01247.html)
- **Affected CPUs:** Intel 10th Generation Core Processors only
- **CVSS:** 5.6 (Medium)
- **Covered by:** CVE-2024-45332 (BPI)
Shared microarchitectural predictor state on 10th generation Intel CPUs may allow information disclosure.
**Why out of scope:** Very narrow scope (single CPU generation). Mitigated by the same microcode update as CVE-2024-45332 (BPI) and handled through the existing Spectre V2 framework. No dedicated sysfs entry or kernel mitigation beyond what BPI already provides.
## CVE-2025-24495 — Lion Cove BPU Initialization
- **Advisory:** [INTEL-SA-01322](https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-01322.html)
- **Research:** [Training Solo (VUSec)](https://www.vusec.net/projects/training-solo/)
- **Affected CPUs:** Intel Core Ultra with Lion Cove core only (Lunar Lake, Arrow Lake)
- **CVSS:** 6.8 (Medium, CVSS v4)
- **Covered by:** CVE-2024-28956 (ITS)
A branch predictor initialization issue specific to Intel's Lion Cove microarchitecture, discovered as part of the "Training Solo" research.
**Why out of scope:** This is a subset of the ITS (Indirect Target Selection) vulnerability (CVE-2024-28956). It shares the same sysfs entry (`/sys/devices/system/cpu/vulnerabilities/indirect_target_selection`) and kernel mitigation framework. Since ITS (CVE-2024-28956) is implemented in this tool, Lion Cove BPU is already covered automatically.
---
# No kernel or microcode mitigations to check
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)
- **Research paper:** [BranchScope (ASPLOS 2018)](http://www.cs.ucr.edu/~nael/pubs/asplos18.pdf)
- **Red Hat bug:** [#1561794](https://bugzilla.redhat.com/show_bug.cgi?id=1561794)
- **CVSS:** 5.6 (Medium)
A speculative execution attack exploiting the directional branch predictor, allowing an attacker to infer data by manipulating the shared branch prediction state (pattern history table). Initially demonstrated on Intel processors.
**Why out of scope:** No kernel or microcode mitigations have been issued. Red Hat closed their tracking bug as "CLOSED CANTFIX", concluding that "this is a hardware processor issue, not a Linux kernel flaw" and that "it is specific to a target software which uses sensitive information in branching expressions." The mitigation responsibility falls on individual software to avoid using sensitive data in conditional branches, which is out of the scope of this tool.
## CVE-2019-15902 — Spectre V1 backport regression
- **Issue:** [#304](https://github.com/speed47/spectre-meltdown-checker/issues/304)
- **CVSS:** 5.6 (Medium)
A backporting mistake in Linux stable/longterm kernel versions (4.4.x through 4.4.190, 4.9.x through 4.9.190, 4.14.x through 4.14.141, 4.19.x through 4.19.69, and 5.2.x through 5.2.11) swapped two code lines in `ptrace_get_debugreg()`, placing the `array_index_nospec()` call after the array access instead of before, reintroducing a Spectre V1 vulnerability.
**Why out of scope:** This is a kernel bug (bad backport), not a hardware vulnerability. The flawed code is not detectable on a running kernel without hardcoding kernel version ranges, which is against this tool's design principles. As the tool author noted: "it's going to be almost impossible to detect it on a running kernel."
## CVE-2020-12965 — Transient Execution of Non-Canonical Accesses (SLAM)
- **Issue:** [#478](https://github.com/speed47/spectre-meltdown-checker/issues/478)
- **Bulletin:** [AMD-SB-1010](https://www.amd.com/en/corporate/product-security/bulletin/amd-sb-1010)
- **Research paper:** [SLAM (VUSec)](https://www.vusec.net/projects/slam/)
- **CVSS:** 7.5 (High)
AMD CPUs may transiently execute non-canonical loads and stores using only the lower 48 address bits, potentially resulting in data leakage. The SLAM research (2023) demonstrated that this could be exploited on existing AMD Zen+/Zen2 CPUs and could also affect future CPUs with Intel LAM, AMD UAI, or ARM TBI features.
**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)
- **Bulletin:** [AMD-SB-1017](https://www.amd.com/en/resources/product-security/bulletin/amd-sb-1017.html)
- **Research paper:** [AMD Prefetch Attacks through Power and Time (USENIX Security '22)](https://www.usenix.org/conference/usenixsecurity22/presentation/lipp)
- **CVSS:** 5.5 (Medium)
The x86 PREFETCH instruction on AMD CPUs leaks timing and power information, enabling a microarchitectural KASLR bypass from unprivileged userspace. The researchers demonstrated kernel address space layout recovery and kernel memory leakage at ~52 B/s using Spectre gadgets.
**Why out of scope:** AMD acknowledged the research but explicitly stated they are "not recommending any mitigations at this time," as the attack leaks kernel address layout information (KASLR bypass) but does not directly leak kernel data across address space boundaries. KPTI was never enabled on AMD by default in the Linux kernel as a result. No microcode, kernel, or sysfs mitigations have been issued, leaving nothing for this script to check.
## CVE-2024-7881 — ARM Prefetcher Privilege Escalation
- **Affected CPUs:** Specific ARM cores only
- **CVSS:** 5.1 (Medium)
The prefetch engine on certain ARM cores can fetch data from privileged memory locations. Mitigation is disabling the affected prefetcher via the `CPUACTLR6_EL1[41]` register bit.
**Why out of scope:** ARM-specific with very narrow scope and no Linux sysfs integration. The mitigation is a per-core register tweak, not a kernel or microcode update detectable by this tool.
## CVE-2024-36348 — AMD Transient Scheduler Attack (UMIP bypass)
- **Bulletin:** [AMD-SB-7029](https://www.amd.com/en/resources/product-security/bulletin/amd-sb-7029.html)
- **CVSS:** 3.8 (Low)
A transient execution vulnerability in some AMD processors may allow a user process to speculatively infer CPU configuration registers even when UMIP is enabled.
**Why out of scope:** AMD has determined that "leakage of CPU Configuration 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.
## CVE-2024-36349 — AMD Transient Scheduler Attack (TSC_AUX leak)
- **Bulletin:** [AMD-SB-7029](https://www.amd.com/en/resources/product-security/bulletin/amd-sb-7029.html)
- **CVSS:** 3.8 (Low)
A transient execution vulnerability in some AMD processors may allow a user process to infer TSC_AUX even when such a read is disabled.
**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)
- **Research paper:** [Defeating Cache Side-channel Protections with TLB Attacks (VUSec, USENIX Security '18)](https://www.vusec.net/projects/tlbleed/)
- **Red Hat blog:** [Temporal side-channels and you: Understanding TLBleed](https://www.redhat.com/en/blog/temporal-side-channels-and-you-understanding-tlbleed)
- **Affected CPUs:** Intel CPUs with Hyper-Threading (demonstrated on Skylake, Coffee Lake, Broadwell Xeon)
A timing side-channel attack exploiting the shared Translation Lookaside Buffer (TLB) on Intel hyperthreaded CPUs. By using machine learning to analyze TLB hit/miss timing patterns, an attacker co-located on the same physical core can extract cryptographic keys (demonstrated with 99.8% success rate on a 256-bit EdDSA key). OpenBSD disabled Hyper-Threading by default in response.
**Why out of scope:** No CVE was ever assigned — Intel explicitly declined to request one. Intel stated the attack is "not related to Spectre or Meltdown" and has no plans to issue a microcode fix, pointing to existing constant-time coding practices in cryptographic software as the appropriate defense. No Linux kernel mitigation was ever merged. Red Hat's guidance was limited to operational advice (disable SMT, use CPU pinning) rather than a software fix. The only OS-level response was OpenBSD disabling Hyper-Threading by default. With no CVE, no microcode update, and no kernel mitigation, there is nothing for this script to check.
---
# Not a transient/speculative execution vulnerability
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)
- **Bulletin:** [AMD-SB-7014](https://www.amd.com/en/resources/product-security/bulletin/amd-sb-7014.html)
- **Research:** [AMD SinkClose (IOActive, DEF CON 32)](https://www.ioactive.com/resources/amd-sinkclose-universal-ring-2-privilege-escalation)
- **Affected CPUs:** AMD Zen 15 (EPYC, Ryzen, Threadripper, Embedded)
- **CVSS:** 7.5 (High)
Improper validation in a model-specific register (MSR) allows a program with ring 0 (kernel) access to modify System Management Mode (SMM) configuration while SMI lock is enabled, escalating privileges from ring 0 to ring -2 (SMM). AMD provides two mitigation paths: BIOS/AGESA firmware updates (all product lines) and hot-loadable microcode updates (EPYC server processors only).
**Why out of scope:** Not a transient or speculative execution vulnerability — this is a privilege escalation via MSR manipulation, with no side-channel component. It requires ring 0 access as a prerequisite, fundamentally different from Spectre/Meltdown-class attacks where unprivileged code can leak data across privilege boundaries. There is no Linux kernel sysfs entry and no kernel-side mitigation. Although AMD provides hot-loadable microcode for some EPYC processors, the client and embedded product lines are mitigated only through BIOS firmware updates, which this tool cannot detect.
## CVE-2024-56161 — EntrySign (AMD Microcode Signature Bypass)
- **Affected CPUs:** AMD Zen 1-5
- **CVSS:** 7.2 (High)
A weakness in AMD's microcode signature verification (AES-CMAC hash) allows loading arbitrary unsigned microcode with administrator privileges.
**Why out of scope:** This is a microcode integrity/authentication issue, not a speculative execution vulnerability. It does not involve transient execution side channels and is outside the scope of this tool.
## CVE-2025-29943 — StackWarp (AMD SEV-SNP)
- **Affected CPUs:** AMD Zen 1-5
- **CVSS:** Low
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.

393
dist/doc/batch_json.md vendored Normal file
View File

@@ -0,0 +1,393 @@
# 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.

382
dist/doc/batch_json.schema.json vendored Normal file
View File

@@ -0,0 +1,382 @@
{
"$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 Normal file
View File

@@ -0,0 +1,154 @@
# 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`

413
dist/doc/batch_prometheus.md vendored Normal file
View File

@@ -0,0 +1,413 @@
# 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.

13
dist/docker-compose.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
services:
spectre-meltdown-checker:
build:
context: ./
dockerfile: ./Dockerfile
image: spectre-meltdown-checker:latest
container_name: spectre-meltdown-checker
privileged: true
network_mode: none
volumes:
- /boot:/boot:ro
- /dev/cpu:/dev/cpu:ro
- /lib/modules:/lib/modules:ro

BIN
img/smc_amd_epyc_milan.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

80
scripts/update_intel_models.sh Executable file
View File

@@ -0,0 +1,80 @@
#!/bin/sh
# vim: set ts=4 sw=4 sts=4 et:
# Download and parse Linux kernel's intel-family.h to generate src/libs/003_intel_models.sh.
# Usage: scripts/update_intel_models.sh
set -eu
SCRIPTDIR="$(cd "$(dirname "$0")" && pwd)"
REPODIR="$(dirname "$SCRIPTDIR")"
OUTFILE="$REPODIR/src/libs/003_intel_models.sh"
URL="https://raw.githubusercontent.com/torvalds/linux/refs/heads/master/arch/x86/include/asm/intel-family.h"
TMPFILE=$(mktemp /tmp/intel-family-XXXXXX.h)
trap 'rm -f "$TMPFILE"' EXIT INT TERM
echo "Downloading $URL ..."
wget -q -O "$TMPFILE" "$URL"
echo "Parsing intel-family.h ..."
{
cat <<'HEADER'
# vim: set ts=4 sw=4 sts=4 et:
# AUTO-GENERATED FILE — DO NOT EDIT MANUALLY.
# Generated by scripts/update_intel_models.sh from:
# https://raw.githubusercontent.com/torvalds/linux/refs/heads/master/arch/x86/include/asm/intel-family.h
# Run scripts/update_intel_models.sh to refresh when new Intel CPU families are added to the kernel.
# shellcheck disable=SC2034
{
HEADER
awk '
/^#define INTEL_[A-Z0-9_]+[[:space:]]+IFM\(/ {
name = $2
# Skip wildcard and notational markers
if (name == "INTEL_ANY") next
if (name ~ /_START$/) next
if (name ~ /_LAST$/) next
# Extract the IFM(...) argument string
line = $0
sub(/.*IFM\(/, "", line) # line is now: "N, 0xNN) ..."
# Extract family
family = line
sub(/,.*/, "", family)
gsub(/[[:space:]]/, "", family)
# Skip non-numeric families (e.g. X86_FAMILY_ANY)
if (family !~ /^[0-9]+$/) next
# Extract model
rest = line
sub(/^[^,]+, */, "", rest) # remove "N, "
model = rest
sub(/\).*/, "", model)
gsub(/[[:space:]]/, "", model)
# Extract optional C comment and convert to shell comment
comment = ""
if (index($0, "/*") > 0) {
c = $0
sub(/.*\/\*/, "/* ", c)
gsub(/ +/, " ", c)
sub(/ *\*\/.*/, " */", c)
comment = "\t# " c
}
# Strip INTEL_ prefix; prepend INTEL_FAM<family>_
sub(/^INTEL_/, "", name)
varname = "INTEL_FAM" family "_" name
printf "\treadonly %s=$(( %s ))%s\n", varname, model, comment
}
' "$TMPFILE"
printf '}\n'
} | shfmt -i 4 -ci -ln bash > "$OUTFILE"
echo "Generated $OUTFILE ($(wc -l < "$OUTFILE") lines)"

File diff suppressed because it is too large Load Diff

153
src/db/100_inteldb.sh Normal file
View File

@@ -0,0 +1,153 @@
# %%% 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
#
# N: Not affected
# S: Affected, software fix
# H: Affected, hardware fix
# 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)
#
# %%% 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,
# 0x00030673,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,
# 0x00030678,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,
# 0x00030679,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,
# 0x000306A9,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,
# 0x000306C3,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,
# 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,
# 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,
# 0x000406A0,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,
# 0x000406C3,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,
# 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,
# 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,
# 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,
# 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,
# 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,
# 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,
# 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,
# 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,
# 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,
# 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,
# 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,
# 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,
# 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,
# 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,
# 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,
# 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,
#
# %%% ENDOFINTELDB

613
src/db/200_mcedb.sh Normal file
View File

@@ -0,0 +1,613 @@
# vim: set ts=4 sw=4 sts=4 et:
# We're using MCE.db from the excellent platomav's MCExtractor project
# The builtin version follows, but the user can download an up-to-date copy (to be stored in their $HOME) by using --update-fwdb
# To update the builtin version itself (by *modifying* this very file), use --update-builtin-fwdb
#
# The format below is:
# X,CPUID_HEX,MICROCODE_VERSION_HEX,YYYYMMDD
# with X being either I for Intel, or A for AMD
# When the date is unknown it defaults to 20000101
# %%% MCEDB v349+i20260227+615b
# I,0x00000611,0xFF,0x00000B27,19961218
# I,0x00000612,0xFF,0x000000C6,19961210
# I,0x00000616,0xFF,0x000000C6,19961210
# I,0x00000617,0xFF,0x000000C6,19961210
# I,0x00000619,0xFF,0x000000D2,19980218
# I,0x00000630,0xFF,0x00000013,19960827
# I,0x00000632,0xFF,0x00000020,19960903
# I,0x00000633,0xFF,0x00000036,19980923
# I,0x00000634,0xFF,0x00000037,19980923
# I,0x00000650,0x01,0x00000040,19990525
# I,0x00000650,0x02,0x00000041,19990525
# I,0x00000650,0x08,0x00000045,19990525
# I,0x00000651,0x01,0x00000040,19990525
# I,0x00000652,0x01,0x0000002A,19990512
# I,0x00000652,0x02,0x0000002C,19990517
# I,0x00000652,0x04,0x0000002B,19990512
# I,0x00000653,0x01,0x00000010,19990628
# I,0x00000653,0x02,0x0000000C,19990518
# I,0x00000653,0x04,0x0000000B,19990520
# I,0x00000653,0x08,0x0000000D,19990518
# I,0x00000660,0x01,0x0000000A,19990505
# I,0x00000665,0x10,0x00000003,19990505
# I,0x0000066A,0x02,0x0000000C,19990505
# I,0x0000066A,0x08,0x0000000D,19990505
# I,0x0000066A,0x20,0x0000000B,19990505
# I,0x0000066D,0x02,0x00000005,19990312
# I,0x0000066D,0x08,0x00000006,19990312
# I,0x0000066D,0x20,0x00000007,19990505
# I,0x00000670,0xFF,0x00000007,19980602
# I,0x00000671,0x04,0x00000014,19980811
# I,0x00000672,0x04,0x00000038,19990922
# I,0x00000673,0x04,0x0000002E,19990910
# I,0x00000680,0xFF,0x00000017,19990610
# I,0x00000681,0x01,0x0000000D,19990921
# I,0x00000681,0x04,0x00000010,19990921
# I,0x00000681,0x08,0x0000000F,19990921
# I,0x00000681,0x10,0x00000011,19990921
# I,0x00000681,0x20,0x0000000E,19990921
# I,0x00000683,0x08,0x00000008,19991015
# I,0x00000683,0x20,0x00000007,19991015
# I,0x00000686,0x01,0x00000007,20000505
# I,0x00000686,0x02,0x0000000A,20000504
# I,0x00000686,0x04,0x00000002,20000504
# I,0x00000686,0x10,0x00000008,20000505
# I,0x00000686,0x80,0x0000000C,20000504
# I,0x0000068A,0x10,0x00000001,20001102
# I,0x0000068A,0x20,0x00000004,20001207
# I,0x0000068A,0x80,0x00000005,20001207
# I,0x00000690,0xFF,0x00000004,20000206
# I,0x00000691,0xFF,0x00000001,20020527
# I,0x00000692,0xFF,0x00000001,20020620
# I,0x00000694,0xFF,0x00000002,20020926
# I,0x00000695,0x10,0x00000007,20041109
# I,0x00000695,0x20,0x00000007,20041109
# I,0x00000695,0x80,0x00000047,20041109
# I,0x00000696,0xFF,0x00000001,20000707
# I,0x000006A0,0x04,0x00000003,20000110
# I,0x000006A1,0x04,0x00000001,20000306
# I,0x000006A4,0xFF,0x00000001,20000616
# I,0x000006B0,0xFF,0x0000001A,20010129
# I,0x000006B1,0x10,0x0000001C,20010215
# I,0x000006B1,0x20,0x0000001D,20010220
# I,0x000006B4,0x10,0x00000001,20020110
# I,0x000006B4,0x20,0x00000002,20020111
# I,0x000006D0,0xFF,0x00000006,20030522
# I,0x000006D1,0xFF,0x00000009,20030709
# I,0x000006D2,0xFF,0x00000010,20030814
# I,0x000006D6,0x20,0x00000018,20041017
# I,0x000006D8,0xFF,0x00000021,20060831
# I,0x000006E0,0xFF,0x00000008,20050215
# I,0x000006E1,0xFF,0x0000000C,20050413
# I,0x000006E4,0xFF,0x00000026,20050816
# I,0x000006E8,0x20,0x00000039,20051115
# I,0x000006EC,0x20,0x00000054,20060501
# I,0x000006EC,0x80,0x00000059,20060912
# I,0x000006F0,0xFF,0x00000005,20050818
# I,0x000006F1,0xFF,0x00000012,20051129
# I,0x000006F2,0x01,0x0000005D,20101002
# I,0x000006F2,0x20,0x0000005C,20101002
# I,0x000006F4,0xFF,0x00000028,20060417
# I,0x000006F5,0xFF,0x00000039,20060727
# I,0x000006F6,0x01,0x000000D0,20100930
# I,0x000006F6,0x04,0x000000D2,20101001
# I,0x000006F6,0x20,0x000000D1,20101001
# I,0x000006F7,0x10,0x0000006A,20101002
# I,0x000006F7,0x40,0x0000006B,20101002
# I,0x000006F9,0xFF,0x00000084,20061012
# I,0x000006FA,0x80,0x00000095,20101002
# I,0x000006FB,0x01,0x000000BA,20101003
# I,0x000006FB,0x04,0x000000BC,20101003
# I,0x000006FB,0x08,0x000000BB,20101003
# I,0x000006FB,0x10,0x000000BA,20101003
# I,0x000006FB,0x20,0x000000BA,20101003
# I,0x000006FB,0x40,0x000000BC,20101003
# I,0x000006FB,0x80,0x000000BA,20101003
# I,0x000006FD,0x01,0x000000A4,20101002
# I,0x000006FD,0x20,0x000000A4,20101002
# I,0x000006FD,0x80,0x000000A4,20101002
# I,0x00000F00,0xFF,0xFFFF0001,20000130
# I,0x00000F01,0xFF,0xFFFF0007,20000404
# I,0x00000F02,0xFF,0xFFFF000B,20000518
# I,0x00000F03,0xFF,0xFFFF0001,20000518
# I,0x00000F04,0xFF,0xFFFF0010,20000803
# I,0x00000F05,0xFF,0x0000000C,20000824
# I,0x00000F06,0xFF,0x00000004,20000911
# I,0x00000F07,0x01,0x00000012,20020716
# I,0x00000F07,0x02,0x00000008,20001115
# I,0x00000F08,0xFF,0x00000008,20001101
# I,0x00000F09,0xFF,0x00000008,20010104
# I,0x00000F0A,0x01,0x00000013,20020716
# I,0x00000F0A,0x02,0x00000015,20020821
# I,0x00000F0A,0x04,0x00000014,20020716
# I,0x00000F11,0xFF,0x0000000A,20030729
# I,0x00000F12,0x04,0x0000002E,20030502
# I,0x00000F13,0xFF,0x00000005,20030508
# I,0x00000F20,0xFF,0x00000001,20010423
# I,0x00000F21,0xFF,0x00000003,20010529
# I,0x00000F22,0xFF,0x00000005,20030729
# I,0x00000F23,0xFF,0x0000000D,20010817
# I,0x00000F24,0x02,0x0000001F,20030605
# I,0x00000F24,0x04,0x0000001E,20030605
# I,0x00000F24,0x10,0x00000021,20030610
# I,0x00000F25,0x01,0x00000029,20040811
# I,0x00000F25,0x02,0x0000002A,20040811
# I,0x00000F25,0x04,0x0000002B,20040811
# I,0x00000F25,0x10,0x0000002C,20040826
# I,0x00000F26,0x02,0x00000010,20040805
# I,0x00000F27,0x02,0x00000038,20030604
# I,0x00000F27,0x04,0x00000037,20030604
# I,0x00000F27,0x08,0x00000039,20030604
# I,0x00000F29,0x02,0x0000002D,20040811
# I,0x00000F29,0x04,0x0000002E,20040811
# I,0x00000F29,0x08,0x0000002F,20040811
# I,0x00000F30,0xFF,0x00000013,20030815
# I,0x00000F31,0xFF,0x0000000B,20031021
# I,0x00000F32,0x0D,0x0000000A,20040511
# I,0x00000F33,0x0D,0x0000000C,20050421
# I,0x00000F34,0x1D,0x00000017,20050421
# I,0x00000F36,0xFF,0x00000007,20040309
# I,0x00000F37,0xFF,0x00000003,20031218
# I,0x00000F40,0xFF,0x00000006,20040318
# I,0x00000F41,0x02,0x00000016,20050421
# I,0x00000F41,0xBD,0x00000017,20050422
# I,0x00000F42,0xFF,0x00000003,20050421
# I,0x00000F43,0x9D,0x00000005,20050421
# I,0x00000F44,0x9D,0x00000006,20050421
# I,0x00000F46,0xFF,0x00000004,20050411
# I,0x00000F47,0x9D,0x00000003,20050421
# I,0x00000F48,0x01,0x0000000C,20060508
# I,0x00000F48,0x02,0x0000000E,20080115
# I,0x00000F48,0x5F,0x00000007,20050630
# I,0x00000F49,0xBD,0x00000003,20050421
# I,0x00000F4A,0x5C,0x00000004,20051214
# I,0x00000F4A,0x5D,0x00000002,20050610
# I,0x00000F60,0xFF,0x00000005,20050124
# I,0x00000F61,0xFF,0x00000008,20050610
# I,0x00000F62,0x04,0x0000000F,20051215
# I,0x00000F63,0xFF,0x00000005,20051010
# I,0x00000F64,0x01,0x00000002,20051215
# I,0x00000F64,0x34,0x00000004,20051223
# I,0x00000F65,0x01,0x00000008,20060426
# I,0x00000F66,0xFF,0x0000001B,20060310
# I,0x00000F68,0x22,0x00000009,20060714
# I,0x00001632,0x00,0x00000002,19980610
# I,0x00010650,0xFF,0x00000002,20060513
# I,0x00010660,0xFF,0x00000004,20060612
# I,0x00010661,0x01,0x00000043,20101004
# I,0x00010661,0x02,0x00000042,20101004
# I,0x00010661,0x80,0x00000044,20101004
# I,0x00010670,0xFF,0x00000005,20070209
# I,0x00010671,0xFF,0x00000106,20070329
# I,0x00010674,0xFF,0x84050100,20070726
# I,0x00010676,0x01,0x0000060F,20100929
# I,0x00010676,0x04,0x0000060F,20100929
# I,0x00010676,0x10,0x0000060F,20100929
# I,0x00010676,0x40,0x0000060F,20100929
# I,0x00010676,0x80,0x0000060F,20100929
# I,0x00010677,0x10,0x0000070A,20100929
# I,0x0001067A,0x11,0x00000A0B,20100928
# I,0x0001067A,0x44,0x00000A0B,20100928
# I,0x0001067A,0xA0,0x00000A0B,20100928
# I,0x000106A0,0xFF,0xFFFF001A,20071128
# I,0x000106A1,0xFF,0xFFFF000B,20080220
# I,0x000106A2,0xFF,0xFFFF0019,20080714
# I,0x000106A4,0x03,0x00000012,20130621
# I,0x000106A5,0x03,0x0000001D,20180511
# I,0x000106C0,0xFF,0x00000007,20070824
# I,0x000106C1,0xFF,0x00000109,20071203
# I,0x000106C2,0x01,0x00000217,20090410
# I,0x000106C2,0x04,0x00000218,20090410
# I,0x000106C2,0x08,0x00000219,20090410
# I,0x000106C9,0xFF,0x00000007,20090213
# I,0x000106CA,0x01,0x00000107,20090825
# I,0x000106CA,0x04,0x00000107,20090825
# I,0x000106CA,0x08,0x00000107,20090825
# I,0x000106CA,0x10,0x00000107,20090825
# I,0x000106D0,0xFF,0x00000005,20071204
# I,0x000106D1,0x08,0x00000029,20100930
# I,0x000106E0,0xFF,0xFFFF0022,20090116
# I,0x000106E1,0xFF,0xFFFF000D,20090206
# I,0x000106E2,0xFF,0xFFFF0011,20090924
# I,0x000106E3,0xFF,0xFFFF0011,20090512
# I,0x000106E4,0xFF,0x00000003,20130701
# I,0x000106E5,0x13,0x0000000A,20180508
# I,0x000106F0,0xFF,0xFFFF0009,20090210
# I,0x000106F1,0xFF,0xFFFF0007,20090210
# I,0x00020650,0xFF,0xFFFF0008,20090218
# I,0x00020651,0xFF,0xFFFF0018,20090818
# I,0x00020652,0x12,0x00000011,20180508
# I,0x00020654,0xFF,0xFFFF0007,20091124
# I,0x00020655,0x92,0x00000007,20180423
# I,0x00020661,0x01,0x00000104,20091023
# I,0x00020661,0x02,0x00000105,20110718
# I,0x000206A0,0xFF,0x00000029,20091102
# I,0x000206A1,0xFF,0x00000007,20091223
# I,0x000206A2,0xFF,0x00000027,20100502
# I,0x000206A3,0xFF,0x00000009,20100609
# I,0x000206A4,0xFF,0x00000022,20100414
# I,0x000206A5,0xFF,0x00000007,20100722
# I,0x000206A6,0xFF,0x90030028,20100924
# I,0x000206A7,0x12,0x0000002F,20190217
# I,0x000206C0,0xFF,0xFFFF001C,20091214
# I,0x000206C1,0xFF,0x00000006,20091222
# I,0x000206C2,0x03,0x0000001F,20180508
# I,0x000206D0,0xFF,0x80000006,20100816
# I,0x000206D1,0xFF,0x80000106,20101201
# I,0x000206D2,0xFF,0xAF506958,20110714
# I,0x000206D3,0xFF,0xAF50696A,20110816
# I,0x000206D5,0xFF,0xAF5069E5,20120118
# I,0x000206D6,0x6D,0x00000621,20200304
# I,0x000206D7,0x6D,0x0000071A,20200324
# I,0x000206E0,0xFF,0xE3493401,20090108
# I,0x000206E1,0xFF,0xE3493402,20090224
# I,0x000206E2,0xFF,0xFFFF0004,20081001
# I,0x000206E3,0xFF,0xE4486547,20090701
# I,0x000206E4,0xFF,0xFFFF0008,20090619
# I,0x000206E5,0xFF,0xFFFF0018,20091215
# I,0x000206E6,0x04,0x0000000D,20180515
# I,0x000206F0,0xFF,0x00000005,20100729
# I,0x000206F1,0xFF,0x00000008,20101013
# I,0x000206F2,0x05,0x0000003B,20180516
# I,0x00030650,0xFF,0x00000009,20120118
# I,0x00030651,0xFF,0x00000110,20131014
# I,0x00030660,0xFF,0x00000003,20101103
# I,0x00030661,0xFF,0x0000010F,20150721
# I,0x00030669,0xFF,0x0000010D,20130515
# I,0x00030671,0xFF,0x00000117,20130410
# I,0x00030672,0xFF,0x0000022E,20140401
# I,0x00030673,0xFF,0x83290100,20190916
# I,0x00030678,0x02,0x00000838,20190422
# I,0x00030678,0x0C,0x00000838,20190422
# I,0x00030679,0x0F,0x0000090D,20190710
# I,0x000306A0,0xFF,0x00000007,20110407
# I,0x000306A2,0xFF,0x0000000C,20110725
# I,0x000306A4,0xFF,0x00000007,20110908
# I,0x000306A5,0xFF,0x00000009,20111110
# I,0x000306A6,0xFF,0x00000004,20111114
# I,0x000306A8,0xFF,0x00000010,20120220
# I,0x000306A9,0x12,0x00000021,20190213
# I,0x000306C0,0xFF,0xFFFF0013,20111110
# I,0x000306C1,0xFF,0xFFFF0014,20120725
# I,0x000306C2,0xFF,0xFFFF0006,20121017
# I,0x000306C3,0x32,0x00000028,20191112
# I,0x000306D1,0xFF,0xFFFF0009,20131015
# I,0x000306D2,0xFF,0xFFFF0009,20131219
# I,0x000306D3,0xFF,0xE3121338,20140825
# I,0x000306D4,0xC0,0x0000002F,20191112
# I,0x000306E0,0xFF,0xE920080F,20121113
# I,0x000306E2,0xFF,0xE9220827,20130523
# I,0x000306E3,0xFF,0x00000308,20130321
# I,0x000306E4,0xED,0x0000042E,20190314
# I,0x000306E6,0xED,0x00000600,20130619
# I,0x000306E7,0xED,0x00000715,20190314
# I,0x000306F0,0xFF,0xFFFF0017,20130730
# I,0x000306F1,0xFF,0xD141D629,20140416
# I,0x000306F2,0x6F,0x00000049,20210811
# I,0x000306F3,0xFF,0x0000000D,20160211
# I,0x000306F4,0x80,0x0000001A,20210524
# I,0x00040650,0xFF,0xFFFF000B,20121206
# I,0x00040651,0x72,0x00000026,20191112
# I,0x00040660,0xFF,0xFFFF0011,20121012
# I,0x00040661,0x32,0x0000001C,20191112
# I,0x00040670,0xFF,0xFFFF0006,20140304
# I,0x00040671,0x22,0x00000022,20191112
# I,0x000406A0,0xFF,0x80124001,20130521
# I,0x000406A8,0xFF,0x0000081F,20140812
# I,0x000406A9,0xFF,0x0000081F,20140812
# I,0x000406C1,0xFF,0x0000010B,20140814
# I,0x000406C2,0xFF,0x00000221,20150218
# I,0x000406C3,0x01,0x00000368,20190423
# I,0x000406C4,0x01,0x00000411,20190423
# I,0x000406D0,0xFF,0x0000000E,20130612
# I,0x000406D8,0x01,0x0000012D,20190916
# I,0x000406E1,0xFF,0x00000020,20141111
# I,0x000406E2,0xFF,0x0000002C,20150521
# I,0x000406E3,0xC0,0x000000F0,20211112
# I,0x000406E8,0xFF,0x00000026,20160414
# I,0x000406F0,0xFF,0x00000014,20150702
# I,0x000406F1,0xFF,0x0B000041,20240216
# I,0x00050650,0xFF,0x8000002B,20160208
# I,0x00050651,0xFF,0x8000002B,20160208
# I,0x00050652,0xFF,0x80000037,20170502
# I,0x00050653,0x97,0x01000191,20230728
# I,0x00050654,0xB7,0x02007006,20230306
# I,0x00050655,0xB7,0x03000010,20181116
# I,0x00050656,0xFF,0x04003901,20241212
# I,0x00050657,0xBF,0x05003901,20241212
# I,0x0005065A,0xFF,0x86002302,20210416
# I,0x0005065B,0xBF,0x07002B01,20241212
# I,0x00050661,0xFF,0xF1000008,20150130
# I,0x00050662,0x10,0x0000001C,20190617
# I,0x00050663,0x10,0x0700001C,20210612
# I,0x00050664,0x10,0x0F00001A,20210612
# I,0x00050665,0x10,0x0E000015,20230803
# I,0x00050670,0xFF,0xFFFF0030,20151113
# I,0x00050671,0xFF,0x000001B6,20180108
# I,0x000506A0,0xFF,0x00000038,20150112
# I,0x000506C0,0xFF,0x00000002,20140613
# I,0x000506C2,0x01,0x00000014,20180511
# I,0x000506C8,0xFF,0x90011010,20160323
# I,0x000506C9,0x03,0x00000048,20211116
# I,0x000506CA,0x03,0x00000028,20211116
# I,0x000506D1,0xFF,0x00000102,20150605
# I,0x000506E0,0xFF,0x00000018,20141119
# I,0x000506E1,0xFF,0x0000002A,20150602
# I,0x000506E2,0xFF,0x0000002E,20150815
# I,0x000506E3,0x36,0x000000F0,20211112
# I,0x000506E8,0xFF,0x00000034,20160710
# I,0x000506F0,0xFF,0x00000010,20160607
# I,0x000506F1,0x01,0x0000003E,20231005
# I,0x00060660,0xFF,0x0000000C,20160821
# I,0x00060661,0xFF,0x0000000E,20170128
# I,0x00060662,0xFF,0x00000022,20171129
# I,0x00060663,0x80,0x0000002A,20180417
# I,0x000606A0,0xFF,0x80000031,20200308
# I,0x000606A4,0xFF,0x0B000280,20200817
# I,0x000606A5,0x87,0x0C0002F0,20210308
# I,0x000606A6,0x87,0x0D000421,20250819
# I,0x000606C0,0xFF,0xFD000220,20210629
# I,0x000606C1,0x10,0x010002F1,20250819
# I,0x000606E0,0xFF,0x0000000B,20161104
# I,0x000606E1,0xFF,0x00000108,20190423
# I,0x000606E4,0xFF,0x0000000C,20190124
# I,0x000706A0,0xFF,0x00000026,20170712
# I,0x000706A1,0x01,0x00000042,20240419
# I,0x000706A8,0x01,0x00000026,20241205
# I,0x000706E0,0xFF,0x0000002C,20180614
# I,0x000706E1,0xFF,0x00000042,20190420
# I,0x000706E2,0xFF,0x00000042,20190420
# I,0x000706E3,0xFF,0x81000008,20181002
# I,0x000706E4,0xFF,0x00000046,20190905
# I,0x000706E5,0x80,0x000000CC,20250724
# I,0x00080650,0xFF,0x00000018,20180108
# I,0x00080664,0xFF,0x4C000025,20230926
# I,0x00080665,0xFF,0x4C000026,20240228
# I,0x00080667,0xFF,0x4C000026,20240228
# I,0x000806A0,0xFF,0x00000010,20190507
# I,0x000806A1,0x10,0x00000033,20230113
# I,0x000806C0,0xFF,0x00000068,20200402
# I,0x000806C1,0x80,0x000000BE,20250724
# I,0x000806C2,0xC2,0x0000003E,20250724
# I,0x000806D0,0xFF,0x00000054,20210507
# I,0x000806D1,0xC2,0x00000058,20250724
# I,0x000806E9,0x10,0x000000F6,20240201
# I,0x000806E9,0xC0,0x000000F6,20240201
# I,0x000806EA,0xC0,0x000000F6,20240201
# I,0x000806EB,0xD0,0x000000F6,20240201
# I,0x000806EC,0x94,0x00000100,20241117
# I,0x000806F1,0xFF,0x800003C0,20220327
# I,0x000806F2,0xFF,0x8C0004E0,20211112
# I,0x000806F3,0xFF,0x8D000520,20220812
# I,0x000806F4,0x10,0x2C000421,20250825
# I,0x000806F4,0x87,0x2B000661,20250825
# I,0x000806F5,0x10,0x2C000421,20250825
# I,0x000806F5,0x87,0x2B000661,20250825
# I,0x000806F6,0x10,0x2C000421,20250825
# I,0x000806F6,0x87,0x2B000661,20250825
# I,0x000806F7,0x87,0x2B000661,20250825
# I,0x000806F8,0x10,0x2C000421,20250825
# I,0x000806F8,0x87,0x2B000661,20250825
# I,0x00090660,0xFF,0x00000009,20200617
# I,0x00090661,0x01,0x0000001A,20240405
# I,0x00090670,0xFF,0x00000019,20201111
# I,0x00090671,0xFF,0x0000001C,20210614
# I,0x00090672,0x07,0x0000003E,20251012
# I,0x00090674,0xFF,0x00000219,20210425
# I,0x00090675,0x07,0x0000003E,20251012
# I,0x000906A0,0xFF,0x0000001C,20210614
# I,0x000906A1,0xFF,0x0000011F,20211104
# I,0x000906A2,0xFF,0x00000315,20220102
# I,0x000906A3,0x80,0x0000043B,20251012
# I,0x000906A4,0x40,0x0000000C,20250710
# I,0x000906A4,0x80,0x0000043B,20251012
# I,0x000906C0,0x01,0x24000026,20230926
# I,0x000906E9,0x2A,0x000000F8,20230928
# I,0x000906EA,0x22,0x000000FA,20240728
# I,0x000906EB,0x02,0x000000F6,20240201
# I,0x000906EC,0x22,0x000000F8,20240201
# I,0x000906ED,0x22,0x00000104,20241114
# I,0x000A0650,0xFF,0x000000BE,20191010
# I,0x000A0651,0xFF,0x000000C2,20191113
# I,0x000A0652,0x20,0x00000100,20241114
# I,0x000A0653,0x22,0x00000100,20241114
# I,0x000A0654,0xFF,0x000000C6,20200123
# I,0x000A0655,0x22,0x00000100,20241114
# I,0x000A0660,0x80,0x00000102,20241114
# I,0x000A0661,0x80,0x00000100,20241114
# I,0x000A0670,0xFF,0x0000002C,20201124
# I,0x000A0671,0x02,0x00000065,20250724
# I,0x000A0680,0xFF,0x80000002,20200121
# I,0x000A06A1,0xFF,0x00000017,20230518
# I,0x000A06A2,0xFF,0x00000011,20230627
# I,0x000A06A4,0xE6,0x00000028,20250924
# I,0x000A06C0,0xFF,0x00000013,20230901
# I,0x000A06C1,0xFF,0x00000005,20231201
# I,0x000A06D0,0xFF,0x10000680,20240818
# I,0x000A06D1,0x20,0x0A000133,20251009
# I,0x000A06D1,0x95,0x01000405,20251031
# I,0x000A06E1,0x97,0x01000303,20251202
# I,0x000A06F0,0xFF,0x80000360,20240130
# I,0x000A06F3,0x01,0x03000382,20250730
# I,0x000B0650,0x80,0x0000000D,20250925
# I,0x000B0664,0xFF,0x00000030,20250529
# I,0x000B0670,0xFF,0x0000000E,20220220
# I,0x000B0671,0x32,0x00000133,20251008
# I,0x000B0674,0x32,0x00000133,20251008
# I,0x000B06A2,0xE0,0x00006134,20251008
# I,0x000B06A3,0xE0,0x00006134,20251008
# I,0x000B06A8,0xE0,0x00006134,20251008
# I,0x000B06D0,0xFF,0x0000001A,20240610
# I,0x000B06D1,0x80,0x00000125,20250828
# I,0x000B06E0,0x19,0x00000021,20250912
# I,0x000B06F2,0x07,0x0000003E,20251012
# I,0x000B06F5,0x07,0x0000003E,20251012
# I,0x000B06F6,0x07,0x0000003E,20251012
# I,0x000B06F7,0x07,0x0000003E,20251012
# I,0x000C0652,0x82,0x0000011B,20250803
# I,0x000C0660,0xFF,0x00000018,20240516
# I,0x000C0662,0x82,0x0000011B,20250803
# I,0x000C0664,0x82,0x0000011B,20250803
# I,0x000C06A2,0x82,0x0000011B,20250803
# I,0x000C06C0,0xFF,0x00000012,20250325
# I,0x000C06C1,0xFF,0x00000115,20251203
# I,0x000C06C2,0xFF,0x00000115,20251203
# I,0x000C06C3,0xFF,0x00000115,20251203
# I,0x000C06F1,0x87,0x210002D3,20250825
# I,0x000C06F2,0x87,0x210002D3,20250825
# I,0x000D0670,0xFF,0x00000003,20250825
# I,0x000D06D0,0xFF,0x00000340,20250807
# I,0x00FF0671,0xFF,0x0000010E,20220907
# I,0x00FF0672,0xFF,0x0000000D,20210816
# I,0x00FF0675,0xFF,0x0000000D,20210816
# A,0x00000F00,0xFF,0x02000008,20070614
# A,0x00000F01,0xFF,0x0000001C,20021031
# A,0x00000F10,0xFF,0x00000003,20020325
# A,0x00000F11,0xFF,0x0000001F,20030220
# A,0x00000F48,0xFF,0x00000046,20040719
# A,0x00000F4A,0xFF,0x00000047,20040719
# A,0x00000F50,0xFF,0x00000024,20021212
# A,0x00000F51,0xFF,0x00000025,20030115
# A,0x00010F50,0xFF,0x00000041,20040225
# A,0x00020F10,0xFF,0x0000004D,20050428
# A,0x00040F01,0xFF,0xC0012102,20050916
# A,0x00040F0A,0xFF,0x00000068,20060920
# A,0x00040F13,0xFF,0x0000007A,20080508
# A,0x00040F14,0xFF,0x00000062,20060127
# A,0x00040F1B,0xFF,0x0000006D,20060920
# A,0x00040F33,0xFF,0x0000007B,20080514
# A,0x00060F80,0xFF,0x00000083,20060929
# A,0x000C0F1B,0xFF,0x0000006E,20060921
# A,0x000F0F00,0xFF,0x00000005,20020627
# A,0x000F0F01,0xFF,0x00000015,20020627
# A,0x00100F00,0xFF,0x01000020,20070326
# A,0x00100F20,0xFF,0x010000CA,20100331
# A,0x00100F22,0xFF,0x010000C9,20100331
# A,0x00100F2A,0xFF,0x01000084,20000101
# A,0x00100F40,0xFF,0x01000085,20080501
# A,0x00100F41,0xFF,0x010000DB,20111024
# A,0x00100F42,0xFF,0x01000092,20081021
# A,0x00100F43,0xFF,0x010000C8,20100311
# A,0x00100F52,0xFF,0x010000DB,20000101
# A,0x00100F53,0xFF,0x010000C8,20000101
# A,0x00100F62,0xFF,0x010000C7,20100311
# A,0x00100F80,0xFF,0x010000DA,20111024
# A,0x00100F81,0xFF,0x010000D9,20111012
# A,0x00100F91,0xFF,0x010000D9,20000101
# A,0x00100FA0,0xFF,0x010000DC,20111024
# A,0x00120F00,0xFF,0x03000002,20100324
# A,0x00200F30,0xFF,0x02000018,20070921
# A,0x00200F31,0xFF,0x02000057,20080502
# A,0x00200F32,0xFF,0x02000034,20080307
# A,0x00300F01,0xFF,0x0300000E,20101004
# A,0x00300F10,0xFF,0x03000027,20111209
# A,0x00500F00,0xFF,0x0500000B,20100601
# A,0x00500F01,0xFF,0x0500001A,20100908
# A,0x00500F10,0xFF,0x05000029,20130121
# A,0x00500F20,0xFF,0x05000119,20130118
# A,0x00580F00,0xFF,0x0500000B,20100601
# A,0x00580F01,0xFF,0x0500001A,20100908
# A,0x00580F10,0xFF,0x05000028,20101124
# A,0x00580F20,0xFF,0x05000103,20110526
# A,0x00600F00,0xFF,0x06000017,20101029
# A,0x00600F01,0xFF,0x0600011F,20110227
# A,0x00600F10,0xFF,0x06000425,20110408
# A,0x00600F11,0xFF,0x0600050D,20110627
# A,0x00600F12,0xFF,0x0600063E,20180207
# A,0x00600F20,0xFF,0x06000852,20180206
# A,0x00610F00,0xFF,0x0600100E,20111102
# A,0x00610F01,0xFF,0x0600111F,20180305
# A,0x00630F00,0xFF,0x0600301C,20130817
# A,0x00630F01,0xFF,0x06003109,20180227
# A,0x00660F00,0xFF,0x06006108,20150302
# A,0x00660F01,0xFF,0x0600611A,20180126
# A,0x00670F00,0xFF,0x06006705,20180220
# A,0x00680F00,0xFF,0x06000017,20101029
# A,0x00680F01,0xFF,0x0600011F,20110227
# A,0x00680F10,0xFF,0x06000410,20110314
# A,0x00690F00,0xFF,0x06001009,20110613
# A,0x00700F00,0xFF,0x0700002A,20121218
# A,0x00700F01,0xFF,0x07000110,20180209
# A,0x00730F00,0xFF,0x07030009,20131206
# A,0x00730F01,0xFF,0x07030106,20180209
# A,0x00800F00,0xFF,0x0800002A,20161006
# A,0x00800F10,0xFF,0x0800100C,20170131
# A,0x00800F11,0xFF,0x08001139,20240822
# A,0x00800F12,0xFF,0x08001279,20241111
# A,0x00800F82,0xFF,0x0800820E,20240815
# A,0x00810F00,0xFF,0x08100004,20161120
# A,0x00810F10,0xFF,0x0810101B,20240716
# A,0x00810F11,0xFF,0x08101104,20240703
# A,0x00810F80,0xFF,0x08108002,20180605
# A,0x00810F81,0xFF,0x0810810E,20241112
# A,0x00820F00,0xFF,0x08200002,20180214
# A,0x00820F01,0xFF,0x08200105,20241111
# A,0x00830F00,0xFF,0x08300027,20190401
# A,0x00830F10,0xFF,0x0830107F,20241111
# A,0x00850F00,0xFF,0x08500004,20180212
# A,0x00860F00,0xFF,0x0860000E,20200127
# A,0x00860F01,0xFF,0x0860010F,20241118
# A,0x00860F81,0xFF,0x08608109,20241118
# A,0x00870F00,0xFF,0x08700004,20181206
# A,0x00870F10,0xFF,0x08701035,20241118
# A,0x00880F40,0xFF,0x08804005,20210312
# A,0x00890F00,0xFF,0x08900007,20200921
# A,0x00890F01,0xFF,0x08900103,20201105
# A,0x00890F02,0xFF,0x08900203,20230915
# A,0x00890F10,0xFF,0x08901003,20230919
# A,0x008A0F00,0xFF,0x08A0000B,20241125
# A,0x00A00F00,0xFF,0x0A000033,20200413
# A,0x00A00F10,0xFF,0x0A00107A,20240226
# A,0x00A00F11,0xFF,0x0A0011DE,20250418
# A,0x00A00F12,0xFF,0x0A001247,20250327
# A,0x00A00F80,0xFF,0x0A008005,20230707
# A,0x00A00F82,0xFF,0x0A00820F,20241111
# A,0x00A10F00,0xFF,0x0A10004B,20220309
# A,0x00A10F01,0xFF,0x0A100104,20220207
# A,0x00A10F0B,0xFF,0x0A100B07,20220610
# A,0x00A10F10,0xFF,0x0A101020,20220913
# A,0x00A10F11,0xFF,0x0A101158,20250609
# A,0x00A10F12,0xFF,0x0A101253,20250612
# A,0x00A10F80,0xFF,0x0A108005,20230613
# A,0x00A10F81,0xFF,0x0A10810C,20241112
# A,0x00A20F00,0xFF,0x0A200025,20200121
# A,0x00A20F10,0xFF,0x0A201030,20241111
# A,0x00A20F12,0xFF,0x0A201213,20241205
# A,0x00A40F00,0xFF,0x0A400016,20210330
# A,0x00A40F40,0xFF,0x0A404002,20210408
# A,0x00A40F41,0xFF,0x0A40410A,20241111
# A,0x00A50F00,0xFF,0x0A500014,20241111
# A,0x00A60F00,0xFF,0x0A600005,20211220
# A,0x00A60F11,0xFF,0x0A601119,20230613
# A,0x00A60F12,0xFF,0x0A60120C,20241110
# A,0x00A60F13,0xFF,0x0A601302,20250228
# A,0x00A70F00,0xFF,0x0A700003,20220517
# A,0x00A70F40,0xFF,0x0A704001,20220721
# A,0x00A70F41,0xFF,0x0A70410A,20241108
# A,0x00A70F42,0xFF,0x0A704202,20230713
# A,0x00A70F52,0xFF,0x0A70520A,20241111
# A,0x00A70F80,0xFF,0x0A70800A,20241111
# A,0x00A70FC0,0xFF,0x0A70C00A,20241111
# A,0x00A80F00,0xFF,0x0A80000B,20241122
# A,0x00A80F01,0xFF,0x0A80010A,20241119
# A,0x00A90F00,0xFF,0x0A90000C,20250710
# A,0x00A90F01,0xFF,0x0A90010D,20250612
# A,0x00AA0F00,0xFF,0x0AA00009,20221006
# A,0x00AA0F01,0xFF,0x0AA00116,20230619
# A,0x00AA0F02,0xFF,0x0AA0021C,20250612
# A,0x00B00F00,0xFF,0x0B00004D,20240318
# A,0x00B00F10,0xFF,0x0B001016,20240318
# A,0x00B00F20,0xFF,0x0B002032,20241003
# A,0x00B00F21,0xFF,0x0B002161,20251105
# A,0x00B00F80,0xFF,0x0B008011,20241211
# A,0x00B00F81,0xFF,0x0B008121,20251020
# A,0x00B10F00,0xFF,0x0B10000F,20240320
# A,0x00B10F10,0xFF,0x0B101058,20251105
# A,0x00B20F40,0xFF,0x0B204037,20251019
# A,0x00B40F00,0xFF,0x0B400034,20240318
# A,0x00B40F40,0xFF,0x0B404035,20251020
# A,0x00B40F41,0xFF,0x0B404108,20251020
# A,0x00B60F00,0xFF,0x0B600037,20251019
# A,0x00B60F80,0xFF,0x0B608038,20251019
# A,0x00B70F00,0xFF,0x0B700037,20251019

View File

@@ -0,0 +1,52 @@
#! /bin/sh
# SPDX-License-Identifier: GPL-3.0-only
# vim: set ts=4 sw=4 sts=4 et:
# shellcheck disable=SC2317,SC2329,SC3043
#
# Spectre & Meltdown checker
#
# Check for the latest version at:
# https://github.com/speed47/spectre-meltdown-checker
# git clone https://github.com/speed47/spectre-meltdown-checker.git
# or wget https://meltdown.ovh -O spectre-meltdown-checker.sh
# or curl -L https://meltdown.ovh -o spectre-meltdown-checker.sh
#
# Stephane Lesimple
#
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 SYS_MODULE_BASE="/sys/module"
readonly CPU_DEV_BASE="/dev/cpu"
readonly BSD_CPUCTL_DEV_BASE="/dev/cpuctl"
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=$?
# 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"
[ -n "${g_kerneltmp2:-}" ] && [ -f "$g_kerneltmp2" ] && rm -f "$g_kerneltmp2"
[ -n "${g_sls_text_tmp:-}" ] && [ -f "$g_sls_text_tmp" ] && rm -f "$g_sls_text_tmp"
[ -n "${g_mcedb_tmp:-}" ] && [ -f "$g_mcedb_tmp" ] && rm -f "$g_mcedb_tmp"
[ -n "${g_intel_tmp:-}" ] && [ -d "$g_intel_tmp" ] && rm -rf "$g_intel_tmp"
[ -n "${g_linuxfw_tmp:-}" ] && [ -f "$g_linuxfw_tmp" ] && rm -f "$g_linuxfw_tmp"
[ "${g_mounted_debugfs:-}" = 1 ] && umount "$DEBUGFS_BASE" 2>/dev/null
[ "${g_mounted_procfs:-}" = 1 ] && umount "$g_procfs" 2>/dev/null
[ "${g_insmod_cpuid:-}" = 1 ] && rmmod cpuid 2>/dev/null
[ "${g_insmod_msr:-}" = 1 ] && rmmod msr 2>/dev/null
[ "${g_kldload_cpuctl:-}" = 1 ] && kldunload cpuctl 2>/dev/null
[ "${g_kldload_vmm:-}" = 1 ] && kldunload vmm 2>/dev/null
exit "$saved_ret"
}
# if we were git clone'd, adjust VERSION
if [ -d "$(dirname "$0")/.git" ] && command -v git >/dev/null 2>&1; then
g_commit=$(git -C "$(dirname "$0")" describe --always --dirty --abbrev=7 --match=- 2>/dev/null)
[ -n "$g_commit" ] && VERSION="$VERSION-git$g_commit"
fi

View File

@@ -0,0 +1,234 @@
# vim: set ts=4 sw=4 sts=4 et:
# Print command-line usage information to stdout
show_usage() {
# shellcheck disable=SC2086
cat <<EOF
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
* 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.
* 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.
* Hardware-only mode: $(basename $0) [options] --hw-only
Only inspect the CPU hardware, and report information and affectedness per vulnerability.
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)
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:
--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)
--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
Firmware database:
--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:
0 (not vulnerable), 2 (vulnerable), 3 (unknown), 255 (error)
IMPORTANT:
A false sense of security is worse than no security at all.
Please use the --disclaimer option to understand exactly what this script does.
EOF
}
# Print the legal disclaimer about tool accuracy and limitations
show_disclaimer() {
cat <<EOF
Disclaimer:
This tool does its best to determine whether your system is immune (or has proper mitigations in place) for the
collectively named "transient execution" (aka "speculative execution") vulnerabilities that started to appear
since early 2018 with the infamous Spectre & Meltdown.
This tool does NOT attempt to run any kind of exploit, and can't 100% guarantee that your system is secure,
but rather helps you verifying whether your system has the known correct mitigations in place.
However, some mitigations could also exist in your kernel that this script doesn't know (yet) how to detect, or it might
falsely detect mitigations that in the end don't work as expected (for example, on backported or modified kernels).
Your system affectability to a given vulnerability depends on your CPU model and CPU microcode version, whereas the
mitigations in place depend on your CPU (model and microcode), your kernel version, and both the runtime configuration
of your CPU (through bits set through the MSRs) and your kernel. The script attempts to explain everything for each
vulnerability, so you know where your system stands. For a given vulnerability, detailed information is sometimes
available using the \`--explain\` switch.
Please also note that for the Spectre-like vulnerabilities, all software can possibly be exploited, in which case
this tool only verifies that the kernel (which is the core of the system) you're using has the proper protections
in place. Verifying all the other software is out of the scope of this tool, as it can't be done in a simple way.
As a general measure, ensure you always have the most up to date stable versions of all the software you use,
especially for those who are exposed to the world, such as network daemons and browsers.
For more information and answers to related questions, please refer to the FAQ.md file.
This tool has been released in the hope that it'll be useful, but don't use it to jump to conclusions about your security.
EOF
}
g_os=$(uname -s)
# parse options
opt_kernel=''
opt_config=''
opt_map=''
opt_runtime=1
opt_no_color=0
opt_batch=0
opt_batch_format='text'
opt_verbose=1
opt_cve_list=''
opt_cve_all=1
opt_no_sysfs=0
opt_sysfs_only=0
opt_coreos=0
opt_arch_prefix=''
opt_hw_only=0
opt_no_hw=0
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
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=''
# CVE Registry: single source of truth for all CVE metadata.
# Fields: cve_id|json_key_name|affected_var_suffix|complete_name_and_aliases
#
# Two 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-9999-NNNN: temporary placeholder for real vulnerabilities awaiting CVE
# assignment. Rename across the codebase once the real CVE is issued.
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
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-2022-21123|SBDR|mmio|Shared Buffers Data Read (SBDR), MMIO Stale Data
CVE-2022-21125|SBDS|mmio|Shared Buffers Data Sampling (SBDS), MMIO Stale Data
CVE-2022-21166|DRPW|mmio|Device Register Partial Write (DRPW), MMIO Stale Data
CVE-2023-20588|DIV0|div0|Division by Zero, AMD Zen1 speculative data leak
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)
CVE-2025-54505|FPDSS|fpdss|FPDSS, AMD Zen1 Floating-Point Divider Stale Data Leak
'
# Derive the supported CVE list from the registry
g_supported_cve_list=$(echo "$CVE_REGISTRY" | grep '^CVE-' | cut -d'|' -f1)
# Look up a field from the CVE registry
# Args: $1=cve_id $2=field_number (see CVE_REGISTRY format above)
# Callers: cve2name, _is_cpu_affected_cached, pvulnstatus
_cve_registry_field() {
local line
line=$(echo "$CVE_REGISTRY" | grep -E "^$1\|")
if [ -z "$line" ]; then
echo "$0: error: invalid CVE '$1' passed to _cve_registry_field()" >&2
exit 255
fi
echo "$line" | cut -d'|' -f"$2"
}
# find a sane command to print colored messages, we prefer `printf` over `echo`
# because `printf` behavior is more standard across Linux/BSD
# we'll try to avoid using shell builtins that might not take options
g_echo_cmd_type='echo'
# ignore SC2230 here because `which` ignores builtins while `command -v` doesn't, and
# we don't want builtins here. Even if `which` is not installed, we'll fallback to the
# `echo` builtin anyway, so this is safe.
# shellcheck disable=SC2230
if command -v printf >/dev/null 2>&1; then
g_echo_cmd=$(command -v printf)
g_echo_cmd_type='printf'
elif which echo >/dev/null 2>&1; then
g_echo_cmd=$(which echo)
else
# maybe the `which` command is broken?
[ -x /bin/echo ] && g_echo_cmd=/bin/echo
# for Android
[ -x /system/bin/echo ] && g_echo_cmd=/system/bin/echo
fi
# still empty? fallback to builtin
[ -z "$g_echo_cmd" ] && g_echo_cmd='echo'

View File

@@ -0,0 +1,105 @@
# vim: set ts=4 sw=4 sts=4 et:
# AUTO-GENERATED FILE — DO NOT EDIT MANUALLY.
# Generated by scripts/update_intel_models.sh from:
# https://raw.githubusercontent.com/torvalds/linux/refs/heads/master/arch/x86/include/asm/intel-family.h
# Run scripts/update_intel_models.sh to refresh when new Intel CPU families are added to the kernel.
# shellcheck disable=SC2034
{
readonly INTEL_FAM5_PENTIUM_75=$((0x02)) # /* P54C */
readonly INTEL_FAM5_PENTIUM_MMX=$((0x04)) # /* P55C */
readonly INTEL_FAM5_QUARK_X1000=$((0x09)) # /* Quark X1000 SoC */
readonly INTEL_FAM6_PENTIUM_PRO=$((0x01))
readonly INTEL_FAM6_PENTIUM_II_KLAMATH=$((0x03))
readonly INTEL_FAM6_PENTIUM_III_DESCHUTES=$((0x05))
readonly INTEL_FAM6_PENTIUM_III_TUALATIN=$((0x0B))
readonly INTEL_FAM6_PENTIUM_M_DOTHAN=$((0x0D))
readonly INTEL_FAM6_CORE_YONAH=$((0x0E))
readonly INTEL_FAM6_CORE2_MEROM=$((0x0F))
readonly INTEL_FAM6_CORE2_MEROM_L=$((0x16))
readonly INTEL_FAM6_CORE2_PENRYN=$((0x17))
readonly INTEL_FAM6_CORE2_DUNNINGTON=$((0x1D))
readonly INTEL_FAM6_NEHALEM=$((0x1E))
readonly INTEL_FAM6_NEHALEM_G=$((0x1F)) # /* Auburndale / Havendale */
readonly INTEL_FAM6_NEHALEM_EP=$((0x1A))
readonly INTEL_FAM6_NEHALEM_EX=$((0x2E))
readonly INTEL_FAM6_WESTMERE=$((0x25))
readonly INTEL_FAM6_WESTMERE_EP=$((0x2C))
readonly INTEL_FAM6_WESTMERE_EX=$((0x2F))
readonly INTEL_FAM6_SANDYBRIDGE=$((0x2A))
readonly INTEL_FAM6_SANDYBRIDGE_X=$((0x2D))
readonly INTEL_FAM6_IVYBRIDGE=$((0x3A))
readonly INTEL_FAM6_IVYBRIDGE_X=$((0x3E))
readonly INTEL_FAM6_HASWELL=$((0x3C))
readonly INTEL_FAM6_HASWELL_X=$((0x3F))
readonly INTEL_FAM6_HASWELL_L=$((0x45))
readonly INTEL_FAM6_HASWELL_G=$((0x46))
readonly INTEL_FAM6_BROADWELL=$((0x3D))
readonly INTEL_FAM6_BROADWELL_G=$((0x47))
readonly INTEL_FAM6_BROADWELL_X=$((0x4F))
readonly INTEL_FAM6_BROADWELL_D=$((0x56))
readonly INTEL_FAM6_SKYLAKE_L=$((0x4E)) # /* Sky Lake */
readonly INTEL_FAM6_SKYLAKE=$((0x5E)) # /* Sky Lake */
readonly INTEL_FAM6_SKYLAKE_X=$((0x55)) # /* Sky Lake */
readonly INTEL_FAM6_KABYLAKE_L=$((0x8E)) # /* Sky Lake */
readonly INTEL_FAM6_KABYLAKE=$((0x9E)) # /* Sky Lake */
readonly INTEL_FAM6_COMETLAKE=$((0xA5)) # /* Sky Lake */
readonly INTEL_FAM6_COMETLAKE_L=$((0xA6)) # /* Sky Lake */
readonly INTEL_FAM6_CANNONLAKE_L=$((0x66)) # /* Palm Cove */
readonly INTEL_FAM6_ICELAKE_X=$((0x6A)) # /* Sunny Cove */
readonly INTEL_FAM6_ICELAKE_D=$((0x6C)) # /* Sunny Cove */
readonly INTEL_FAM6_ICELAKE=$((0x7D)) # /* Sunny Cove */
readonly INTEL_FAM6_ICELAKE_L=$((0x7E)) # /* Sunny Cove */
readonly INTEL_FAM6_ICELAKE_NNPI=$((0x9D)) # /* Sunny Cove */
readonly INTEL_FAM6_ROCKETLAKE=$((0xA7)) # /* Cypress Cove */
readonly INTEL_FAM6_TIGERLAKE_L=$((0x8C)) # /* Willow Cove */
readonly INTEL_FAM6_TIGERLAKE=$((0x8D)) # /* Willow Cove */
readonly INTEL_FAM6_SAPPHIRERAPIDS_X=$((0x8F)) # /* Golden Cove */
readonly INTEL_FAM6_EMERALDRAPIDS_X=$((0xCF)) # /* Raptor Cove */
readonly INTEL_FAM6_GRANITERAPIDS_X=$((0xAD)) # /* Redwood Cove */
readonly INTEL_FAM6_GRANITERAPIDS_D=$((0xAE))
readonly INTEL_FAM19_DIAMONDRAPIDS_X=$((0x01)) # /* Panther Cove */
readonly INTEL_FAM6_BARTLETTLAKE=$((0xD7)) # /* Raptor Cove */
readonly INTEL_FAM6_LAKEFIELD=$((0x8A)) # /* Sunny Cove / Tremont */
readonly INTEL_FAM6_ALDERLAKE=$((0x97)) # /* Golden Cove / Gracemont */
readonly INTEL_FAM6_ALDERLAKE_L=$((0x9A)) # /* Golden Cove / Gracemont */
readonly INTEL_FAM6_RAPTORLAKE=$((0xB7)) # /* Raptor Cove / Enhanced Gracemont */
readonly INTEL_FAM6_RAPTORLAKE_P=$((0xBA))
readonly INTEL_FAM6_RAPTORLAKE_S=$((0xBF))
readonly INTEL_FAM6_METEORLAKE=$((0xAC)) # /* Redwood Cove / Crestmont */
readonly INTEL_FAM6_METEORLAKE_L=$((0xAA))
readonly INTEL_FAM6_ARROWLAKE_H=$((0xC5)) # /* Lion Cove / Skymont */
readonly INTEL_FAM6_ARROWLAKE=$((0xC6))
readonly INTEL_FAM6_ARROWLAKE_U=$((0xB5))
readonly INTEL_FAM6_LUNARLAKE_M=$((0xBD)) # /* Lion Cove / Skymont */
readonly INTEL_FAM6_PANTHERLAKE_L=$((0xCC)) # /* Cougar Cove / Darkmont */
readonly INTEL_FAM6_WILDCATLAKE_L=$((0xD5))
readonly INTEL_FAM18_NOVALAKE=$((0x01)) # /* Coyote Cove / Arctic Wolf */
readonly INTEL_FAM18_NOVALAKE_L=$((0x03)) # /* Coyote Cove / Arctic Wolf */
readonly INTEL_FAM6_ATOM_BONNELL=$((0x1C)) # /* Diamondville, Pineview */
readonly INTEL_FAM6_ATOM_BONNELL_MID=$((0x26)) # /* Silverthorne, Lincroft */
readonly INTEL_FAM6_ATOM_SALTWELL=$((0x36)) # /* Cedarview */
readonly INTEL_FAM6_ATOM_SALTWELL_MID=$((0x27)) # /* Penwell */
readonly INTEL_FAM6_ATOM_SALTWELL_TABLET=$((0x35)) # /* Cloverview */
readonly INTEL_FAM6_ATOM_SILVERMONT=$((0x37)) # /* Bay Trail, Valleyview */
readonly INTEL_FAM6_ATOM_SILVERMONT_D=$((0x4D)) # /* Avaton, Rangely */
readonly INTEL_FAM6_ATOM_SILVERMONT_MID=$((0x4A)) # /* Merriefield */
readonly INTEL_FAM6_ATOM_SILVERMONT_MID2=$((0x5A)) # /* Anniedale */
readonly INTEL_FAM6_ATOM_AIRMONT=$((0x4C)) # /* Cherry Trail, Braswell */
readonly INTEL_FAM6_ATOM_AIRMONT_NP=$((0x75)) # /* Lightning Mountain */
readonly INTEL_FAM6_ATOM_GOLDMONT=$((0x5C)) # /* Apollo Lake */
readonly INTEL_FAM6_ATOM_GOLDMONT_D=$((0x5F)) # /* Denverton */
readonly INTEL_FAM6_ATOM_GOLDMONT_PLUS=$((0x7A)) # /* Gemini Lake */
readonly INTEL_FAM6_ATOM_TREMONT_D=$((0x86)) # /* Jacobsville */
readonly INTEL_FAM6_ATOM_TREMONT=$((0x96)) # /* Elkhart Lake */
readonly INTEL_FAM6_ATOM_TREMONT_L=$((0x9C)) # /* Jasper Lake */
readonly INTEL_FAM6_ATOM_GRACEMONT=$((0xBE)) # /* Alderlake N */
readonly INTEL_FAM6_ATOM_CRESTMONT_X=$((0xAF)) # /* Sierra Forest */
readonly INTEL_FAM6_ATOM_CRESTMONT=$((0xB6)) # /* Grand Ridge */
readonly INTEL_FAM6_ATOM_DARKMONT_X=$((0xDD)) # /* Clearwater Forest */
readonly INTEL_FAM6_XEON_PHI_KNL=$((0x57)) # /* Knights Landing */
readonly INTEL_FAM6_XEON_PHI_KNM=$((0x85)) # /* Knights Mill */
readonly INTEL_FAM15_P4_WILLAMETTE=$((0x01)) # /* Also Xeon Foster */
readonly INTEL_FAM15_P4_PRESCOTT=$((0x03))
readonly INTEL_FAM15_P4_PRESCOTT_2M=$((0x04))
readonly INTEL_FAM15_P4_CEDARMILL=$((0x06)) # /* Also Xeon Dempsey */
}

View File

@@ -0,0 +1,127 @@
# 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

@@ -0,0 +1,106 @@
# vim: set ts=4 sw=4 sts=4 et:
# Low-level echo wrapper handling color stripping and printf/echo portability
# Args: $1=opt(-n for no newline, '' for normal) $2...=message
# Callers: _pr_echo, _pr_echo_nol
_pr_echo_raw() {
local opt msg interpret_chars ctrlchar
opt="$1"
shift
msg="$*"
if [ "$opt_no_color" = 1 ]; then
# strip ANSI color codes
# some sed versions (i.e. toybox) can't seem to handle
# \033 aka \x1B correctly, so do it for them.
if [ "$g_echo_cmd_type" = printf ]; then
interpret_chars=''
else
interpret_chars='-e'
fi
ctrlchar=$($g_echo_cmd $interpret_chars "\033")
msg=$($g_echo_cmd $interpret_chars "$msg" | sed -E "s/$ctrlchar\[([0-9][0-9]?(;[0-9][0-9]?)?)?m//g")
fi
if [ "$g_echo_cmd_type" = printf ]; then
if [ "$opt" = "-n" ]; then
$g_echo_cmd "$msg"
else
$g_echo_cmd "$msg\n"
fi
else
# shellcheck disable=SC2086
$g_echo_cmd $opt -e "$msg"
fi
}
# Print a message if the current verbosity level is high enough
# Args: $1=minimum_verbosity_level $2...=message
# Callers: pr_warn, pr_info, pr_verbose, pr_debug, _emit_text, toplevel batch output
_pr_echo() {
if [ "$opt_verbose" -ge "$1" ]; then
shift
_pr_echo_raw '' "$*"
fi
}
# Print a message without trailing newline if the current verbosity level is high enough
# Args: $1=minimum_verbosity_level $2...=message
# Callers: pr_info_nol, pr_verbose_nol
_pr_echo_nol() {
if [ "$opt_verbose" -ge "$1" ]; then
shift
_pr_echo_raw -n "$*"
fi
}
# Print a warning message in red to stderr (verbosity 0, always shown)
# Args: $1...=message
pr_warn() {
_pr_echo 0 "\033[31m$*\033[0m" >&2
}
# Print an informational message (verbosity >= 1)
# Args: $1...=message
pr_info() {
_pr_echo 1 "$*"
}
# Print an informational message without trailing newline (verbosity >= 1)
# Args: $1...=message
pr_info_nol() {
_pr_echo_nol 1 "$*"
}
# Print a verbose message (verbosity >= 2)
# Args: $1...=message
pr_verbose() {
_pr_echo 2 "$*"
}
# Print a verbose message without trailing newline (verbosity >= 2)
# Args: $1...=message
pr_verbose_nol() {
_pr_echo_nol 2 "$*"
}
# Print a debug message in blue (verbosity >= 3)
# Args: $1...=message
pr_debug() {
_pr_echo 3 "\033[34m(debug) $*\033[0m"
}
# Print a "How to fix" explanation when --explain is enabled
# Args: $1...=fix description
explain() {
if [ "$opt_explain" = 1 ]; then
pr_info ''
pr_info "> \033[41m\033[30mHow to fix:\033[0m $*"
fi
}
# Convert a CVE ID to its human-readable vulnerability name
# Args: $1=cve_id (e.g. "CVE-2017-5753")
cve2name() {
_cve_registry_field "$1" 4
}
g_is_cpu_affected_cached=0

View File

@@ -0,0 +1,845 @@
# vim: set ts=4 sw=4 sts=4 et:
# Helpers for is_cpu_affected: encode the 4 patterns for setting affected_* variables.
# Each function takes the variable suffix as $1 (e.g. "variantl1tf", not "affected_variantl1tf").
# Variables hold 1 (not affected / immune) or 0 (affected / vuln); empty = not yet decided.
# Set affected_$1 to 1 (not affected) unconditionally.
# Use for: hardware capability bits (cap_rdcl_no, cap_ssb_no, cap_gds_no, cap_tsa_*_no),
# is_cpu_specex_free results, and vendor-wide immune facts (AMD/L1TF, Cavium, etc.).
# This always wins and cannot be overridden by _infer_vuln (which only fires on empty).
# Must not be followed by _set_vuln for the same variable in the same code path.
_set_immune() { eval "affected_$1=1"; }
# Set affected_$1 to 0 (affected) unconditionally.
# Use for: confirmed-vuln model/erratum lists, ARM unknown-CPU fallback.
# Note: intentionally overrides a prior _infer_immune (1) — this is required for ARM
# big.LITTLE cumulative logic where a second vuln core must override a prior safe core.
# Must not be called after _set_immune for the same variable in the same code path.
_set_vuln() { eval "affected_$1=0"; }
# Set affected_$1 to 1 (not affected) only if not yet decided (currently empty).
# Use for: model/family whitelists, per-part ARM immune inferences,
# AMD/ARM partial immunity (immune on this variant axis but not others).
_infer_immune() { eval "[ -z \"\$affected_$1\" ] && affected_$1=1 || :"; }
# Set affected_$1 to 0 (affected) only if not yet decided (currently empty).
# Use for: family-level catch-all fallbacks (Intel L1TF non-whitelist, itlbmh non-whitelist).
_infer_vuln() { eval "[ -z \"\$affected_$1\" ] && affected_$1=0 || :"; }
# Return the cached affected_* status for a given CVE
# Args: $1=cve_id
# Returns: 0 if affected, 1 if not affected
# Callers: is_cpu_affected
_is_cpu_affected_cached() {
local suffix
suffix=$(_cve_registry_field "$1" 3)
# shellcheck disable=SC2086
eval "return \$affected_${suffix}"
}
# Determine whether the current CPU is affected by a given CVE using whitelist logic
# Args: $1=cve_id (one of the $g_supported_cve_list items)
# Returns: 0 if affected, 1 if not affected
is_cpu_affected() {
local result cpuid_hex reptar_ucode_list bpi_ucode_list tuple fixed_ucode_ver affected_fmspi affected_fms ucode_platformid_mask affected_cpuid i cpupart cpuarch
# if CPU is Intel and is in our dump of the Intel official affected CPUs page, use it:
if is_intel; then
cpuid_hex=$(printf "0x%08X" $((cpu_cpuid)))
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
if [ -z "$g_intel_line" ]; then
g_intel_line=no
pr_debug "is_cpu_affected: $cpuid_hex not in Intel database"
fi
fi
if [ "$g_intel_line" != "no" ]; then
result=$(echo "$g_intel_line" | grep -Eo ,"$(echo "$1" | cut -c5-)"'=[^,]+' | cut -d= -f2)
pr_debug "is_cpu_affected: inteldb for $1 says '$result'"
# handle special case for Foreshadow SGX (CVE-2018-3615):
# even if we are affected to L1TF (CVE-2018-3620/CVE-2018-3646), if there's no SGX on our CPU,
# then we're not affected to the original Foreshadow.
if [ "$1" = "CVE-2018-3615" ] && [ "$cap_sgx" = 0 ]; then
# not affected
return 1
fi
# /special case
if [ "$result" = "N" ]; then
# not affected
return 1
elif [ -n "$result" ]; then
# non-empty string != N means affected
return 0
fi
fi
fi
# Otherwise, do it ourselves
if [ "$g_is_cpu_affected_cached" = 1 ]; then
_is_cpu_affected_cached "$1"
return $?
fi
affected_variant1=''
affected_variant2=''
affected_variant3=''
affected_variant3a=''
affected_variant4=''
affected_variantl1tf=''
affected_msbds=''
affected_mfbds=''
affected_mlpds=''
affected_mdsum=''
affected_taa=''
affected_itlbmh=''
affected_srbds=''
affected_mmio=''
affected_sls=''
# DIV0, FPDSS, 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:
_set_immune tsa
# Retbleed: AMD (CVE-2022-29900) and Intel (CVE-2022-29901) specific:
_set_immune retbleed
# Downfall, Reptar, RFDS, ITS & BPI are Intel specific, look for "is_intel" below:
_set_immune downfall
_set_immune reptar
_set_immune rfds
_set_immune its
_set_immune bpi
# VMScape affects Intel, AMD and Hygon — set immune, overridden below:
_set_immune vmscape
if is_cpu_mds_free; then
_infer_immune msbds
_infer_immune mfbds
_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
_infer_immune taa
pr_debug "is_cpu_affected: cpu not affected by TSX Asynhronous Abort"
fi
if is_cpu_srbds_free; then
_infer_immune srbds
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)
if { [ "$cpu_vendor" = "CentaurHauls" ] || [ "$cpu_vendor" = "Shanghai" ]; } && [ "$cpu_family" = 7 ]; then
_infer_immune variant2
pr_debug "is_cpu_affected: Centaur/Zhaoxin family 7 immune to Spectre V2 (NO_SPECTRE_V2)"
fi
if is_cpu_specex_free; then
_set_immune variant1
_set_immune variant2
_set_immune variant3
_set_immune variant3a
_set_immune variant4
_set_immune variantl1tf
_set_immune msbds
_set_immune mfbds
_set_immune mlpds
_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
# https://github.com/paboldin/meltdown-exploit/issues/19 ^F E5200 => meltdown affected
# model name : Pentium(R) Dual-Core CPU E5200 @ 2.50GHz
if echo "$cpu_friendly_name" | grep -qE 'Pentium\(R\) Dual-Core[[:space:]]+CPU[[:space:]]+E[0-9]{4}K?'; then
_set_vuln variant1
_infer_immune variant2
_set_vuln variant3
fi
if [ "$cap_rdcl_no" = 1 ]; then
# capability bit for future Intel processor that will explicitly state
# that they're not affected to Meltdown
# this var is set in check_cpu()
_set_immune variant3
_set_immune variantl1tf
pr_debug "is_cpu_affected: RDCL_NO is set so not vuln to meltdown nor l1tf"
fi
if [ "$cap_ssb_no" = 1 ]; then
# capability bit for future Intel processor that will explicitly state
# that they're not affected to Variant 4
# this var is set in check_cpu()
_set_immune variant4
pr_debug "is_cpu_affected: SSB_NO is set so not vuln to affected_variant4"
fi
if is_cpu_ssb_free; then
_infer_immune variant4
pr_debug "is_cpu_affected: cpu not affected by speculative store bypass so not vuln to affected_variant4"
fi
# variant 3a
if [ "$cpu_family" = 6 ]; then
if [ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNL" ] || [ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNM" ]; then
pr_debug "is_cpu_affected: xeon phi immune to variant 3a"
_infer_immune variant3a
elif [ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_MID" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_D" ]; then
# https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00115.html
# https://github.com/speed47/spectre-meltdown-checker/issues/310
# => silvermont CPUs (aka cherry lake for tablets and brawsell for mobile/desktop) don't seem to be affected
# => goldmont ARE affected
pr_debug "is_cpu_affected: silvermont immune to variant 3a"
_infer_immune variant3a
fi
fi
# L1TF (cap_rdcl_no already checked above)
if [ "$cpu_family" = 6 ]; then
if [ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL_TABLET" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL_MID" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_BONNELL" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_BONNELL_MID" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_MID" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_MID2" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT_NP" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_PLUS" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNL" ] ||
[ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNM" ]; then
pr_debug "is_cpu_affected: intel family 6 but model known to be immune to l1tf"
_infer_immune variantl1tf
else
pr_debug "is_cpu_affected: intel family 6 is vuln to l1tf"
_infer_vuln variantl1tf
fi
elif [ "$cpu_family" -lt 6 ]; then
pr_debug "is_cpu_affected: intel family < 6 is immune to l1tf"
_infer_immune variantl1tf
fi
# Downfall
if [ "$cap_gds_no" = 1 ]; then
# capability bit for future Intel processors that will explicitly state
# that they're unaffected by GDS. Also set by hypervisors on virtual CPUs
# so that the guest kernel doesn't try to mitigate GDS when it's already mitigated on the host
pr_debug "is_cpu_affected: downfall: not affected (GDS_NO)"
_set_immune downfall
elif [ "$cpu_family" = 6 ]; then
# model blacklist from the kernel (arch/x86/kernel/cpu/common.c cpu_vuln_blacklist):
# 8974eb588283 (initial list) + c9f4c45c8ec3 (added Skylake/Skylake_L client)
set -u
if [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_X" ] ||
[ "$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_TIGERLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_TIGERLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ROCKETLAKE" ]; then
pr_debug "is_cpu_affected: downfall: affected"
_set_vuln downfall
elif [ "$cap_avx2" = 0 ] && [ "$cap_avx512" = 0 ]; then
pr_debug "is_cpu_affected: downfall: no avx; immune"
_infer_immune downfall
else
# Intel family 6 CPU with AVX2 or AVX512, not in the known-affected list
# and GDS_NO not set: assume affected (whitelist principle)
pr_debug "is_cpu_affected: downfall: unknown AVX-capable CPU, defaulting to affected"
_infer_vuln downfall
fi
set +u
fi
# RFDS (Register File Data Sampling, CVE-2023-28746)
# kernel cpu_vuln_blacklist (8076fcde016c, initial model list)
# immunity: ARCH_CAP_RFDS_NO (bit 27 of IA32_ARCH_CAPABILITIES)
# vendor scope: Intel only (family 6), Atom/hybrid cores
if [ "$cap_rfds_no" = 1 ]; then
pr_debug "is_cpu_affected: rfds: not affected (RFDS_NO)"
_set_immune rfds
elif [ "$cpu_family" = 6 ]; then
set -u
if [ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_PLUS" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_TREMONT_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GRACEMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ALDERLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ALDERLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_RAPTORLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_RAPTORLAKE_P" ] ||
[ "$cpu_model" = "$INTEL_FAM6_RAPTORLAKE_S" ]; then
pr_debug "is_cpu_affected: rfds: affected"
_set_vuln rfds
fi
set +u
fi
# ITS (Indirect Target Selection, CVE-2024-28956)
# kernel vulnerable_to_its() + cpu_vuln_blacklist (159013a7ca18)
# immunity: ARCH_CAP_ITS_NO (bit 62 of IA32_ARCH_CAPABILITIES)
# immunity: X86_FEATURE_BHI_CTRL (none of the affected CPUs have this)
# vendor scope: Intel only (family 6), with stepping constraints on some models
if [ "$cap_its_no" = 1 ]; then
pr_debug "is_cpu_affected: its: not affected (ITS_NO)"
_set_immune its
elif [ "$cpu_family" = 6 ]; then
set -u
if { [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_X" ] && [ "$cpu_stepping" -gt 5 ]; } ||
{ [ "$cpu_model" = "$INTEL_FAM6_KABYLAKE_L" ] && [ "$cpu_stepping" -gt 11 ]; } ||
{ [ "$cpu_model" = "$INTEL_FAM6_KABYLAKE" ] && [ "$cpu_stepping" -gt 12 ]; } ||
[ "$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_TIGERLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_TIGERLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ROCKETLAKE" ]; then
pr_debug "is_cpu_affected: its: affected"
_set_vuln its
fi
set +u
fi
# Reptar
# the only way to know whether a CPU is vuln, is to check whether there is a known ucode update for it,
# as the mitigation is only ucode-based and there's no flag exposed by the kernel or by an updated ucode.
# we have to hardcode the truthtable of affected CPUs vs updated ucodes...
# https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/redundant-prefix-issue.html
# list initially taken from:
# https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files/commit/ece0d294a29a1375397941a4e6f2f7217910bc89#diff-e6fad0f2abbac6c9603b2e8f88fe1d151a83de708aeca1c1d93d881c958ecba4R26
# updated 2026-04 with Intel affected processor list + releasenote.md:
# added 06-9a-04/40 (AZB), 06-bd-01/80 (Lunar Lake, post-dates Reptar: first ucode already includes fix)
g_reptar_fixed_ucode_version=''
reptar_ucode_list='
06-97-02/07,00000032
06-97-05/07,00000032
06-9a-03/80,00000430
06-9a-04/80,00000430
06-9a-04/40,00000005
06-6c-01/10,01000268
06-6a-06/87,0d0003b9
06-7e-05/80,000000c2
06-ba-02/e0,0000411c
06-b7-01/32,0000011d
06-a7-01/02,0000005d
06-bf-05/07,00000032
06-bf-02/07,00000032
06-ba-03/e0,0000411c
06-8f-08/87,2b0004d0
06-8f-07/87,2b0004d0
06-8f-06/87,2b0004d0
06-8f-05/87,2b0004d0
06-8f-04/87,2b0004d0
06-8f-08/10,2c000290
06-8c-01/80,000000b4
06-8c-00/ff,000000b4
06-8d-01/c2,0000004e
06-8d-00/c2,0000004e
06-8c-02/c2,00000034
06-bd-01/80,0000011f
'
for tuple in $reptar_ucode_list; do
fixed_ucode_ver=$((0x$(echo "$tuple" | cut -d, -f2)))
affected_fmspi=$(echo "$tuple" | cut -d, -f1)
affected_fms=$(echo "$affected_fmspi" | cut -d/ -f1)
ucode_platformid_mask=0x$(echo "$affected_fmspi" | cut -d/ -f2)
affected_cpuid=$(
fms2cpuid \
0x"$(echo "$affected_fms" | cut -d- -f1)" \
0x"$(echo "$affected_fms" | cut -d- -f2)" \
0x"$(echo "$affected_fms" | cut -d- -f3)"
)
if [ "$cpu_cpuid" = "$affected_cpuid" ] && [ $((cpu_platformid & ucode_platformid_mask)) -gt 0 ]; then
_set_vuln reptar
g_reptar_fixed_ucode_version=$fixed_ucode_ver
break
fi
done
# if we didn't match the ucode list above, also check the model blacklist:
# Intel never tells about their EOL CPUs, so more CPUs might be affected
# than the ones that received a microcode update (e.g. steppings with
# different platform IDs that were dropped before the Reptar fix).
if [ -z "$g_reptar_fixed_ucode_version" ] && [ "$cpu_family" = 6 ]; then
set -u
if [ "$cpu_model" = "$INTEL_FAM6_ALDERLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ALDERLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ROCKETLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_TIGERLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_TIGERLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SAPPHIRERAPIDS_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_RAPTORLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_RAPTORLAKE_P" ] ||
[ "$cpu_model" = "$INTEL_FAM6_RAPTORLAKE_S" ] ||
[ "$cpu_model" = "$INTEL_FAM6_LUNARLAKE_M" ]; then
pr_debug "is_cpu_affected: reptar: affected (model match, no known fixing ucode)"
_set_vuln reptar
fi
set +u
fi
# Retbleed (Intel, CVE-2022-29901): Skylake through Rocket Lake, or any CPU with RSBA
# kernel cpu_vuln_blacklist for RETBLEED (6b80b59b3555, 6ad0ad2bf8a6, f54d45372c6a)
# plus ARCH_CAP_RSBA catch-all (bit 2 of IA32_ARCH_CAPABILITIES)
if [ "$cap_rsba" = 1 ]; then
_set_vuln retbleed
elif [ "$cpu_family" = 6 ]; then
if [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_KABYLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_KABYLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_CANNONLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_COMETLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_COMETLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_LAKEFIELD" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ROCKETLAKE" ]; then
_set_vuln retbleed
fi
fi
# VMScape (CVE-2025-40300): Intel model blacklist
# kernel cpu_vuln_blacklist VMSCAPE (a508cec6e521 + 8a68d64bb103)
# immunity: no ARCH_CAP bits (purely blacklist-based)
# note: kernel only sets bug on bare metal (!X86_FEATURE_HYPERVISOR)
# vendor scope: Intel + AMD + Hygon (AMD/Hygon handled below)
if [ "$cpu_family" = 6 ]; then
set -u
if [ "$cpu_model" = "$INTEL_FAM6_SANDYBRIDGE_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SANDYBRIDGE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_IVYBRIDGE_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_IVYBRIDGE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_HASWELL" ] ||
[ "$cpu_model" = "$INTEL_FAM6_HASWELL_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_HASWELL_G" ] ||
[ "$cpu_model" = "$INTEL_FAM6_HASWELL_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_BROADWELL_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_BROADWELL_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_BROADWELL_G" ] ||
[ "$cpu_model" = "$INTEL_FAM6_BROADWELL" ] ||
[ "$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_CANNONLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_COMETLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_COMETLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ALDERLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ALDERLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_RAPTORLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_RAPTORLAKE_P" ] ||
[ "$cpu_model" = "$INTEL_FAM6_RAPTORLAKE_S" ] ||
[ "$cpu_model" = "$INTEL_FAM6_METEORLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ARROWLAKE_H" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ARROWLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ARROWLAKE_U" ] ||
[ "$cpu_model" = "$INTEL_FAM6_LUNARLAKE_M" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SAPPHIRERAPIDS_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_GRANITERAPIDS_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_EMERALDRAPIDS_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GRACEMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_CRESTMONT_X" ]; then
pr_debug "is_cpu_affected: vmscape: affected"
_set_vuln vmscape
fi
set +u
fi
# BPI (Branch Privilege Injection, CVE-2024-45332)
# microcode-only fix, no kernel X86_BUG flag, no CPUID/MSR indicator for the fix.
# We have to hardcode the truthtable of affected CPUs vs fixing ucodes,
# same approach as Reptar (see above).
# https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/indirect-branch-predictor-delayed-updates.html
# list taken from Intel affected processor list + Intel-Linux-Processor-Microcode-Data-Files releasenote.md
# format: FF-MM-SS/platformid_mask,fixed_ucode_version
g_bpi_fixed_ucode_version=''
bpi_ucode_list='
06-9e-0d/22,00000104
06-8e-0a/c0,000000f6
06-8e-0b/d0,000000f6
06-8e-0c/94,00000100
06-a5-02/20,00000100
06-a5-03/22,00000100
06-a5-05/22,00000100
06-a6-00/80,00000102
06-a6-01/80,00000100
06-a7-01/02,00000065
06-7e-05/80,000000cc
06-6a-06/87,0d000421
06-6c-01/10,010002f1
06-8c-01/80,000000be
06-8c-02/c2,0000003e
06-8d-01/c2,00000058
06-97-02/07,0000003e
06-97-05/07,0000003e
06-9a-03/80,0000043b
06-9a-04/80,0000043b
06-9a-04/40,0000000c
06-be-00/19,00000021
06-b7-01/32,00000133
06-ba-02/e0,00006134
06-ba-03/e0,00006134
06-bf-02/07,0000003e
06-bf-05/07,0000003e
06-aa-04/e6,00000028
06-b5-00/80,0000000d
06-c5-02/82,0000011b
06-c6-02/82,0000011b
06-bd-01/80,00000125
06-55-0b/bf,07002b01
06-8f-07/87,2b000661
06-8f-08/87,2b000661
06-8f-08/10,2c000421
06-cf-02/87,210002d3
06-7a-08/01,00000026
'
for tuple in $bpi_ucode_list; do
fixed_ucode_ver=$((0x$(echo "$tuple" | cut -d, -f2)))
affected_fmspi=$(echo "$tuple" | cut -d, -f1)
affected_fms=$(echo "$affected_fmspi" | cut -d/ -f1)
ucode_platformid_mask=0x$(echo "$affected_fmspi" | cut -d/ -f2)
affected_cpuid=$(
fms2cpuid \
0x"$(echo "$affected_fms" | cut -d- -f1)" \
0x"$(echo "$affected_fms" | cut -d- -f2)" \
0x"$(echo "$affected_fms" | cut -d- -f3)"
)
if [ "$cpu_cpuid" = "$affected_cpuid" ] && [ $((cpu_platformid & ucode_platformid_mask)) -gt 0 ]; then
_set_vuln bpi
g_bpi_fixed_ucode_version=$fixed_ucode_ver
break
fi
done
# if we didn't match the ucode list above, also check the model blacklist:
# Intel never tells about their EOL CPUs, so more CPUs might be affected
# than the ones that received a microcode update. In that case, we flag
# the CPU as affected but g_bpi_fixed_ucode_version stays empty (the CVE
# check will handle this by reporting VULN with no known fix).
if [ -z "$g_bpi_fixed_ucode_version" ] && [ "$cpu_family" = 6 ]; then
set -u
if [ "$cpu_model" = "$INTEL_FAM6_KABYLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_KABYLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_COMETLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_COMETLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ROCKETLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ICELAKE_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_TIGERLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_TIGERLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ALDERLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ALDERLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GRACEMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_RAPTORLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_RAPTORLAKE_P" ] ||
[ "$cpu_model" = "$INTEL_FAM6_RAPTORLAKE_S" ] ||
[ "$cpu_model" = "$INTEL_FAM6_METEORLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ARROWLAKE_H" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ARROWLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ARROWLAKE_U" ] ||
[ "$cpu_model" = "$INTEL_FAM6_LUNARLAKE_M" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SAPPHIRERAPIDS_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_EMERALDRAPIDS_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_PLUS" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_CRESTMONT" ]; then
pr_debug "is_cpu_affected: bpi: affected (model match, no known fixing ucode)"
_set_vuln bpi
fi
set +u
fi
elif is_amd || is_hygon; then
# AMD revised their statement about affected_variant2 => affected
# https://www.amd.com/en/corporate/speculative-execution
_set_vuln variant1
_set_vuln variant2
_infer_immune variant3
# https://www.amd.com/en/corporate/security-updates
# "We have not identified any AMD x86 products susceptible to the Variant 3a vulnerability in our analysis to-date."
_infer_immune variant3a
if is_cpu_ssb_free; then
_infer_immune variant4
pr_debug "is_cpu_affected: cpu not affected by speculative store bypass so not vuln to affected_variant4"
fi
_set_immune variantl1tf
# DIV0 (Zen1/Zen+)
# 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.
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
amd_legacy_erratum "$(amd_model_range 0x17 0xa0 0x0 0xaf 0xf)" && _set_vuln zenbleed
# Inception (according to kernel, zen 1 to 4)
if [ "$cpu_family" = $((0x17)) ] || [ "$cpu_family" = $((0x19)) ]; then
_set_vuln inception
fi
# TSA (Zen 3/4 are affected, unless CPUID says otherwise)
if [ "$cap_tsa_sq_no" = 1 ] && [ "$cap_tsa_l1_no" = 1 ]; then
# capability bits for AMD processors that explicitly state
# they're not affected to TSA-SQ and TSA-L1
# these vars are set in check_cpu()
pr_debug "is_cpu_affected: TSA_SQ_NO and TSA_L1_NO are set so not vuln to TSA"
_set_immune tsa
elif [ "$cpu_family" = $((0x19)) ]; then
_set_vuln tsa
fi
# Retbleed (AMD, CVE-2022-29900): families 0x15-0x17 (kernel X86_BUG_RETBLEED)
if [ "$cpu_family" = $((0x15)) ] || [ "$cpu_family" = $((0x16)) ] || [ "$cpu_family" = $((0x17)) ]; then
_set_vuln retbleed
fi
# VMScape (CVE-2025-40300): AMD families 0x17/0x19/0x1a, Hygon family 0x18
# kernel cpu_vuln_blacklist VMSCAPE (a508cec6e521)
if is_amd; then
if [ "$cpu_family" = $((0x17)) ] || [ "$cpu_family" = $((0x19)) ] || [ "$cpu_family" = $((0x1a)) ]; then
pr_debug "is_cpu_affected: vmscape: AMD family $cpu_family affected"
_set_vuln vmscape
fi
elif is_hygon; then
if [ "$cpu_family" = $((0x18)) ]; then
pr_debug "is_cpu_affected: vmscape: Hygon family $cpu_family affected"
_set_vuln vmscape
fi
fi
elif [ "$cpu_vendor" = CAVIUM ]; then
_set_immune variant3
_set_immune variant3a
_set_immune variantl1tf
elif [ "$cpu_vendor" = PHYTIUM ]; then
_set_immune variant3
_set_immune variant3a
_set_immune variantl1tf
elif [ "$cpu_vendor" = ARM ]; then
# ARM
# reference: https://developer.arm.com/support/security-update
# some devices (phones or other) have several ARMs and as such different part numbers,
# an example is "bigLITTLE". we shouldn't rely on the first CPU only, so we check the whole list
i=0
for cpupart in $cpu_part_list; do
i=$((i + 1))
# do NOT quote $cpu_arch_list below
# shellcheck disable=SC2086
cpuarch=$(echo $cpu_arch_list | awk '{ print $'$i' }')
pr_debug "checking cpu$i: <$cpupart> <$cpuarch>"
# some kernels report AArch64 instead of 8
[ "$cpuarch" = "AArch64" ] && cpuarch=8
# some kernels report architecture with suffix (e.g. "5TEJ" for ARMv5TEJ), extract numeric prefix
cpuarch=$(echo "$cpuarch" | grep -oE '^[0-9]+')
if [ -n "$cpupart" ] && [ -n "$cpuarch" ]; then
# Cortex-R7 and Cortex-R8 are real-time and only used in medical devices or such
# I can't find their CPU part number, but it's probably not that useful anyway
# model R7 R8 A8 A9 A12 A15 A17 A57 A72 A73 A75 A76 A77 Neoverse-N1 Neoverse-V1 Neoverse-N1 Neoverse-V2
# part ? ? c08 c09 c0d c0f c0e d07 d08 d09 d0a d0b d0d d0c d40 d49 d4f
# arch 7? 7? 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8
#
# Whitelist identified non-affected processors, use vulnerability information from
# https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability
# Partnumbers can be found here:
# https://github.com/gcc-mirror/gcc/blob/master/gcc/config/arm/arm-cpus.in
#
# Maintain cumulative check of vulnerabilities -
# if at least one of the cpu is affected, then the system is affected
if [ "$cpuarch" = 7 ] && echo "$cpupart" | grep -q -w -e 0xc08 -e 0xc09 -e 0xc0d -e 0xc0e; then
_set_vuln variant1
_set_vuln variant2
_infer_immune variant3
_infer_immune variant3a
_infer_immune variant4
pr_debug "checking cpu$i: armv7 A8/A9/A12/A17 non affected to variants 3, 3a & 4"
elif [ "$cpuarch" = 7 ] && echo "$cpupart" | grep -q -w -e 0xc0f; then
_set_vuln variant1
_set_vuln variant2
_infer_immune variant3
_set_vuln variant3a
_infer_immune variant4
pr_debug "checking cpu$i: armv7 A15 non affected to variants 3 & 4"
elif [ "$cpuarch" = 8 ] && echo "$cpupart" | grep -q -w -e 0xd07 -e 0xd08; then
_set_vuln variant1
_set_vuln variant2
_infer_immune variant3
_set_vuln variant3a
_set_vuln variant4
pr_debug "checking cpu$i: armv8 A57/A72 non affected to variants 3"
elif [ "$cpuarch" = 8 ] && echo "$cpupart" | grep -q -w -e 0xd09; then
_set_vuln variant1
_set_vuln variant2
_infer_immune variant3
_infer_immune variant3a
_set_vuln variant4
pr_debug "checking cpu$i: armv8 A73 non affected to variants 3 & 3a"
elif [ "$cpuarch" = 8 ] && echo "$cpupart" | grep -q -w -e 0xd0a; then
_set_vuln variant1
_set_vuln variant2
_set_vuln variant3
_infer_immune variant3a
_set_vuln variant4
pr_debug "checking cpu$i: armv8 A75 non affected to variant 3a"
elif [ "$cpuarch" = 8 ] && echo "$cpupart" | grep -q -w -e 0xd0b -e 0xd0c -e 0xd0d; then
_set_vuln variant1
_infer_immune variant2
_infer_immune variant3
_infer_immune variant3a
_set_vuln variant4
pr_debug "checking cpu$i: armv8 A76/A77/NeoverseN1 non affected to variant 2, 3 & 3a"
elif [ "$cpuarch" = 8 ] && echo "$cpupart" | grep -q -w -e 0xd40 -e 0xd49 -e 0xd4f; then
_set_vuln variant1
_infer_immune variant2
_infer_immune variant3
_infer_immune variant3a
_infer_immune variant4
pr_debug "checking cpu$i: armv8 NeoverseN2/V1/V2 non affected to variant 2, 3, 3a & 4"
elif [ "$cpuarch" -le 7 ] || { [ "$cpuarch" = 8 ] && [ $((cpupart)) -lt $((0xd07)) ]; }; then
_infer_immune variant1
_infer_immune variant2
_infer_immune variant3
_infer_immune variant3a
_infer_immune variant4
pr_debug "checking cpu$i: arm arch$cpuarch, all immune (v7 or v8 and model < 0xd07)"
else
_set_vuln variant1
_set_vuln variant2
_set_vuln variant3
_set_vuln variant3a
_set_vuln variant4
pr_debug "checking cpu$i: arm unknown arch$cpuarch part$cpupart, considering vuln"
fi
fi
pr_debug "is_cpu_affected: for cpu$i and so far, we have <$affected_variant1> <$affected_variant2> <$affected_variant3> <$affected_variant3a> <$affected_variant4>"
done
_set_immune variantl1tf
fi
# we handle iTLB Multihit here (not linked to is_specex_free)
if is_intel; then
# commit f9aa6b73a407b714c9aac44734eb4045c893c6f7
if [ "$cpu_family" = 6 ]; then
if [ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL_TABLET" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL_MID" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_BONNELL" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_BONNELL_MID" ] ||
[ "$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_AIRMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNL" ] ||
[ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNM" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_MID2" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_GOLDMONT_PLUS" ]; then
pr_debug "is_cpu_affected: intel family 6 but model known to be immune to itlbmh"
_infer_immune itlbmh
else
pr_debug "is_cpu_affected: intel family 6 is vuln to itlbmh"
_infer_vuln itlbmh
fi
elif [ "$cpu_family" -lt 6 ]; then
pr_debug "is_cpu_affected: intel family < 6 is immune to itlbmh"
_infer_immune itlbmh
fi
else
pr_debug "is_cpu_affected: non-intel not affected to itlbmh"
_infer_immune itlbmh
fi
# SLS (Straight-Line Speculation):
# - x86_64: all CPUs are affected (compile-time mitigation CONFIG_MITIGATION_SLS)
# - arm64 (CVE-2020-13844): Cortex-A32/A34/A35/A53/A57/A72/A73 confirmed affected,
# and broadly all speculative Armv8-A cores. No kernel mitigation merged.
# Part numbers: A32=0xd01 A34=0xd02 A53=0xd03 A35=0xd04 A57=0xd07 A72=0xd08 A73=0xd09
# Plus later speculative cores: A75=0xd0a A76=0xd0b A77=0xd0d N1=0xd0c V1=0xd40 N2=0xd49 V2=0xd4f
if is_intel || is_amd; then
_infer_vuln sls
elif [ "$cpu_vendor" = ARM ]; then
for cpupart in $cpu_part_list; do
if echo "$cpupart" | grep -q -w -e 0xd01 -e 0xd02 -e 0xd03 -e 0xd04 \
-e 0xd07 -e 0xd08 -e 0xd09 -e 0xd0a -e 0xd0b -e 0xd0c -e 0xd0d \
-e 0xd40 -e 0xd49 -e 0xd4f; then
_set_vuln sls
fi
done
# non-speculative ARM cores (arch <= 7, or early v8 models) are not affected
_infer_immune sls
else
_infer_immune sls
fi
# 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"
}
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
[ "$cap_sgx" = 0 ] && _set_immune variantl1tf_sgx
pr_debug "is_cpu_affected: variantl1tf_sgx=<$affected_variantl1tf_sgx>"
g_is_cpu_affected_cached=1
_is_cpu_affected_cached "$1"
return $?
}

290
src/libs/210_cpu_detect.sh Normal file
View File

@@ -0,0 +1,290 @@
# vim: set ts=4 sw=4 sts=4 et:
# Check whether the CPU is known to not perform speculative execution
# Returns: 0 if the CPU is speculation-free, 1 otherwise
is_cpu_specex_free() {
# source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c#n882
# { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SALTWELL, X86_FEATURE_ANY },
# { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SALTWELL_TABLET, X86_FEATURE_ANY },
# { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_BONNELL_MID, X86_FEATURE_ANY },
# { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SALTWELL_MID, X86_FEATURE_ANY },
# { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_BONNELL, X86_FEATURE_ANY },
# { X86_VENDOR_CENTAUR, 5 },
# { X86_VENDOR_INTEL, 5 },
# { X86_VENDOR_NSC, 5 },
# { X86_VENDOR_ANY, 4 },
parse_cpu_details
if is_intel; then
if [ "$cpu_family" = 6 ]; then
if [ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL_TABLET" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_BONNELL_MID" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SALTWELL_MID" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_BONNELL" ]; then
return 0
fi
elif [ "$cpu_family" = 5 ]; then
return 0
fi
fi
# Centaur family 5 and NSC family 5 are also non-speculative
if [ "$cpu_vendor" = "CentaurHauls" ] && [ "$cpu_family" = 5 ]; then
return 0
fi
if [ "$cpu_vendor" = "Geode by NSC" ] && [ "$cpu_family" = 5 ]; then
return 0
fi
[ "$cpu_family" = 4 ] && return 0
return 1
}
# Check whether the CPU is known to be unaffected by microarchitectural data sampling (MDS)
# Returns: 0 if MDS-free, 1 if affected or unknown
is_cpu_mds_free() {
# source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c
#VULNWL_INTEL(ATOM_GOLDMONT, NO_MDS | NO_L1TF),
#VULNWL_INTEL(ATOM_GOLDMONT_X, NO_MDS | NO_L1TF),
#VULNWL_INTEL(ATOM_GOLDMONT_PLUS, NO_MDS | NO_L1TF),
#/* AMD Family 0xf - 0x12 */
#VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
#VULNWL_AMD(0x10, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
#VULNWL_AMD(0x11, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
#VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS),
#/* FAMILY_ANY must be last, otherwise 0x0f - 0x12 matches won't work */
#VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS),
#VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS),
parse_cpu_details
if is_intel; then
if [ "$cpu_family" = 6 ]; then
if [ "$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
[ "$cap_mds_no" = 1 ] && return 0
fi
# official statement from AMD says none of their CPUs are affected
# https://www.amd.com/en/corporate/product-security
# https://www.amd.com/system/files/documents/security-whitepaper.pdf
if is_amd; then
return 0
elif is_hygon; then
return 0
elif [ "$cpu_vendor" = CAVIUM ]; then
return 0
elif [ "$cpu_vendor" = PHYTIUM ]; then
return 0
elif [ "$cpu_vendor" = ARM ]; then
return 0
fi
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() {
if ! is_intel; then
return 0
# is intel
elif [ "$cap_taa_no" = 1 ] || [ "$cap_rtm" = 0 ]; then
return 0
fi
return 1
}
# Check whether the CPU is known to be unaffected by Special Register Buffer Data Sampling (SRBDS)
# Returns: 0 if SRBDS-free, 1 if affected or unknown
is_cpu_srbds_free() {
# source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c
#
# A processor is affected by SRBDS if its Family_Model and stepping is in the
# following list, with the exception of the listed processors
# exporting MDS_NO while Intel TSX is available yet not enabled. The
# latter class of processors are only affected when Intel TSX is enabled
# by software using TSX_CTRL_MSR otherwise they are not affected.
#
# ============= ============ ========
# common name Family_Model Stepping
# ============= ============ ========
# IvyBridge 06_3AH All (INTEL_FAM6_IVYBRIDGE)
#
# Haswell 06_3CH All (INTEL_FAM6_HASWELL)
# Haswell_L 06_45H All (INTEL_FAM6_HASWELL_L)
# Haswell_G 06_46H All (INTEL_FAM6_HASWELL_G)
#
# Broadwell_G 06_47H All (INTEL_FAM6_BROADWELL_G)
# Broadwell 06_3DH All (INTEL_FAM6_BROADWELL)
#
# Skylake_L 06_4EH All (INTEL_FAM6_SKYLAKE_L)
# Skylake 06_5EH All (INTEL_FAM6_SKYLAKE)
#
# Kabylake_L 06_8EH <=0xC (MDS_NO) (INTEL_FAM6_KABYLAKE_L)
#
# Kabylake 06_9EH <=0xD (MDS_NO) (INTEL_FAM6_KABYLAKE)
# ============= ============ ========
parse_cpu_details
if is_intel; then
if [ "$cpu_family" = 6 ]; then
if [ "$cpu_model" = "$INTEL_FAM6_IVYBRIDGE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_HASWELL" ] ||
[ "$cpu_model" = "$INTEL_FAM6_HASWELL_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_HASWELL_G" ] ||
[ "$cpu_model" = "$INTEL_FAM6_BROADWELL_G" ] ||
[ "$cpu_model" = "$INTEL_FAM6_BROADWELL" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE" ]; then
return 1
elif [ "$cpu_model" = "$INTEL_FAM6_KABYLAKE_L" ] && [ "$cpu_stepping" -le 12 ] ||
[ "$cpu_model" = "$INTEL_FAM6_KABYLAKE" ] && [ "$cpu_stepping" -le 13 ]; then
if [ "$cap_mds_no" -eq 1 ] && { [ "$cap_rtm" -eq 0 ] || [ "$cap_tsx_ctrl_rtm_disable" -eq 1 ] || [ "$cap_tsx_force_abort_rtm_disable" -eq 1 ]; }; then
return 0
else
return 1
fi
fi
fi
fi
return 0
}
# Check whether the CPU is known to be unaffected by MMIO Stale Data (CVE-2022-21123/21125/21166)
# Returns: 0 if MMIO-free, 1 if affected or unknown
is_cpu_mmio_free() {
# source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c
#
# CPU affection logic from kernel (51802186158c, v5.19):
# Bug is set when: cpu_matches(blacklist, MMIO) AND NOT arch_cap_mmio_immune()
# arch_cap_mmio_immune() requires ALL THREE bits set:
# ARCH_CAP_FBSDP_NO (bit 14) AND ARCH_CAP_PSDP_NO (bit 15) AND ARCH_CAP_SBDR_SSDP_NO (bit 13)
#
# Intel Family 6 model blacklist (unchanged since v5.19):
# HASWELL_X (0x3F)
# BROADWELL_D (0x56), BROADWELL_X (0x4F)
# SKYLAKE_X (0x55), SKYLAKE_L (0x4E), SKYLAKE (0x5E)
# KABYLAKE_L (0x8E), KABYLAKE (0x9E)
# ICELAKE_L (0x7E), ICELAKE_D (0x6C), ICELAKE_X (0x6A)
# COMETLAKE (0xA5), COMETLAKE_L (0xA6)
# LAKEFIELD (0x8A)
# ROCKETLAKE (0xA7)
# ATOM_TREMONT (0x96), ATOM_TREMONT_D (0x86), ATOM_TREMONT_L (0x9C)
#
# Vendor scope: Intel only. Non-Intel CPUs are not affected.
parse_cpu_details
# ARCH_CAP immunity: all three bits must be set
if [ "$cap_sbdr_ssdp_no" = 1 ] && [ "$cap_fbsdp_no" = 1 ] && [ "$cap_psdp_no" = 1 ]; then
return 0
fi
if is_intel; then
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
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() {
# source1: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/common.c#n945
# source2: https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/tree/arch/x86/kernel/cpu/common.c
# Only list CPUs that speculate but are immune, to avoid duplication of cpus listed in is_cpu_specex_free()
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT },
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT },
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT_X },
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT_MID },
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_CORE_YONAH },
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNL },
#{ X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNM },
#{ X86_VENDOR_AMD, 0x12, },
#{ X86_VENDOR_AMD, 0x11, },
#{ X86_VENDOR_AMD, 0x10, },
#{ X86_VENDOR_AMD, 0xf, },
parse_cpu_details
if is_intel; then
if [ "$cpu_family" = 6 ]; then
if [ "$cpu_model" = "$INTEL_FAM6_ATOM_AIRMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_D" ] ||
[ "$cpu_model" = "$INTEL_FAM6_ATOM_SILVERMONT_MID" ]; then
return 0
elif [ "$cpu_model" = "$INTEL_FAM6_CORE_YONAH" ] ||
[ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNL" ] ||
[ "$cpu_model" = "$INTEL_FAM6_XEON_PHI_KNM" ]; then
return 0
fi
fi
fi
if is_amd; then
if [ "$cpu_family" = "18" ] ||
[ "$cpu_family" = "17" ] ||
[ "$cpu_family" = "16" ] ||
[ "$cpu_family" = "15" ]; then
return 0
fi
fi
if is_hygon; then
return 1
fi
[ "$cpu_family" = 4 ] && return 0
return 1
}

214
src/libs/220_util_update.sh Normal file
View File

@@ -0,0 +1,214 @@
# vim: set ts=4 sw=4 sts=4 et:
# Print the tool name and version banner
show_header() {
pr_info "Spectre and Meltdown mitigation detection tool v$VERSION"
pr_info
}
# Convert Family-Model-Stepping triplet to a CPUID value (base-10 to stdout)
# Args: $1=family $2=model $3=stepping
fms2cpuid() {
local family model stepping extfamily lowfamily extmodel lowmodel
family="$1"
model="$2"
stepping="$3"
if [ "$((family))" -le 15 ]; then
extfamily=0
lowfamily=$((family))
else
# when we have a family > 0xF, then lowfamily is stuck at 0xF
# and extfamily is ADDED to it (as in "+"), to ensure old software
# never sees a lowfamily < 0xF for newer families
lowfamily=15
extfamily=$(((family) - 15))
fi
extmodel=$(((model & 0xF0) >> 4))
lowmodel=$(((model & 0x0F) >> 0))
echo $(((stepping & 0x0F) | (lowmodel << 4) | (lowfamily << 8) | (extmodel << 16) | (extfamily << 20)))
}
# Download a file using wget, curl, or fetch (whichever is available)
# Args: $1=url $2=output_file
download_file() {
local ret url file
url="$1"
file="$2"
if command -v wget >/dev/null 2>&1; then
wget -q "$url" -O "$file"
ret=$?
elif command -v curl >/dev/null 2>&1; then
curl -sL "$url" -o "$file"
ret=$?
elif command -v fetch >/dev/null 2>&1; then
fetch -q "$url" -o "$file"
ret=$?
else
echo ERROR "please install one of \`wget\`, \`curl\` of \`fetch\` programs"
unset file url
return 1
fi
unset file url
if [ "$ret" != 0 ]; then
echo ERROR "error $ret"
return $ret
fi
echo DONE
}
[ -z "$HOME" ] && HOME="$(getent passwd "$(whoami)" | cut -d: -f6)"
g_mcedb_cache="$HOME/.mcedb"
# Download and update the local microcode firmware database cache
# Sets: g_mcedb_tmp (temp file, cleaned up on exit)
update_fwdb() {
local previous_dbversion dbversion mcedb_revision iucode_tool nbfound linuxfw_hash mcedb_url intel_url linuxfw_url newfile line cpuid pfmask date version intel_timestamp intel_latest_date family model stepping sqlstm
show_header
set -e
if [ -r "$g_mcedb_cache" ]; then
previous_dbversion=$(awk '/^# %%% MCEDB / { print $4 }' "$g_mcedb_cache")
fi
# first, download the MCE.db from the excellent platomav's MCExtractor project
g_mcedb_tmp="$(mktemp -t smc-mcedb-XXXXXX)"
mcedb_url='https://github.com/platomav/MCExtractor/raw/master/MCE.db'
pr_info_nol "Fetching MCE.db from the MCExtractor project... "
download_file "$mcedb_url" "$g_mcedb_tmp" || return $?
# second, get the Intel firmwares from GitHub
g_intel_tmp="$(mktemp -d -t smc-intelfw-XXXXXX)"
intel_url="https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files/archive/main.zip"
pr_info_nol "Fetching Intel firmwares... "
## https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files.git
download_file "$intel_url" "$g_intel_tmp/fw.zip" || return $?
# now extract MCEdb contents using sqlite
pr_info_nol "Extracting MCEdb data... "
if ! command -v sqlite3 >/dev/null 2>&1; then
echo ERROR "please install the \`sqlite3\` program"
return 1
fi
mcedb_revision=$(sqlite3 "$g_mcedb_tmp" "SELECT \"revision\" from \"MCE\"")
if [ -z "$mcedb_revision" ]; then
echo ERROR "downloaded file seems invalid"
return 1
fi
sqlite3 "$g_mcedb_tmp" "ALTER TABLE \"Intel\" ADD COLUMN \"origin\" TEXT"
sqlite3 "$g_mcedb_tmp" "ALTER TABLE \"Intel\" ADD COLUMN \"pfmask\" TEXT"
sqlite3 "$g_mcedb_tmp" "ALTER TABLE \"AMD\" ADD COLUMN \"origin\" TEXT"
sqlite3 "$g_mcedb_tmp" "ALTER TABLE \"AMD\" ADD COLUMN \"pfmask\" TEXT"
sqlite3 "$g_mcedb_tmp" "UPDATE \"Intel\" SET \"origin\"='mce'"
sqlite3 "$g_mcedb_tmp" "UPDATE \"Intel\" SET \"pfmask\"='FF'"
sqlite3 "$g_mcedb_tmp" "UPDATE \"AMD\" SET \"origin\"='mce'"
sqlite3 "$g_mcedb_tmp" "UPDATE \"AMD\" SET \"pfmask\"='FF'"
echo OK "MCExtractor database revision $mcedb_revision"
# parse Intel firmwares to get their versions
pr_info_nol "Integrating Intel firmwares data to db... "
if ! command -v unzip >/dev/null 2>&1; then
echo ERROR "please install the \`unzip\` program"
return 1
fi
(cd "$g_intel_tmp" && unzip fw.zip >/dev/null)
if ! [ -d "$g_intel_tmp/Intel-Linux-Processor-Microcode-Data-Files-main/intel-ucode" ]; then
echo ERROR "expected the 'intel-ucode' folder in the downloaded zip file"
return 1
fi
if ! command -v iucode_tool >/dev/null 2>&1; then
if ! command -v iucode-tool >/dev/null 2>&1; then
echo ERROR "please install the \`iucode-tool\` program"
return 1
else
iucode_tool="iucode-tool"
fi
else
iucode_tool="iucode_tool"
fi
# 079/001: sig 0x000106c2, pf_mask 0x01, 2009-04-10, rev 0x0217, size 5120
# 078/004: sig 0x000106ca, pf_mask 0x10, 2009-08-25, rev 0x0107, size 5120
$iucode_tool -l "$g_intel_tmp/Intel-Linux-Processor-Microcode-Data-Files-main/intel-ucode" | grep -wF sig | while read -r line; do
cpuid=$(echo "$line" | grep -Eio 'sig 0x[0-9a-f]+' | awk '{print $2}')
cpuid=$((cpuid))
cpuid=$(printf "%08X" "$cpuid")
pfmask=$(echo "$line" | grep -Eio 'pf_mask 0x[0-9a-f]+' | awk '{print $2}')
pfmask=$((pfmask))
pfmask=$(printf "%02X" $pfmask)
date=$(echo "$line" | grep -Eo '(19|20)[0-9][0-9]-[01][0-9]-[0-3][0-9]' | tr -d '-')
version=$(echo "$line" | grep -Eio 'rev 0x[0-9a-f]+' | awk '{print $2}')
version=$((version))
version=$(printf "%08X" "$version")
# ensure the official Intel DB always has precedence over mcedb, even if mcedb has seen a more recent fw
sqlite3 "$g_mcedb_tmp" "DELETE FROM \"Intel\" WHERE \"origin\" != 'intel' AND \"cpuid\" = '$cpuid';"
# then insert our version
sqlite3 "$g_mcedb_tmp" "INSERT INTO \"Intel\" (\"origin\",\"cpuid\",\"pfmask\",\"version\",\"yyyymmdd\") VALUES ('intel','$cpuid','$pfmask','$version','$date');"
done
intel_timestamp=$(stat -c %Y "$g_intel_tmp/Intel-Linux-Processor-Microcode-Data-Files-main/license" 2>/dev/null || stat -f %m "$g_intel_tmp/Intel-Linux-Processor-Microcode-Data-Files-main/license" 2>/dev/null)
if [ -n "$intel_timestamp" ]; then
# use this date, it matches the last commit date
intel_latest_date=$(date -d @"$intel_timestamp" +%Y%m%d 2>/dev/null || date -r "$intel_timestamp" +%Y%m%d)
else
echo "Falling back to the latest microcode date"
intel_latest_date=$(sqlite3 "$g_mcedb_tmp" "SELECT \"yyyymmdd\" FROM \"Intel\" WHERE \"origin\"='intel' ORDER BY \"yyyymmdd\" DESC LIMIT 1;")
fi
echo DONE "(version $intel_latest_date)"
# now parse the most recent linux-firmware amd-ucode README file
pr_info_nol "Fetching latest amd-ucode README from linux-firmware project... "
linuxfw_url="https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/plain/amd-ucode/README"
g_linuxfw_tmp=$(mktemp -t smc-linuxfw-XXXXXX)
download_file "$linuxfw_url" "$g_linuxfw_tmp" || return $?
pr_info_nol "Parsing the README... "
nbfound=0
for line in $(grep -E 'Family=0x[0-9a-f]+ Model=0x[0-9a-f]+ Stepping=0x[0-9a-f]+: Patch=0x[0-9a-f]+' "$g_linuxfw_tmp" | tr " " ","); do
pr_debug "Parsing line $line"
family=$(echo "$line" | grep -Eoi 'Family=0x[0-9a-f]+' | cut -d= -f2)
model=$(echo "$line" | grep -Eoi 'Model=0x[0-9a-f]+' | cut -d= -f2)
stepping=$(echo "$line" | grep -Eoi 'Stepping=0x[0-9a-f]+' | cut -d= -f2)
version=$(echo "$line" | grep -Eoi 'Patch=0x[0-9a-f]+' | cut -d= -f2)
version=$(printf "%08X" "$((version))")
cpuid=$(fms2cpuid "$family" "$model" "$stepping")
cpuid=$(printf "%08X" "$cpuid")
sqlstm="INSERT INTO \"AMD\" (\"origin\",\"cpuid\",\"pfmask\",\"version\",\"yyyymmdd\") VALUES ('linux-firmware','$cpuid','FF','$version','20000101')"
pr_debug "family $family model $model stepping $stepping cpuid $cpuid"
pr_debug "$sqlstm"
sqlite3 "$g_mcedb_tmp" "$sqlstm"
nbfound=$((nbfound + 1))
unset family model stepping version cpuid date sqlstm
done
echo "found $nbfound microcodes"
unset nbfound
dbversion="$mcedb_revision+i$intel_latest_date"
linuxfw_hash=$(md5sum "$g_linuxfw_tmp" 2>/dev/null | cut -c1-4)
if [ -n "$linuxfw_hash" ]; then
dbversion="$dbversion+$linuxfw_hash"
fi
if [ "$1" != builtin ] && [ -n "$previous_dbversion" ] && [ "$previous_dbversion" = "v$dbversion" ]; then
echo "We already have this version locally, no update needed"
return 0
fi
pr_info_nol "Building local database... "
{
echo "# Spectre & Meltdown Checker"
echo "# %%% MCEDB v$dbversion"
# we'll use the more recent fw for Intel and AMD
sqlite3 "$g_mcedb_tmp" "SELECT '# I,0x'||\"t1\".\"cpuid\"||',0x'||\"t1\".\"pfmask\"||',0x'||MAX(\"t1\".\"version\")||','||\"t1\".\"yyyymmdd\" FROM \"Intel\" AS \"t1\" LEFT OUTER JOIN \"Intel\" AS \"t2\" ON \"t2\".\"cpuid\"=\"t1\".\"cpuid\" AND \"t2\".\"pfmask\"=\"t1\".\"pfmask\" AND \"t2\".\"yyyymmdd\" > \"t1\".\"yyyymmdd\" WHERE \"t2\".\"yyyymmdd\" IS NULL GROUP BY \"t1\".\"cpuid\",\"t1\".\"pfmask\" ORDER BY \"t1\".\"cpuid\",\"t1\".\"pfmask\" ASC;" | grep -v '^# .,0x00000000,'
sqlite3 "$g_mcedb_tmp" "SELECT '# A,0x'||\"t1\".\"cpuid\"||',0x'||\"t1\".\"pfmask\"||',0x'||MAX(\"t1\".\"version\")||','||\"t1\".\"yyyymmdd\" FROM \"AMD\" AS \"t1\" LEFT OUTER JOIN \"AMD\" AS \"t2\" ON \"t2\".\"cpuid\"=\"t1\".\"cpuid\" AND \"t2\".\"pfmask\"=\"t1\".\"pfmask\" AND \"t2\".\"yyyymmdd\" > \"t1\".\"yyyymmdd\" WHERE \"t2\".\"yyyymmdd\" IS NULL GROUP BY \"t1\".\"cpuid\",\"t1\".\"pfmask\" ORDER BY \"t1\".\"cpuid\",\"t1\".\"pfmask\" ASC;" | grep -v '^# .,0x00000000,'
} >"$g_mcedb_cache"
echo DONE "(version $dbversion)"
if [ "$1" = builtin ]; then
newfile=$(mktemp -t smc-builtin-XXXXXX)
awk '/^# %%% MCEDB / { exit }; { print }' "$0" >"$newfile"
awk '{ if (NR>1) { print } }' "$g_mcedb_cache" >>"$newfile"
cat "$newfile" >"$0"
rm -f "$newfile"
fi
}

View File

@@ -0,0 +1,363 @@
# vim: set ts=4 sw=4 sts=4 et:
# Validate a command-line option that expects a readable file path
# Args: $1=option_name $2=option_value (file path)
parse_opt_file() {
local option_name option_value
option_name="$1"
option_value="$2"
if [ -z "$option_value" ]; then
show_header
show_usage
echo "$0: error: --$option_name expects one parameter (a file)" >&2
exit 1
elif [ ! -e "$option_value" ]; then
show_header
echo "$0: error: couldn't find file $option_value" >&2
exit 1
elif [ ! -f "$option_value" ]; then
show_header
echo "$0: error: $option_value is not a file" >&2
exit 1
elif [ ! -r "$option_value" ]; then
show_header
echo "$0: error: couldn't read $option_value (are you root?)" >&2
exit 1
fi
echo "$option_value"
exit 0
}
while [ -n "${1:-}" ]; do
if [ "$1" = "--kernel" ]; then
opt_kernel=$(parse_opt_file kernel "$2")
ret=$?
[ $ret -ne 0 ] && exit 255
shift 2
elif [ "$1" = "--config" ]; then
opt_config=$(parse_opt_file config "$2")
ret=$?
[ $ret -ne 0 ] && exit 255
shift 2
elif [ "$1" = "--map" ]; then
opt_map=$(parse_opt_file map "$2")
ret=$?
[ $ret -ne 0 ] && exit 255
shift 2
elif [ "$1" = "--arch-prefix" ]; then
opt_arch_prefix="$2"
shift 2
elif [ "$1" = "--live" ]; then
# deprecated, kept for backward compatibility (live is now the default)
shift
elif [ "$1" = "--no-color" ]; then
opt_no_color=1
shift
elif [ "$1" = "--no-sysfs" ]; then
opt_no_sysfs=1
shift
elif [ "$1" = "--sysfs-only" ]; then
opt_sysfs_only=1
shift
elif [ "$1" = "--coreos" ]; then
opt_coreos=1
shift
elif [ "$1" = "--coreos-within-toolbox" ]; then
# don't use directly: used internally by --coreos
opt_coreos=0
shift
elif [ "$1" = "--paranoid" ]; then
opt_paranoid=1
shift
elif [ "$1" = "--extra" ]; then
opt_extra=1
shift
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" = "--cpu" ]; then
opt_cpu=$2
if [ "$opt_cpu" != all ]; then
if echo "$opt_cpu" | grep -Eq '^[0-9]+'; then
opt_cpu=$((opt_cpu))
else
echo "$0: error: --cpu should be an integer or 'all', got '$opt_cpu'" >&2
exit 255
fi
fi
shift 2
elif [ "$1" = "--no-explain" ]; then
# deprecated, kept for compatibility
opt_explain=0
shift
elif [ "$1" = "--update-fwdb" ] || [ "$1" = "--update-mcedb" ]; then
update_fwdb
exit $?
elif [ "$1" = "--update-builtin-fwdb" ] || [ "$1" = "--update-builtin-mcedb" ]; then
update_fwdb builtin
exit $?
elif [ "$1" = "--dump-mock-data" ]; then
opt_mock=1
shift
elif [ "$1" = "--explain" ]; then
opt_explain=1
shift
elif [ "$1" = "--batch" ]; then
opt_batch=1
opt_verbose=0
opt_no_color=1
shift
case "$1" in
text | short | nrpe | json | json-terse | prometheus)
opt_batch_format="$1"
shift
;;
--*) ;; # allow subsequent flags
'') ;; # 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
exit 255
;;
esac
elif [ "$1" = "-v" ] || [ "$1" = "--verbose" ]; then
opt_verbose=$((opt_verbose + 1))
[ "$opt_verbose" -ge 2 ] && opt_mock=1
shift
elif [ "$1" = "--cve" ]; then
if [ -z "$2" ]; then
echo "$0: error: option --cve expects a parameter, supported CVEs are: $g_supported_cve_list" >&2
exit 255
fi
selected_cve=$(echo "$g_supported_cve_list" | grep -iwo "$2")
if [ -n "$selected_cve" ]; then
opt_cve_list="$opt_cve_list $selected_cve"
opt_cve_all=0
else
echo "$0: error: unsupported CVE specified ('$2'), supported CVEs are: $g_supported_cve_list" >&2
exit 255
fi
shift 2
elif [ "$1" = "--vmm" ]; then
if [ -z "$2" ]; then
echo "$0: error: option --vmm (auto, yes, no)" >&2
exit 255
fi
case "$2" in
auto) opt_vmm=-1 ;;
yes) opt_vmm=1 ;;
no) opt_vmm=0 ;;
*)
echo "$0: error: expected one of (auto, yes, no) to option --vmm instead of '$2'" >&2
exit 255
;;
esac
shift 2
elif [ "$1" = "--variant" ]; then
if [ -z "$2" ]; then
echo "$0: error: option --variant expects a parameter (see --variant help)" >&2
exit 255
fi
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"
exit 0
;;
1)
opt_cve_list="$opt_cve_list CVE-2017-5753"
opt_cve_all=0
;;
2)
opt_cve_list="$opt_cve_list CVE-2017-5715"
opt_cve_all=0
;;
3)
opt_cve_list="$opt_cve_list CVE-2017-5754"
opt_cve_all=0
;;
3a)
opt_cve_list="$opt_cve_list CVE-2018-3640"
opt_cve_all=0
;;
4)
opt_cve_list="$opt_cve_list CVE-2018-3639"
opt_cve_all=0
;;
msbds)
opt_cve_list="$opt_cve_list CVE-2018-12126"
opt_cve_all=0
;;
mfbds)
opt_cve_list="$opt_cve_list CVE-2018-12130"
opt_cve_all=0
;;
mlpds)
opt_cve_list="$opt_cve_list CVE-2018-12127"
opt_cve_all=0
;;
mdsum)
opt_cve_list="$opt_cve_list CVE-2019-11091"
opt_cve_all=0
;;
l1tf)
opt_cve_list="$opt_cve_list CVE-2018-3615 CVE-2018-3620 CVE-2018-3646"
opt_cve_all=0
;;
taa)
opt_cve_list="$opt_cve_list CVE-2019-11135"
opt_cve_all=0
;;
mcepsc)
opt_cve_list="$opt_cve_list CVE-2018-12207"
opt_cve_all=0
;;
srbds)
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
;;
downfall)
opt_cve_list="$opt_cve_list CVE-2022-40982"
opt_cve_all=0
;;
retbleed)
opt_cve_list="$opt_cve_list CVE-2022-29900 CVE-2022-29901"
opt_cve_all=0
;;
inception)
opt_cve_list="$opt_cve_list CVE-2023-20569"
opt_cve_all=0
;;
reptar)
opt_cve_list="$opt_cve_list CVE-2023-23583"
opt_cve_all=0
;;
rfds)
opt_cve_list="$opt_cve_list CVE-2023-28746"
opt_cve_all=0
;;
tsa)
opt_cve_list="$opt_cve_list CVE-2024-36350 CVE-2024-36357"
opt_cve_all=0
;;
tsa-sq)
opt_cve_list="$opt_cve_list CVE-2024-36350"
opt_cve_all=0
;;
tsa-l1)
opt_cve_list="$opt_cve_list CVE-2024-36357"
opt_cve_all=0
;;
its)
opt_cve_list="$opt_cve_list CVE-2024-28956"
opt_cve_all=0
;;
vmscape)
opt_cve_list="$opt_cve_list CVE-2025-40300"
opt_cve_all=0
;;
bpi)
opt_cve_list="$opt_cve_list CVE-2024-45332"
opt_cve_all=0
;;
sls)
opt_cve_list="$opt_cve_list CVE-0000-0001"
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" = "-h" ] || [ "$1" = "--help" ]; then
show_header
show_usage
exit 0
elif [ "$1" = "--version" ]; then
opt_no_color=1
show_header
exit 0
elif [ "$1" = "--disclaimer" ]; then
show_header
show_disclaimer
exit 0
else
show_header
show_usage
echo "$0: error: unknown option '$1'"
exit 255
fi
done
show_header
if [ "$opt_no_sysfs" = 1 ] && [ "$opt_sysfs_only" = 1 ]; then
pr_warn "Incompatible options specified (--no-sysfs and --sysfs-only), aborting"
exit 255
fi
if [ "$opt_no_hw" = 1 ] && [ "$opt_hw_only" = 1 ]; then
pr_warn "Incompatible options specified (--no-hw and --hw-only), aborting"
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'
fi

View File

@@ -0,0 +1,21 @@
# vim: set ts=4 sw=4 sts=4 et:
# Print a colored status badge followed by an optional supplement
# Args: $1=color(red|green|yellow|blue) $2=message $3=supplement(optional)
pstatus() {
local col
if [ "$opt_no_color" = 1 ]; then
pr_info_nol "$2"
else
case "$1" in
red) col="\033[41m\033[30m" ;;
green) col="\033[42m\033[30m" ;;
yellow) col="\033[43m\033[30m" ;;
blue) col="\033[44m\033[30m" ;;
*) col="" ;;
esac
pr_info_nol "$col $2 \033[0m"
fi
[ -n "${3:-}" ] && pr_info_nol " ($3)"
pr_info
unset col
}

View File

@@ -0,0 +1,571 @@
# 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
# Args: $1=cve $2=aka $3=status $4=description
# Callers: pvulnstatus
_emit_text() {
_pr_echo 0 "$1: $3 ($4)"
}
# Append CVE ID to the space-separated short output buffer
# Args: $1=cve $2=aka $3=status $4=description
# Sets: g_short_output
# Callers: pvulnstatus
_emit_short() {
g_short_output="${g_short_output}$1 "
}
# Append a CVE result as a terse 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() {
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
exit 255
;;
esac
esc_name=$(_json_escape "$2")
esc_infos=$(_json_escape "$4")
[ -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
# 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
# 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
}
# 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
# 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"
}
# Update global state used to determine the program exit code
# Args: $1=cve $2=status(UNK|VULN|OK)
# Sets: g_unknown, g_critical
# Callers: pvulnstatus
_record_result() {
case "$2" in
UNK) g_unknown="1" ;;
VULN) g_critical="1" ;;
OK) ;;
*)
echo "$0: error: unknown status '$2' passed to _record_result()" >&2
exit 255
;;
esac
}
# Print the final vulnerability status for a CVE and dispatch to batch emitters
# Args: $1=cve $2=status(UNK|OK|VULN) $3=description
# Sets: g_pvulnstatus_last_cve
pvulnstatus() {
local aka vulnstatus
g_pvulnstatus_last_cve="$1"
if [ "$opt_batch" = 1 ]; then
aka=$(_cve_registry_field "$1" 2)
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" ;;
nrpe) _emit_nrpe "$1" "$aka" "$2" "$3" ;;
prometheus) _emit_prometheus "$1" "$aka" "$2" "$3" ;;
*)
echo "$0: error: invalid batch format '$opt_batch_format' specified" >&2
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"
# display info if we're not in quiet/batch mode
vulnstatus="$2"
shift 2
pr_info_nol "> \033[46m\033[30mSTATUS:\033[0m "
: "${g_final_summary:=}"
: "${g_final_summary_count:=0}"
g_final_summary_count=$((g_final_summary_count + 1))
# wrap to a new line every 4 entries for readability
if [ "$g_final_summary_count" -gt 1 ] && [ $((g_final_summary_count % 4)) -eq 1 ]; then
g_final_summary="$g_final_summary\n "
fi
# pad entry to fixed width so columns align despite varying CVE ID lengths
case "$vulnstatus" in
UNK)
pstatus yellow 'UNKNOWN' "$@"
_summary_label=$(printf "%-17s" "$g_pvulnstatus_last_cve:??")
g_final_summary="$g_final_summary \033[43m\033[30m$_summary_label\033[0m"
;;
VULN)
pstatus red 'VULNERABLE' "$@"
_summary_label=$(printf "%-17s" "$g_pvulnstatus_last_cve:KO")
g_final_summary="$g_final_summary \033[41m\033[30m$_summary_label\033[0m"
;;
OK)
pstatus green 'NOT VULNERABLE' "$@"
_summary_label=$(printf "%-17s" "$g_pvulnstatus_last_cve:OK")
g_final_summary="$g_final_summary \033[42m\033[30m$_summary_label\033[0m"
;;
*)
echo "$0: error: unknown status '$vulnstatus' passed to pvulnstatus()" >&2
exit 255
;;
esac
}

View File

@@ -0,0 +1,154 @@
# vim: set ts=4 sw=4 sts=4 et:
# The 3 below functions are taken from the extract-linux script, available here:
# https://github.com/torvalds/linux/blob/master/scripts/extract-vmlinux
# The functions have been modified for better integration to this script
# The original header of the file has been retained below
# ----------------------------------------------------------------------
# extract-vmlinux - Extract uncompressed vmlinux from a kernel image
#
# Inspired from extract-ikconfig
# (c) 2009,2010 Dick Streefland <dick@streefland.net>
#
# (c) 2011 Corentin Chary <corentin.chary@gmail.com>
#
# Licensed under the GNU General Public License, version 2 (GPLv2).
# ----------------------------------------------------------------------
g_kernel=''
g_kernel_err=''
# Validate whether a file looks like a valid uncompressed Linux kernel image
# Args: $1=file_path
# Sets: g_kernel, g_kernel_err
check_kernel() {
local ret file mode readelf_warnings readelf_sections kernel_size
file="$1"
mode="${2:-normal}"
# checking the return code of readelf -h is not enough, we could get
# a damaged ELF file and validate it, check for stderr warnings too
# the warning "readelf: Warning: [16]: Link field (0) should index a symtab section./" can appear on valid kernels, ignore it
readelf_warnings=$("${opt_arch_prefix}readelf" -S "$file" 2>&1 >/dev/null | grep -v 'should index a symtab section' | tr "\n" "/")
ret=$?
readelf_sections=$("${opt_arch_prefix}readelf" -S "$file" 2>/dev/null | grep -c -e data -e text -e init)
kernel_size=$(stat -c %s "$file" 2>/dev/null || stat -f %z "$file" 2>/dev/null || echo 10000)
pr_debug "check_kernel: ret=$? size=$kernel_size sections=$readelf_sections warnings=$readelf_warnings"
if [ "$mode" = desperate ]; then
if "${opt_arch_prefix}strings" "$file" | grep -Eq '^Linux version '; then
pr_debug "check_kernel (desperate): ... matched!"
if [ "$readelf_sections" = 0 ] && grep -qF -e armv6 -e armv7 "$file"; then
pr_debug "check_kernel (desperate): raw arm binary found, adjusting objdump options"
g_objdump_options="-D -b binary -marm"
else
g_objdump_options="-d"
fi
return 0
else
pr_debug "check_kernel (desperate): ... invalid"
fi
else
if [ $ret -eq 0 ] && [ -z "$readelf_warnings" ] && [ "$readelf_sections" -gt 0 ]; then
if [ "$kernel_size" -ge 100000 ]; then
pr_debug "check_kernel: ... file is valid"
g_objdump_options="-d"
return 0
else
pr_debug "check_kernel: ... file seems valid but is too small, ignoring"
fi
else
pr_debug "check_kernel: ... file is invalid"
fi
fi
return 1
}
# Attempt to find and decompress a kernel image using a given compression format
# Args: $1=magic_search $2=magic_match $3=format_name $4=decompress_cmd $5=decompress_args $6=input_file $7=output_file
try_decompress() {
local pos ret
# The obscure use of the "tr" filter is to work around older versions of
# "grep" that report the byte offset of the line instead of the pattern.
# Try to find the header ($1) and decompress from here
pr_debug "try_decompress: looking for $3 magic in $6"
for pos in $(tr "$1\n$2" "\n$2=" <"$6" | grep -abo "^$2"); do
pr_debug "try_decompress: magic for $3 found at offset $pos"
if ! command -v "$3" >/dev/null 2>&1; then
if [ "$8" = 1 ]; then
# pass1: if the tool is not installed, just bail out silently
# and hope that the next decompression tool will be, and that
# it'll happen to be the proper one for this kernel
pr_debug "try_decompress: the '$3' tool is not installed (pass 1), try the next algo"
else
# pass2: if the tool is not installed, populate g_kernel_err this time
g_kernel_err="missing '$3' tool, please install it, usually it's in the '$5' package"
pr_debug "try_decompress: $g_kernel_err"
fi
return 1
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
ret=$?
if [ ! -s "$g_kerneltmp" ]; then
# don't rely on $ret, sometimes it's != 0 but worked
# (e.g. gunzip ret=2 just means there was trailing garbage)
pr_debug "try_decompress: decompression with $3 failed (err=$ret)"
elif check_kernel "$g_kerneltmp" "$7"; then
g_kernel="$g_kerneltmp"
pr_debug "try_decompress: decompressed with $3 successfully!"
return 0
elif [ "$3" != "cat" ]; then
pr_debug "try_decompress: decompression with $3 worked but result is not a kernel, trying with an offset"
[ -z "$g_kerneltmp2" ] && g_kerneltmp2=$(mktemp -t smc-kernel-XXXXXX)
cat "$g_kerneltmp" >"$g_kerneltmp2"
try_decompress '\177ELF' xxy 'cat' '' cat "$g_kerneltmp2" && return 0
else
pr_debug "try_decompress: decompression with $3 worked but result is not a kernel"
fi
done
return 1
}
# Extract an uncompressed vmlinux from a possibly compressed kernel image
# Args: $1=kernel_image_path
# Sets: g_kerneltmp
extract_kernel() {
local pass mode
[ -n "${1:-}" ] || return 1
# Prepare temp files:
g_kerneltmp="$(mktemp -t smc-kernel-XXXXXX)"
# Initial attempt for uncompressed images or objects:
if check_kernel "$1"; then
pr_debug "extract_kernel: found kernel is valid, no decompression needed"
cat "$1" >"$g_kerneltmp"
g_kernel=$g_kerneltmp
return 0
fi
# That didn't work, so retry after decompression.
for pass in 1 2; do
for mode in normal desperate; do
pr_debug "extract_kernel: pass $pass $mode mode"
try_decompress '\037\213\010' xy gunzip '' gunzip "$1" "$mode" "$pass" && return 0
try_decompress '\002\041\114\030' xyy 'lz4' '-d -l' liblz4-tool "$1" "$mode" "$pass" && return 0
try_decompress '\3757zXZ\000' abcde unxz '' xz-utils "$1" "$mode" "$pass" && return 0
try_decompress 'BZh' xy bunzip2 '' bzip2 "$1" "$mode" "$pass" && return 0
try_decompress '\135\0\0\0' xxx unlzma '' xz-utils "$1" "$mode" "$pass" && return 0
try_decompress '\211\114\132' xy 'lzop' '-d' lzop "$1" "$mode" "$pass" && return 0
try_decompress '\177ELF' xxy 'cat' '' cat "$1" "$mode" "$pass" && return 0
try_decompress '(\265/\375' xxy unzstd '' zstd "$1" "$mode" "$pass" && return 0
done
done
# g_kernel_err might already have been populated by try_decompress() if we're missing one of the tools
if [ -z "$g_kernel_err" ]; then
g_kernel_err="kernel compression format is unknown or image is invalid"
fi
pr_verbose "Couldn't extract the kernel image ($g_kernel_err), accuracy might be reduced"
return 1
}
# end of extract-vmlinux functions

View File

@@ -0,0 +1,32 @@
# vim: set ts=4 sw=4 sts=4 et:
# Mount debugfs if not already available, remembering to unmount on cleanup
# Sets: g_mounted_debugfs
mount_debugfs() {
if [ ! -e "$DEBUGFS_BASE/sched_features" ]; then
# try to mount the debugfs hierarchy ourselves and remember it to umount afterwards
mount -t debugfs debugfs "$DEBUGFS_BASE" 2>/dev/null && g_mounted_debugfs=1
fi
}
# Load the MSR kernel module (Linux) or cpuctl (BSD) if not already loaded
# Sets: g_insmod_msr, g_kldload_cpuctl
load_msr() {
[ "${g_load_msr_once:-}" = 1 ] && return
g_load_msr_once=1
if [ "$g_os" = Linux ]; then
if ! grep -qw msr "$g_procfs/modules" 2>/dev/null; then
modprobe msr 2>/dev/null && g_insmod_msr=1
pr_debug "attempted to load module msr, g_insmod_msr=$g_insmod_msr"
else
pr_debug "msr module already loaded"
fi
else
if ! kldstat -q -m cpuctl; then
kldload cpuctl 2>/dev/null && g_kldload_cpuctl=1
pr_debug "attempted to load module cpuctl, g_kldload_cpuctl=$g_kldload_cpuctl"
else
pr_debug "cpuctl module already loaded"
fi
fi
}

177
src/libs/320_cpu_cpuid.sh Normal file
View File

@@ -0,0 +1,177 @@
# vim: set ts=4 sw=4 sts=4 et:
# Load the CPUID kernel module if not already loaded (Linux only)
# Sets: g_insmod_cpuid
load_cpuid() {
[ "${g_load_cpuid_once:-}" = 1 ] && return
g_load_cpuid_once=1
if [ "$g_os" = Linux ]; then
if ! grep -qw cpuid "$g_procfs/modules" 2>/dev/null; then
modprobe cpuid 2>/dev/null && g_insmod_cpuid=1
pr_debug "attempted to load module cpuid, g_insmod_cpuid=$g_insmod_cpuid"
else
pr_debug "cpuid module already loaded"
fi
else
if ! kldstat -q -m cpuctl; then
kldload cpuctl 2>/dev/null && g_kldload_cpuctl=1
pr_debug "attempted to load module cpuctl, g_kldload_cpuctl=$g_kldload_cpuctl"
else
pr_debug "cpuctl module already loaded"
fi
fi
}
# shellcheck disable=SC2034
readonly EAX=1
readonly EBX=2
readonly ECX=3
readonly EDX=4
readonly READ_CPUID_RET_OK=0
readonly READ_CPUID_RET_KO=1
readonly READ_CPUID_RET_ERR=2
# Read a CPUID register value across one or all cores
# Args: $1=leaf $2=subleaf $3=register(EAX|EBX|ECX|EDX) $4=shift $5=bit_width $6=expected_value
# Sets: ret_read_cpuid_value, ret_read_cpuid_msg
# Returns: READ_CPUID_RET_OK | READ_CPUID_RET_KO | READ_CPUID_RET_ERR
read_cpuid() {
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_cpuid_one_core "$opt_cpu" "$@"
return $?
fi
# otherwise we must read all cores
for core in $(seq 0 "$g_max_core_id"); do
read_cpuid_one_core "$core" "$@"
ret=$?
if [ "$core" = 0 ]; then
# save the result of the first core, for comparison with the others
first_core_ret=$ret
first_core_value=$ret_read_cpuid_value
else
# compare first core with the other ones
if [ "$first_core_ret" != "$ret" ] || [ "$first_core_value" != "$ret_read_cpuid_value" ]; then
ret_read_cpuid_msg="result is not homogeneous between all cores, at least core 0 and $core differ!"
return $READ_CPUID_RET_ERR
fi
fi
done
# if we're here, all cores agree, return the result
return "$ret"
}
# Read a CPUID register value from a single CPU core
# Args: $1=core $2=leaf $3=subleaf $4=register(EAX|EBX|ECX|EDX) $5=shift $6=bit_width $7=expected_value
# Sets: ret_read_cpuid_value, ret_read_cpuid_msg
# Returns: READ_CPUID_RET_OK | READ_CPUID_RET_KO | READ_CPUID_RET_ERR
read_cpuid_one_core() {
local core leaf subleaf register shift mask wanted position ddskip odskip cpuid mockvarname reg reg_shifted
# on which core to send the CPUID instruction
core="$1"
# leaf is the value of the eax register when calling the cpuid instruction:
leaf="$2"
# subleaf is the value of the ecx register when calling the cpuid instruction:
subleaf="$3"
# eax=1 ebx=2 ecx=3 edx=4:
register="$4"
# number of bits to shift the register right to, 0-31:
shift="$5"
# mask to apply as an AND operand to the shifted register value
mask="$6"
# wanted value (optional), if present we return 0(true) if the obtained value is equal, 1 otherwise:
wanted="${7:-}"
# in any case, the read value is globally available in $ret_read_cpuid_value
ret_read_cpuid_value=''
ret_read_cpuid_msg='unknown error'
if [ $# -lt 6 ]; then
ret_read_cpuid_msg="read_cpuid: missing arguments, got only $#, expected at least 6: $*"
return $READ_CPUID_RET_ERR
fi
if [ "$register" -gt 4 ]; then
ret_read_cpuid_msg="read_cpuid: register must be 0-4, got $register"
return $READ_CPUID_RET_ERR
fi
if [ "$shift" -gt 32 ]; then
ret_read_cpuid_msg="read_cpuid: shift must be 0-31, got $shift"
return $READ_CPUID_RET_ERR
fi
if [ ! -e $CPU_DEV_BASE/0/cpuid ] && [ ! -e ${BSD_CPUCTL_DEV_BASE}0 ]; then
# try to load the module ourselves (and remember it so we can rmmod it afterwards)
load_cpuid
fi
if [ -e $CPU_DEV_BASE/0/cpuid ]; then
# Linux
if [ ! -r $CPU_DEV_BASE/0/cpuid ]; then
ret_read_cpuid_msg="Couldn't load cpuid module"
return $READ_CPUID_RET_ERR
fi
# on some kernel versions, $CPU_DEV_BASE/0/cpuid doesn't imply that the cpuid module is loaded, in that case dd returns an error,
# we use that fact to load the module if dd returns an error
if ! dd if=$CPU_DEV_BASE/0/cpuid bs=16 count=1 >/dev/null 2>&1; then
load_cpuid
fi
# we need leaf to be converted to decimal for dd
leaf=$((leaf))
subleaf=$((subleaf))
position=$((leaf + (subleaf << 32)))
# to avoid using iflag=skip_bytes, which doesn't exist on old versions of dd, seek to the closer multiple-of-16
ddskip=$((position / 16))
odskip=$((position - ddskip * 16))
# now read the value
cpuid=$(dd if="$CPU_DEV_BASE/$core/cpuid" bs=16 skip=$ddskip count=$((odskip + 1)) 2>/dev/null | od -j $((odskip * 16)) -A n -t u4)
elif [ -e ${BSD_CPUCTL_DEV_BASE}0 ]; then
# BSD
if [ ! -r ${BSD_CPUCTL_DEV_BASE}0 ]; then
ret_read_cpuid_msg="Couldn't read cpuid info from cpuctl"
return $READ_CPUID_RET_ERR
fi
cpuid=$(cpucontrol -i "$leaf","$subleaf" "${BSD_CPUCTL_DEV_BASE}$core" 2>/dev/null | cut -d: -f2-)
# cpuid level 0x4, level_type 0x2: 0x1c004143 0x01c0003f 0x000001ff 0x00000000
else
ret_read_cpuid_msg="Found no way to read cpuid info"
return $READ_CPUID_RET_ERR
fi
pr_debug "cpuid: leaf$leaf subleaf$subleaf on cpu$core, eax-ebx-ecx-edx: $cpuid"
mockvarname="SMC_MOCK_CPUID_${leaf}_${subleaf}"
# shellcheck disable=SC1083
if [ -n "$(eval echo \${"$mockvarname":-})" ]; then
cpuid="$(eval echo \$"$mockvarname")"
pr_debug "read_cpuid: MOCKING enabled for leaf $leaf subleaf $subleaf, will return $cpuid"
g_mocked=1
else
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_CPUID_${leaf}_${subleaf}='$cpuid'")
fi
if [ -z "$cpuid" ]; then
ret_read_cpuid_msg="Failed to get cpuid data"
return $READ_CPUID_RET_ERR
fi
# get the value of the register we want
reg=$(echo "$cpuid" | awk '{print $'"$register"'}')
# Linux returns it as decimal, BSD as hex, normalize to decimal
reg=$((reg))
# shellcheck disable=SC2046
pr_debug "cpuid: wanted register ($register) has value $reg aka "$(printf "%08x" "$reg")
reg_shifted=$((reg >> shift))
# shellcheck disable=SC2046
pr_debug "cpuid: shifted value by $shift is $reg_shifted aka "$(printf "%x" "$reg_shifted")
ret_read_cpuid_value=$((reg_shifted & mask))
# shellcheck disable=SC2046
pr_debug "cpuid: after AND $mask, final value is $ret_read_cpuid_value aka "$(printf "%x" "$ret_read_cpuid_value")
if [ -n "$wanted" ]; then
pr_debug "cpuid: wanted $wanted and got $ret_read_cpuid_value"
if [ "$ret_read_cpuid_value" = "$wanted" ]; then
return $READ_CPUID_RET_OK
else
return $READ_CPUID_RET_KO
fi
fi
return $READ_CPUID_RET_OK
}

24
src/libs/330_cpu_misc.sh Normal file
View File

@@ -0,0 +1,24 @@
# vim: set ts=4 sw=4 sts=4 et:
# Search dmesg for a pattern, returning nothing if the buffer has been truncated
# Args: $1=grep_pattern
# Sets: ret_dmesg_grep_grepped
# Returns: 0=found, 1=not found, 2=dmesg truncated
dmesg_grep() {
ret_dmesg_grep_grepped=''
if ! dmesg 2>/dev/null | grep -qE -e '(^|\] )Linux version [0-9]' -e '^FreeBSD is a registered'; then
# dmesg truncated
return 2
fi
ret_dmesg_grep_grepped=$(dmesg 2>/dev/null | grep -E "$1" | head -n1)
# not found:
[ -z "$ret_dmesg_grep_grepped" ] && return 1
# found, output is in $ret_dmesg_grep_grepped
return 0
}
# Check whether the system is running CoreOS/Flatcar
# Returns: 0 if CoreOS, 1 otherwise
is_coreos() {
command -v coreos-install >/dev/null 2>&1 && command -v toolbox >/dev/null 2>&1 && return 0
return 1
}

351
src/libs/340_cpu_msr.sh Normal file
View File

@@ -0,0 +1,351 @@
# vim: set ts=4 sw=4 sts=4 et:
readonly WRITE_MSR_RET_OK=0
readonly WRITE_MSR_RET_KO=1
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)
# 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")
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
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
else
# 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
done
# if we're here, all cores agree, return the result
return $ret
}
# Write a value to an MSR register on a single CPU core
# Args: $1=core $2=msr_address $3=value
# Sets: ret_write_msr_msg
# Returns: WRITE_MSR_RET_OK | WRITE_MSR_RET_KO | WRITE_MSR_RET_ERR | WRITE_MSR_RET_LOCKDOWN
write_msr_one_core() {
local ret core msr msr_dec value value_dec mockvarname write_denied
core="$1"
msr_dec=$(($2))
msr=$(printf "0x%x" "$msr_dec")
value_dec=$((${3:-0}))
value=$(printf "0x%x" "$value_dec")
ret_write_msr_msg='unknown error'
: "${g_msr_locked_down:=0}"
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"
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
fi
if [ ! -e $CPU_DEV_BASE/0/msr ] && [ ! -e ${BSD_CPUCTL_DEV_BASE}0 ]; then
# try to load the module ourselves (and remember it so we can rmmod it afterwards)
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"
return $WRITE_MSR_RET_ERR
fi
write_denied=0
if [ "$g_os" != Linux ]; then
cpucontrol -m "$msr=$value" "${BSD_CPUCTL_DEV_BASE}$core" >/dev/null 2>&1
ret=$?
else
# for Linux
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
ret=$?
# ret=4: msr doesn't exist, ret=127: msr.allow_writes=off
[ "$ret" = 127 ] && write_denied=1
# or fallback to dd if it supports seek_bytes, we prefer it over perl because we can tell the difference between EPERM and EIO
elif dd if=/dev/null of=/dev/null bs=8 count=1 seek="$msr_dec" oflag=seek_bytes 2>/dev/null && [ "${SMC_NO_DD:-}" != 1 ]; then
pr_debug "write_msr: using dd"
awk "BEGIN{printf \"%c\", $value_dec}" | dd of=$CPU_DEV_BASE/"$core"/msr bs=8 count=1 seek="$msr_dec" oflag=seek_bytes 2>/dev/null
ret=$?
# if it failed, inspect stderrto look for EPERM
if [ "$ret" != 0 ]; then
if awk "BEGIN{printf \"%c\", $value_dec}" | dd of=$CPU_DEV_BASE/"$core"/msr bs=8 count=1 seek="$msr_dec" oflag=seek_bytes 2>&1 | grep -qF 'Operation not permitted'; then
write_denied=1
fi
fi
# or if we have perl, use it, any 5.x version will work
elif command -v perl >/dev/null 2>&1 && [ "${SMC_NO_PERL:-}" != 1 ]; then
pr_debug "write_msr: using perl"
ret=1
perl -e "open(M,'>','$CPU_DEV_BASE/$core/msr') and seek(M,$msr_dec,0) and exit(syswrite(M,pack(v4,$value_dec)))"
[ $? -eq 8 ] && ret=0
else
pr_debug "write_msr: got no wrmsr, perl or recent enough dd!"
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_WRMSR_${msr}_RET=$WRITE_MSR_RET_ERR")
ret_write_msr_msg="missing tool, install either msr-tools or perl"
return $WRITE_MSR_RET_ERR
fi
if [ "$ret" != 0 ]; then
# * Fedora (and probably Red Hat) have a "kernel lock down" feature that prevents us to write to MSRs
# when this mode is enabled and EFI secure boot is enabled (see issue #303)
# https://src.fedoraproject.org/rpms/kernel/blob/master/f/efi-lockdown.patch
# when this happens, any write will fail and dmesg will have a msg printed "msr: Direct access to MSR"
# * A version of this patch also made it to vanilla in 5.4+, in that case the message is: 'raw MSR access is restricted'
# * we don't use dmesg_grep() because we don't care if dmesg is truncated here, as the message has just been printed
# yet more recent versions of the msr module can be set to msr.allow_writes=off, in which case no dmesg message is printed,
# but the write fails
if [ "$write_denied" = 1 ]; then
pr_debug "write_msr: writing to msr has been denied"
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 configured to deny writes to MSRs from user space"
return $WRITE_MSR_RET_LOCKDOWN
elif dmesg 2>/dev/null | grep -qF "msr: Direct access to MSR"; then
pr_debug "write_msr: locked down kernel detected (Red Hat / Fedora)"
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 (Fedora/Red Hat), please reboot without secure boot and retry"
return $WRITE_MSR_RET_LOCKDOWN
elif dmesg 2>/dev/null | grep -qF "raw MSR access is restricted"; then
pr_debug "write_msr: locked down kernel detected (vanilla)"
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
unset write_denied
fi
fi
# normalize ret
if [ "$ret" = 0 ]; then
ret=$WRITE_MSR_RET_OK
else
ret=$WRITE_MSR_RET_KO
fi
pr_debug "write_msr: for cpu $core on msr $msr, value=$value, ret=$ret"
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_WRMSR_${msr}_RET=$ret")
return $ret
}
readonly MSR_IA32_PLATFORM_ID=0x17
readonly MSR_IA32_SPEC_CTRL=0x48
readonly MSR_IA32_ARCH_CAPABILITIES=0x10a
readonly MSR_IA32_TSX_FORCE_ABORT=0x10f
readonly MSR_IA32_TSX_CTRL=0x122
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
read_msr() {
local ret core first_core_ret first_core_value msr_dec msr
msr_dec=$(($1))
msr=$(printf "0x%x" "$msr_dec")
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
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
first_core_value=$ret_read_msr_value
else
# 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
done
# if we're here, all cores agree, return the result
return "$ret"
}
# 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
read_msr_one_core() {
local ret core msr msr_dec mockvarname msr_h msr_l mockval
core="$1"
msr_dec=$(($2))
msr=$(printf "0x%x" "$msr_dec")
ret_read_msr_value=''
ret_read_msr_value_hi=''
ret_read_msr_value_lo=''
ret_read_msr_msg='unknown error'
mockvarname="SMC_MOCK_RDMSR_${msr}"
# shellcheck disable=SC2086,SC1083
if [ -n "$(eval echo \${$mockvarname:-})" ]; then
mockval="$(eval echo \$$mockvarname)"
# accept both legacy decimal (small values) and new 16-char hex format
if [ "${#mockval}" -eq 16 ]; then
ret_read_msr_value="$mockval"
else
ret_read_msr_value=$(printf '%016x' "$mockval")
fi
ret_read_msr_value_hi=$((0x${ret_read_msr_value%????????}))
ret_read_msr_value_lo=$((0x${ret_read_msr_value#????????}))
pr_debug "read_msr: MOCKING enabled for msr $msr, returning $ret_read_msr_value"
g_mocked=1
return $READ_MSR_RET_OK
fi
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"
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
fi
if [ ! -e $CPU_DEV_BASE/0/msr ] && [ ! -e ${BSD_CPUCTL_DEV_BASE}0 ]; then
# try to load the module ourselves (and remember it so we can rmmod it afterwards)
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"
return $READ_MSR_RET_ERR
fi
if [ "$g_os" != Linux ]; then
# for BSD
msr=$(cpucontrol -m "$msr" "${BSD_CPUCTL_DEV_BASE}$core" 2>/dev/null)
ret=$?
if [ $ret -ne 0 ]; then
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_RDMSR_${msr}_RET=$READ_MSR_RET_KO")
return $READ_MSR_RET_KO
fi
# MSR 0x10: 0x000003e1 0xb106dded
msr_h=$(echo "$msr" | awk '{print $3}')
msr_l=$(echo "$msr" | awk '{print $4}')
ret_read_msr_value=$(printf '%08x%08x' "$((msr_h))" "$((msr_l))")
else
# for Linux
if [ ! -r $CPU_DEV_BASE/"$core"/msr ]; then
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_RDMSR_${msr}_RET=$READ_MSR_RET_ERR")
ret_read_msr_msg="No read permission for $CPU_DEV_BASE/$core/msr"
return $READ_MSR_RET_ERR
# if rdmsr is available, use it
elif command -v rdmsr >/dev/null 2>&1 && [ "${SMC_NO_RDMSR:-}" != 1 ]; then
pr_debug "read_msr: using rdmsr on $msr"
ret_read_msr_value=$(rdmsr -r $msr_dec 2>/dev/null | od -A n -t x8)
# or if we have perl, use it, any 5.x version will work
elif command -v perl >/dev/null 2>&1 && [ "${SMC_NO_PERL:-}" != 1 ]; then
pr_debug "read_msr: using perl on $msr"
ret_read_msr_value=$(perl -e "open(M,'<','$CPU_DEV_BASE/$core/msr') and seek(M,$msr_dec,0) and read(M,\$_,8) and print" | od -A n -t x8)
# fallback to dd if it supports skip_bytes
elif dd if=/dev/null of=/dev/null bs=8 count=1 skip="$msr_dec" iflag=skip_bytes 2>/dev/null; then
pr_debug "read_msr: using dd on $msr"
ret_read_msr_value=$(dd if=$CPU_DEV_BASE/"$core"/msr bs=8 count=1 skip="$msr_dec" iflag=skip_bytes 2>/dev/null | od -A n -t x8)
else
pr_debug "read_msr: got no rdmsr, perl or recent enough dd!"
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_RDMSR_${msr}_RET=$READ_MSR_RET_ERR")
ret_read_msr_msg='missing tool, install either msr-tools or perl'
return $READ_MSR_RET_ERR
fi
if [ -z "$ret_read_msr_value" ]; then
# MSR doesn't exist, don't check for $? because some versions of dd still return 0!
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_RDMSR_${msr}_RET=$READ_MSR_RET_KO")
return $READ_MSR_RET_KO
fi
# remove sparse spaces od might give us
ret_read_msr_value=$(printf '%s' "$ret_read_msr_value" | tr -d ' \t\n' | tr '[:upper:]' '[:lower:]')
fi
ret_read_msr_value_hi=$((0x${ret_read_msr_value%????????}))
ret_read_msr_value_lo=$((0x${ret_read_msr_value#????????}))
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_RDMSR_${msr}='$ret_read_msr_value'")
pr_debug "read_msr: MSR=$msr value is $ret_read_msr_value"
return $READ_MSR_RET_OK
}

198
src/libs/350_cpu_detect2.sh Normal file
View File

@@ -0,0 +1,198 @@
# vim: set ts=4 sw=4 sts=4 et:
# Detect and cache CPU vendor, family, model, stepping, microcode, and arch capabilities
# Sets: cpu_vendor, cpu_family, cpu_model, cpu_stepping, cpu_cpuid, cpu_ucode, cpu_friendly_name, g_max_core_id, and many cap_* globals
parse_cpu_details() {
[ "${g_parse_cpu_details_done:-}" = 1 ] && return 0
local number_of_cores arch part ret
if command -v nproc >/dev/null; then
number_of_cores=$(nproc)
elif echo "$g_os" | grep -q BSD; then
number_of_cores=$(sysctl -n hw.ncpu 2>/dev/null || echo 1)
elif [ -e "$g_procfs/cpuinfo" ]; then
number_of_cores=$(grep -c ^processor "$g_procfs/cpuinfo" 2>/dev/null || echo 1)
else
# if we don't know, default to 1 CPU
number_of_cores=1
fi
g_max_core_id=$((number_of_cores - 1))
cap_avx2=0
cap_avx512=0
if [ -e "$g_procfs/cpuinfo" ]; then
if grep -qw avx2 "$g_procfs/cpuinfo" 2>/dev/null; then cap_avx2=1; fi
if grep -qw avx512 "$g_procfs/cpuinfo" 2>/dev/null; then cap_avx512=1; fi
cpu_vendor=$(grep '^vendor_id' "$g_procfs/cpuinfo" | awk '{print $3}' | head -n1)
cpu_friendly_name=$(grep '^model name' "$g_procfs/cpuinfo" | cut -d: -f2- | head -n1 | sed -e 's/^ *//')
# 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 }')
# shellcheck disable=SC2086
part=$(echo $cpu_part_list | awk '{ print $1 }')
[ "$arch" = "AArch64" ] && arch=8
cpu_friendly_name="ARM"
[ -n "$arch" ] && cpu_friendly_name="$cpu_friendly_name v$arch"
[ -n "$part" ] && cpu_friendly_name="$cpu_friendly_name model $part"
elif grep -qi 'CPU implementer[[:space:]]*:[[:space:]]*0x43' "$g_procfs/cpuinfo"; then
cpu_vendor='CAVIUM'
elif grep -qi 'CPU implementer[[:space:]]*:[[:space:]]*0x70' "$g_procfs/cpuinfo"; then
cpu_vendor='PHYTIUM'
fi
cpu_family=$(grep '^cpu family' "$g_procfs/cpuinfo" | awk '{print $4}' | grep -E '^[0-9]+$' | head -n1)
cpu_model=$(grep '^model' "$g_procfs/cpuinfo" | awk '{print $3}' | grep -E '^[0-9]+$' | head -n1)
cpu_stepping=$(grep '^stepping' "$g_procfs/cpuinfo" | awk '{print $3}' | grep -E '^[0-9]+$' | head -n1)
cpu_ucode=$(grep '^microcode' "$g_procfs/cpuinfo" | awk '{print $3}' | head -n1)
else
cpu_vendor=$(dmesg 2>/dev/null | grep -i -m1 'Origin=' | awk '{print $2}' | cut -f2 -d= | cut -f2 -d\")
cpu_family=$(dmesg 2>/dev/null | grep -i -m1 'Family=' | awk '{print $4}' | cut -f2 -d=)
cpu_family=$((cpu_family))
cpu_model=$(dmesg 2>/dev/null | grep -i -m1 'Model=' | awk '{print $5}' | cut -f2 -d=)
cpu_model=$((cpu_model))
cpu_stepping=$(dmesg 2>/dev/null | grep -i -m1 'Stepping=' | awk '{print $6}' | cut -f2 -d=)
cpu_friendly_name=$(sysctl -n hw.model 2>/dev/null)
fi
# Intel processors have a 3bit Platform ID field in MSR(17H) that specifies the platform type for up to 8 types
# 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=$?
if [ $ret = $READ_MSR_RET_OK ]; then
# platform ID (bits 52:50) = bits 18:20 of the upper 32-bit word
cpu_platformid=$((1 << ((ret_read_msr_value_hi >> 18) & 7)))
fi
fi
if [ -n "${SMC_MOCK_CPU_FRIENDLY_NAME:-}" ]; then
cpu_friendly_name="$SMC_MOCK_CPU_FRIENDLY_NAME"
pr_debug "parse_cpu_details: MOCKING cpu friendly name to $cpu_friendly_name"
g_mocked=1
else
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_CPU_FRIENDLY_NAME='$cpu_friendly_name'")
fi
if [ -n "${SMC_MOCK_CPU_VENDOR:-}" ]; then
cpu_vendor="$SMC_MOCK_CPU_VENDOR"
pr_debug "parse_cpu_details: MOCKING cpu vendor to $cpu_vendor"
g_mocked=1
else
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_CPU_VENDOR='$cpu_vendor'")
fi
if [ -n "${SMC_MOCK_CPU_FAMILY:-}" ]; then
cpu_family="$SMC_MOCK_CPU_FAMILY"
pr_debug "parse_cpu_details: MOCKING cpu family to $cpu_family"
g_mocked=1
else
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_CPU_FAMILY='$cpu_family'")
fi
if [ -n "${SMC_MOCK_CPU_MODEL:-}" ]; then
cpu_model="$SMC_MOCK_CPU_MODEL"
pr_debug "parse_cpu_details: MOCKING cpu model to $cpu_model"
g_mocked=1
else
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_CPU_MODEL='$cpu_model'")
fi
if [ -n "${SMC_MOCK_CPU_STEPPING:-}" ]; then
cpu_stepping="$SMC_MOCK_CPU_STEPPING"
pr_debug "parse_cpu_details: MOCKING cpu stepping to $cpu_stepping"
g_mocked=1
else
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_CPU_STEPPING='$cpu_stepping'")
fi
if [ -n "${SMC_MOCK_CPU_PLATFORMID:-}" ]; then
cpu_platformid="$SMC_MOCK_CPU_PLATFORMID"
pr_debug "parse_cpu_details: MOCKING cpu platformid name to $cpu_platformid"
g_mocked=1
else
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"
else
# try to build it by ourselves
pr_debug "parse_cpu_details: build the CPUID by ourselves"
cpu_cpuid=$(fms2cpuid "$cpu_family" "$cpu_model" "$cpu_stepping")
fi
# under BSD, linprocfs often doesn't export ucode information, so fetch it ourselves the good old way
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
# 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
# Intel: write 0 to IA32_BIOS_SIGN_ID, execute CPUID, then read back
cpucontrol -m 0x8b=0 ${BSD_CPUCTL_DEV_BASE}0 2>/dev/null
cpucontrol -i 1 ${BSD_CPUCTL_DEV_BASE}0 >/dev/null 2>&1
cpu_ucode=$(cpucontrol -m 0x8b ${BSD_CPUCTL_DEV_BASE}0 2>/dev/null | awk '{print $3}')
fi
if [ -n "$cpu_ucode" ]; then
# convert to decimal then back to hex
cpu_ucode=$((cpu_ucode))
cpu_ucode=$(printf "0x%x" "$cpu_ucode")
fi
fi
fi
# if we got no cpu_ucode (e.g. we're in a vm), leave it empty
# so that we can detect this case and avoid false positives
# on non-x86 systems (e.g. ARM), these fields may not exist in cpuinfo, fall back to 0
: "${cpu_family:=0}"
: "${cpu_model:=0}"
: "${cpu_stepping:=0}"
if [ -n "${SMC_MOCK_CPU_UCODE:-}" ]; then
cpu_ucode="$SMC_MOCK_CPU_UCODE"
pr_debug "parse_cpu_details: MOCKING cpu ucode to $cpu_ucode"
g_mocked=1
else
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_parse_cpu_details_done=1
}
# Check whether the CPU vendor is Hygon
# Returns: 0 if Hygon, 1 otherwise

246
src/libs/360_cpu_smt.sh Normal file
View File

@@ -0,0 +1,246 @@
# vim: set ts=4 sw=4 sts=4 et:
is_hygon() {
parse_cpu_details
[ "$cpu_vendor" = HygonGenuine ] && return 0
return 1
}
# Check whether the CPU vendor is AMD
# Returns: 0 if AMD, 1 otherwise
is_amd() {
parse_cpu_details
[ "$cpu_vendor" = AuthenticAMD ] && return 0
return 1
}
# Check whether the CPU vendor is Intel
# Returns: 0 if Intel, 1 otherwise
is_intel() {
parse_cpu_details
[ "$cpu_vendor" = GenuineIntel ] && return 0
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() {
local siblings cpucores
# SMT / HyperThreading is enabled if siblings != cpucores
if [ -e "$g_procfs/cpuinfo" ]; then
siblings=$(awk '/^siblings/ {print $3;exit}' "$g_procfs/cpuinfo")
cpucores=$(awk '/^cpu cores/ {print $4;exit}' "$g_procfs/cpuinfo")
if [ -n "$siblings" ] && [ -n "$cpucores" ]; then
if [ "$siblings" = "$cpucores" ]; then
return 1
else
return 0
fi
fi
fi
# we can't tell
return 2
}
# Check whether the current CPU microcode version is on Intel's blacklist
# Returns: 0 if blacklisted, 1 otherwise
is_ucode_blacklisted() {
local tuple model stepping ucode cpuid
parse_cpu_details
# if it's not an Intel, don't bother: it's not blacklisted
is_intel || return 1
# it also needs to be family=6
[ "$cpu_family" = 6 ] || return 1
# now, check each known bad microcode
# source: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/cpu/intel.c#n105
# 2018-02-08 update: https://newsroom.intel.com/wp-content/uploads/sites/11/2018/02/microcode-update-guidance.pdf
# model,stepping,microcode
for tuple in \
$INTEL_FAM6_KABYLAKE,0x0B,0x80 \
$INTEL_FAM6_KABYLAKE,0x0A,0x80 \
$INTEL_FAM6_KABYLAKE,0x09,0x80 \
$INTEL_FAM6_KABYLAKE_L,0x0A,0x80 \
$INTEL_FAM6_KABYLAKE_L,0x09,0x80 \
$INTEL_FAM6_SKYLAKE_X,0x03,0x0100013e \
$INTEL_FAM6_SKYLAKE_X,0x04,0x02000036 \
$INTEL_FAM6_SKYLAKE_X,0x04,0x0200003a \
$INTEL_FAM6_SKYLAKE_X,0x04,0x0200003c \
$INTEL_FAM6_BROADWELL,0x04,0x28 \
$INTEL_FAM6_BROADWELL_G,0x01,0x1b \
$INTEL_FAM6_BROADWELL_D,0x02,0x14 \
$INTEL_FAM6_BROADWELL_D,0x03,0x07000011 \
$INTEL_FAM6_BROADWELL_X,0x01,0x0b000025 \
$INTEL_FAM6_HASWELL_L,0x01,0x21 \
$INTEL_FAM6_HASWELL_G,0x01,0x18 \
$INTEL_FAM6_HASWELL,0x03,0x23 \
$INTEL_FAM6_HASWELL_X,0x02,0x3b \
$INTEL_FAM6_HASWELL_X,0x04,0x10 \
$INTEL_FAM6_IVYBRIDGE_X,0x04,0x42a \
$INTEL_FAM6_SANDYBRIDGE_X,0x06,0x61b \
$INTEL_FAM6_SANDYBRIDGE_X,0x07,0x712; do
model=$(echo "$tuple" | cut -d, -f1)
stepping=$(($(echo "$tuple" | cut -d, -f2)))
if [ "$cpu_model" = "$model" ] && [ "$cpu_stepping" = "$stepping" ]; then
ucode=$(($(echo "$tuple" | cut -d, -f3)))
if [ "$cpu_ucode" = "$ucode" ]; then
pr_debug "is_ucode_blacklisted: we have a match! ($cpu_model/$cpu_stepping/$cpu_ucode)"
return 0
fi
fi
done
# 2024-01-09 update: https://github.com/speed47/spectre-meltdown-checker/issues/475
# this time the tuple is cpuid,microcode
for tuple in \
0xB0671,0x119 \
0xB06A2,0x4119 \
0xB06A3,0x4119; do
cpuid=$(($(echo "$tuple" | cut -d, -f1)))
ucode=$(($(echo "$tuple" | cut -d, -f2)))
if [ "$cpu_cpuid" = "$cpuid" ] && [ "$cpu_ucode" = "$ucode" ]; then
pr_debug "is_ucode_blacklisted: we have a match! ($cpuid/$ucode)"
return 0
fi
done
pr_debug "is_ucode_blacklisted: no ($cpu_model/$cpu_stepping/$cpu_ucode)"
return 1
}
# Check whether the CPU is a Skylake/Kabylake family processor
# Returns: 0 if Skylake-family, 1 otherwise
is_skylake_cpu() {
# return 0 if yes, 1 otherwise
#if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
# boot_cpu_data.x86 == 6) {
# switch (boot_cpu_data.x86_model) {
# case INTEL_FAM6_SKYLAKE_MOBILE:
# case INTEL_FAM6_SKYLAKE_DESKTOP:
# case INTEL_FAM6_SKYLAKE_X:
# case INTEL_FAM6_KABYLAKE_MOBILE:
# case INTEL_FAM6_KABYLAKE_DESKTOP:
# return true;
parse_cpu_details
is_intel || return 1
[ "$cpu_family" = 6 ] || return 1
if [ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE" ] ||
[ "$cpu_model" = "$INTEL_FAM6_SKYLAKE_X" ] ||
[ "$cpu_model" = "$INTEL_FAM6_KABYLAKE_L" ] ||
[ "$cpu_model" = "$INTEL_FAM6_KABYLAKE" ]; then
return 0
fi
return 1
}
# Check whether the CPU is vulnerable to empty RSB speculation
# Returns: 0 if vulnerable, 1 otherwise
is_vulnerable_to_empty_rsb() {
if is_intel && [ -z "$cap_rsba" ]; then
pr_warn "is_vulnerable_to_empty_rsb() called before ARCH CAPABILITIES MSR was read"
fi
if is_skylake_cpu || [ "$cap_rsba" = 1 ]; then
return 0
fi
return 1
}
# Check whether the CPU is from the AMD Zen family (Ryzen, EPYC, ...)
# Returns: 0 if Zen, 1 otherwise
is_zen_cpu() {
parse_cpu_details
is_amd || return 1
[ "$cpu_family" = 23 ] && return 0
return 1
}
# Check whether the CPU is a Hygon Moksha (Dhyana) family processor
# Returns: 0 if Moksha, 1 otherwise
is_moksha_cpu() {
parse_cpu_details
is_hygon || return 1
[ "$cpu_family" = 24 ] && return 0
return 1
}
# Encode an AMD family/model/stepping range into a single integer (mimics Linux AMD_MODEL_RANGE macro)
# Args: $1=family $2=model_start $3=stepping_start $4=model_end $5=stepping_end
amd_model_range() {
echo $((($1 << 24) | ($2 << 16) | ($3 << 12) | ($4 << 4) | ($5)))
}
# Check if the current AMD CPU falls within a given model/stepping range (mimics Linux amd_legacy_erratum)
# Args: $1=range (output of amd_model_range)
# Returns: 0 if CPU is in range, 1 otherwise
amd_legacy_erratum() {
local range ms
range="$1"
ms=$((cpu_model << 4 | cpu_stepping))
if [ "$cpu_family" = $((((range) >> 24) & 0xff)) ] &&
[ $ms -ge $((((range) >> 12) & 0xfff)) ] &&
[ $ms -le $(((range) & 0xfff)) ]; then
return 0
fi
return 1
}
# Check whether the CPU has a microcode version that fixes Zenbleed
# Sets: g_zenbleed_fw, g_zenbleed_fw_required
# Returns: 0=fixed, 1=not fixed, 2=not applicable
has_zenbleed_fixed_firmware() {
local tuples tuple model_low model_high fwver
# return cached data
[ -n "$g_zenbleed_fw" ] && return "$g_zenbleed_fw"
# or compute it:
g_zenbleed_fw=2 # unknown
# only amd
if ! is_amd; then
g_zenbleed_fw=1
return $g_zenbleed_fw
fi
# list of known fixed firmwares, from commit 522b1d69219d8f083173819fde04f994aa051a98
tuples="
0x30,0x3f,0x0830107a
0x60,0x67,0x0860010b
0x68,0x6f,0x08608105
0x70,0x7f,0x08701032
0xa0,0xaf,0x08a00008
"
for tuple in $tuples; do
model_low=$(echo "$tuple" | cut -d, -f1)
model_high=$(echo "$tuple" | cut -d, -f2)
fwver=$(echo "$tuple" | cut -d, -f3)
if [ $((cpu_model)) -ge $((model_low)) ] && [ $((cpu_model)) -le $((model_high)) ]; then
if [ -n "$cpu_ucode" ] && [ $((cpu_ucode)) -ge $((fwver)) ]; then
g_zenbleed_fw=0 # true
break
else
g_zenbleed_fw=1 # false
g_zenbleed_fw_required=$fwver
fi
fi
done
unset tuples
return $g_zenbleed_fw
}

120
src/libs/365_kernel_arch.sh Normal file
View File

@@ -0,0 +1,120 @@
# 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'
}

57
src/libs/370_hw_vmm.sh Normal file
View File

@@ -0,0 +1,57 @@
# vim: set ts=4 sw=4 sts=4 et:
# Check whether the system is running as a Xen paravirtualized guest
# Returns: 0 if Xen PV, 1 otherwise
is_xen() {
local ret
if [ ! -d "$g_procfs/xen" ]; then
return 1
fi
# XXX do we have a better way that relying on dmesg?
dmesg_grep 'Booting paravirtualized kernel on Xen$'
ret=$?
if [ "$ret" -eq 2 ]; then
pr_warn "dmesg truncated, Xen detection will be unreliable. Please reboot and relaunch this script"
return 1
elif [ "$ret" -eq 0 ]; then
return 0
else
return 1
fi
}
# Check whether the system is a Xen Dom0 (privileged domain)
# Returns: 0 if Dom0, 1 otherwise
is_xen_dom0() {
if ! is_xen; then
return 1
fi
if [ -e "$g_procfs/xen/capabilities" ] && grep -q "control_d" "$g_procfs/xen/capabilities"; then
return 0
else
return 1
fi
}
# Check whether the system is a Xen DomU (unprivileged PV guest)
# Returns: 0 if DomU, 1 otherwise
is_xen_domU() {
local ret
if ! is_xen; then
return 1
fi
# PVHVM guests also print 'Booting paravirtualized kernel', so we need this check.
dmesg_grep 'Xen HVM callback vector for event delivery is enabled$'
ret=$?
if [ "$ret" -eq 0 ]; then
return 1
fi
if ! is_xen_dom0; then
return 0
else
return 1
fi
}

View File

@@ -0,0 +1,78 @@
# vim: set ts=4 sw=4 sts=4 et:
g_builtin_dbversion=$(awk '/^# %%% MCEDB / { print $4 }' "$0")
if [ -r "$g_mcedb_cache" ]; then
# we have a local cache file, but it might be older than the builtin version we have
g_local_dbversion=$(awk '/^# %%% MCEDB / { print $4 }' "$g_mcedb_cache")
# compare version strings of the form vN+iYYYYMMDD+hash
local_v=$(echo "$g_local_dbversion" | sed 's/^v\([0-9]*\).*/\1/')
builtin_v=$(echo "$g_builtin_dbversion" | sed 's/^v\([0-9]*\).*/\1/')
local_i=$(echo "$g_local_dbversion" | sed 's/.*+i\([0-9]*\).*/\1/')
builtin_i=$(echo "$g_builtin_dbversion" | sed 's/.*+i\([0-9]*\).*/\1/')
if [ "$local_v" -gt "$builtin_v" ] ||
{ [ "$local_v" -eq "$builtin_v" ] && [ "$local_i" -gt "$builtin_i" ]; }; then
g_mcedb_source="$g_mcedb_cache"
g_mcedb_info="local firmwares DB $g_local_dbversion"
fi
fi
# if g_mcedb_source is not set, either we don't have a local cached db, or it is older than the builtin db
if [ -z "${g_mcedb_source:-}" ]; then
g_mcedb_source="$0"
g_mcedb_info="builtin firmwares DB $g_builtin_dbversion"
fi
# Read the MCExtractor microcode database (from local cache or builtin) to stdout
read_mcedb() {
awk '{ if (DELIM==1) { print $2 } } /^# %%% MCEDB / { DELIM=1 }' "$g_mcedb_source"
}
# Read the Intel official affected CPUs database (builtin) to stdout
read_inteldb() {
awk '/^# %%% ENDOFINTELDB/ { exit } { if (DELIM==1) { print $2 } } /^# %%% INTELDB/ { DELIM=1 }' "$0"
}
# Check whether the CPU is running the latest known microcode version
# Sets: ret_is_latest_known_ucode_latest, ret_is_latest_known_ucode_version
# 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
fi
if [ -z "$cpu_ucode" ]; then
ret_is_latest_known_ucode_latest="couldn't get your microcode version"
return 2
fi
ret_is_latest_known_ucode_latest="latest microcode version for your CPU model is unknown"
if is_intel; then
brand_prefix=I
elif is_amd; then
brand_prefix=A
else
return 2
fi
for tuple in $(read_mcedb | grep "$(printf "^$brand_prefix,0x%08X," "$cpu_cpuid")"); do
# skip if the pfmask doesn't match our platformid
pfmask=$(echo "$tuple" | cut -d, -f3)
if is_intel && [ $((cpu_platformid & pfmask)) -eq 0 ]; then
continue
fi
ucode=$(($(echo "$tuple" | cut -d, -f4)))
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
return 1
fi
done
pr_debug "is_latest_known_ucode: this cpuid is not referenced ($cpu_cpuid)"
return 2
}
# Read and cache the kernel command line from /proc/cmdline or mock
# Sets: g_kernel_cmdline

View File

@@ -0,0 +1,16 @@
# vim: set ts=4 sw=4 sts=4 et:
get_cmdline() {
if [ -n "${g_kernel_cmdline:-}" ]; then
return
fi
if [ -n "${SMC_MOCK_CMDLINE:-}" ]; then
g_mocked=1
pr_debug "get_cmdline: using g_mocked cmdline '$SMC_MOCK_CMDLINE'"
g_kernel_cmdline="$SMC_MOCK_CMDLINE"
return
else
g_kernel_cmdline=$(cat "$g_procfs/cmdline")
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_CMDLINE='$g_kernel_cmdline'")
fi
}

1501
src/libs/400_hw_check.sh Normal file

File diff suppressed because it is too large Load Diff

224
src/main.sh Normal file
View File

@@ -0,0 +1,224 @@
# 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"
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
if [ "$opt_cve_all" = 1 ] || echo "$opt_cve_list" | grep -qw "$cve"; then
check_"$(echo "$cve" | tr - _)"
pr_info
fi
done
fi # g_mode != hw-only
if [ -n "$g_final_summary" ]; then
pr_info "> \033[46m\033[30mSUMMARY:\033[0m$g_final_summary"
pr_info ""
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"
fi
g_vars=$(set | grep -Ev '^[A-Z_[:space:]]' | grep -v -F 'g_mockme=' | sort | tr "\n" '|')
pr_debug "variables at end of script: $g_vars"
if [ -n "$g_mockme" ] && [ "$opt_mock" = 1 ]; then
if command -v "gzip" >/dev/null 2>&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')"
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
fi
if [ -n "$g_mock_cpuinfo" ]; then
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_CPUINFO='$g_mock_cpuinfo'")
unset g_mock_cpuinfo
fi
pr_info ""
# shellcheck disable=SC2046
pr_warn "To mock this CPU, set those vars: "$(echo "$g_mockme" | sort -u)
fi
# root check
if [ "$(id -u)" -ne 0 ]; then
pr_warn "Note that you should launch this script with root privileges to get completely accurate information."
pr_warn "To run it as root, you can try the following command: sudo $0"
pr_warn
fi
if [ "$opt_explain" = 0 ]; then
pr_info "Need more detailed information about mitigation options? Use --explain"
fi
pr_info "A false sense of security is worse than no security at all, see --disclaimer"
if [ "$g_mocked" = 1 ]; then
pr_info ""
pr_warn "One or several values have been g_mocked. This should only be done when debugging/testing this script."
pr_warn "The results do NOT reflect the actual status of the system we're running on."
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"
else
_nrpe_status_word='OK'
_nrpe_summary="All ${g_nrpe_total} CVE checks passed"
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
_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)"
fi
# exit with the proper exit code
[ "$g_critical" = 1 ] && exit 2 # critical
[ "$g_unknown" = 1 ] && exit 3 # unknown
exit 0 # ok

View File

@@ -0,0 +1,24 @@
# vim: set ts=4 sw=4 sts=4 et:
# Generic CVE check dispatcher: prints CVE header and calls the OS-specific check function
# Args: $1=cve_id $2=func_prefix(optional, default derived from CVE ID)
check_cve() {
local cve func_prefix
cve="$1"
func_prefix="${2:-check_$(echo "$cve" | tr - _)}"
pr_info "\033[1;34m$cve aka '$(cve2name "$cve")'\033[0m"
if [ "$g_os" = Linux ]; then
if type "${func_prefix}_linux" >/dev/null 2>&1; then
"${func_prefix}_linux"
else
pr_warn "Unsupported OS ($g_os)"
fi
elif echo "$g_os" | grep -q BSD; then
if type "${func_prefix}_bsd" >/dev/null 2>&1; then
"${func_prefix}_bsd"
else
pr_warn "Unsupported OS ($g_os)"
fi
else
pr_warn "Unsupported OS ($g_os)"
fi
}

View File

@@ -0,0 +1,248 @@
# vim: set ts=4 sw=4 sts=4 et:
# MDS (microarchitectural data sampling) - BSD mitigation check
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 sysctl hw.mds_disable >/dev/null 2>&1; then
pstatus green YES
kernel_md_clear=1
else
pstatus yellow NO
kernel_md_clear=0
fi
else
if grep -Fq hw.mds_disable "$opt_kernel"; then
pstatus green YES
kernel_md_clear=1
else
kernel_md_clear=0
pstatus yellow NO
fi
fi
pr_info_nol "* CPU Hyper-Threading (SMT) is disabled: "
if sysctl machdep.hyperthreading_allowed >/dev/null 2>&1; then
kernel_smt_allowed=$(sysctl -n machdep.hyperthreading_allowed 2>/dev/null)
if [ "$kernel_smt_allowed" = 1 ]; then
pstatus yellow NO
else
pstatus green YES
fi
else
pstatus yellow UNKNOWN "sysctl machdep.hyperthreading_allowed doesn't exist"
fi
pr_info_nol "* Kernel mitigation is enabled: "
if [ "$kernel_md_clear" = 1 ]; then
kernel_mds_enabled=$(sysctl -n hw.mds_disable 2>/dev/null)
else
kernel_mds_enabled=0
fi
case "$kernel_mds_enabled" in
0) pstatus yellow NO ;;
1) pstatus green YES "with microcode support" ;;
2) pstatus green YES "software-only support (SLOW)" ;;
3) pstatus green YES ;;
*) pstatus yellow UNKNOWN "unknown value $kernel_mds_enabled" ;;
esac
pr_info_nol "* Kernel mitigation is active: "
if [ "$kernel_md_clear" = 1 ]; then
kernel_mds_state=$(sysctl -n hw.mds_disable_state 2>/dev/null)
else
kernel_mds_state=inactive
fi
# possible values for hw.mds_disable_state (FreeBSD cpu_machdep.c):
# - inactive: no mitigation (non-Intel, disabled, or not needed)
# - VERW: microcode-based VERW instruction
# - software IvyBridge: SW sequence for Ivy Bridge
# - software Broadwell: SW sequence for Broadwell
# - software Skylake SSE: SW sequence for Skylake (SSE)
# - software Skylake AVX: SW sequence for Skylake (AVX)
# - software Skylake AVX512: SW sequence for Skylake (AVX-512)
# - software Silvermont: SW sequence for Silvermont
# - unknown: fallback if handler doesn't match any known
# ref: https://github.com/freebsd/freebsd-src/blob/main/sys/x86/x86/cpu_machdep.c
case "$kernel_mds_state" in
inactive) pstatus yellow NO ;;
VERW) pstatus green YES "with microcode support" ;;
software*) pstatus green YES "software-only support (SLOW)" ;;
*) pstatus yellow UNKNOWN ;;
esac
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
else
if [ "$cap_md_clear" = 1 ]; then
if [ "$kernel_md_clear" = 1 ]; then
if [ "$g_mode" = live ]; then
# mitigation must also be enabled
if [ "$kernel_mds_enabled" -ge 1 ]; then
if [ "$opt_paranoid" != 1 ] || [ "$kernel_smt_allowed" = 0 ]; then
pvulnstatus "$cve" OK "Your microcode and kernel are both up to date for this mitigation, and mitigation is enabled"
else
pvulnstatus "$cve" VULN "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
pvulnstatus "$cve" VULN "Your microcode and kernel are both up to date for this mitigation, but the mitigation is not active"
explain "To enable mitigation, run \`sysctl hw.mds_disable=1'. To make this change persistent across reboots, you can add 'hw.mds_disable=1' to /etc/sysctl.conf."
fi
else
pvulnstatus "$cve" OK "Your microcode and kernel are both up to date for this mitigation"
fi
else
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
# no MD_CLEAR in microcode, but FreeBSD may still have software-only mitigation active
case "$kernel_mds_state" in
software*)
if [ "$opt_paranoid" = 1 ]; then
pvulnstatus "$cve" VULN "Software-only mitigation is active, but in paranoid mode a microcode-based mitigation is required"
elif [ "$kernel_smt_allowed" = 1 ]; then
pvulnstatus "$cve" OK "Software-only mitigation is active, but SMT is enabled so cross-thread attacks are still possible"
else
pvulnstatus "$cve" OK "Software-only mitigation is active (no microcode update required for this CPU)"
fi
;;
*)
pvulnstatus "$cve" VULN "Your kernel supports mitigation, but your CPU microcode also needs to be updated to mitigate the vulnerability"
;;
esac
elif [ "$kernel_md_clear" = 1 ]; then
pvulnstatus "$cve" VULN "Your kernel supports mitigation, but your CPU microcode also needs to be updated to mitigate the vulnerability"
else
pvulnstatus "$cve" VULN "Neither your kernel or your microcode support mitigation, upgrade both to mitigate the vulnerability"
fi
fi
fi
}
# MDS (microarchitectural data sampling) - Linux mitigation check
check_mds_linux() {
local status sys_interface_available msg kernel_md_clear kernel_md_clear_can_tell mds_mitigated mds_smt_mitigated mystatus mymsg
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "$VULN_SYSFS_BASE/mds" '^[^;]+'; then
sys_interface_available=1
status=$ret_sys_interface_check_status
fi
if [ "$opt_sysfs_only" != 1 ]; then
# MDS is Intel-only; skip x86-specific kernel/cpuinfo checks on non-x86 kernels
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"
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 [ "$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
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"
else
if [ "$opt_sysfs_only" != 1 ]; then
# 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
# mitigation must also be enabled
if [ "$mds_mitigated" = 1 ]; then
if [ "$opt_paranoid" != 1 ] || [ "$mds_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_md_clear" ]; 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 now 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
fi
}

View File

@@ -0,0 +1,256 @@
# vim: set ts=4 sw=4 sts=4 et:
# MMIO Stale Data (Processor MMIO Stale Data Vulnerabilities) - BSD mitigation check
check_mmio_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
}
# 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
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.
#
# 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.
# Bug is set only when: cpu_matches(blacklist, MMIO) AND NOT arch_cap_mmio_immune().
#
# microcode mitigation: ARCH_CAP_FB_CLEAR (bit 17) -- VERW clears fill buffers.
# 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"
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

@@ -0,0 +1,286 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# 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
# by CONFIG_MITIGATION_SLS (formerly CONFIG_SLS before kernel 6.8), which
# enables -mharden-sls=all to insert INT3 after these instructions.
# No sysfs interface, no MSR, no CPU feature flag.
# Related: CVE-2021-26341 (AMD Zen1/Zen2 direct-branch SLS subset).
# Heuristic: scan the kernel .text section for indirect call/jmp thunks
# (retpoline-style stubs), then check whether tail-call JMPs to those thunks
# are followed by INT3 (0xcc). With SLS enabled: >80%. Without: <20%.
#
# Thunk signature: e8 01 00 00 00 cc 48 89 XX 24
# call +1; int3; mov <reg>,(%rsp); ...
# Tail-call pattern: e9 XX XX XX XX [cc?]
# jmp <thunk>; [int3 if SLS]
# Perl implementation of the SLS heuristic byte scanner.
# Args: $1 = path to raw .text binary (from objcopy -O binary -j .text)
# Output: thunks=N jmps=N sls=N
#
# The heuristic looks for two types of thunks and counts how many jmp rel32
# instructions targeting them are followed by INT3 (the SLS mitigation):
#
# 1. Indirect call/jmp thunks (retpoline stubs used for indirect tail calls):
# e8 01 00 00 00 cc 48 89 XX 24 (call +1; int3; mov <reg>,(%rsp))
#
# 2. Return thunk (used for all function returns via jmp __x86_return_thunk):
# c3 90 90 90 90 cc cc cc cc cc (ret; nop*4; int3*5+)
# This is the most common jmp target in retpoline-enabled kernels.
#
# Some kernels only use indirect thunks, some only the return thunk, and some
# use both. We check both and combine the results.
_sls_heuristic_perl() {
perl -e '
use strict;
use warnings;
local $/;
open my $fh, "<:raw", $ARGV[0] or die "open: $!";
my $text = <$fh>;
close $fh;
my $len = length($text);
# Collect two types of thunks separately, as different kernels
# apply SLS to different thunk types.
my (%indirect_thunks, %return_thunks);
# Pattern 1: indirect call/jmp thunks (retpoline stubs)
while ($text =~ /\xe8\x01\x00\x00\x00\xcc\x48\x89.\x24/gs) {
$indirect_thunks{ pos($text) - length($&) } = 1;
}
# Pattern 2: return thunk (ret; nop*4; int3*5)
while ($text =~ /\xc3\x90\x90\x90\x90\xcc\xcc\xcc\xcc\xcc/gs) {
$return_thunks{ pos($text) - length($&) } = 1;
}
my $n_indirect = scalar keys %indirect_thunks;
my $n_return = scalar keys %return_thunks;
if ($n_indirect + $n_return == 0) {
print "thunks=0 jmps=0 sls=0\n";
exit 0;
}
# Count jmps to each thunk type separately
my ($ind_total, $ind_sls) = (0, 0);
my ($ret_total, $ret_sls) = (0, 0);
for (my $i = 0; $i + 5 < $len; $i++) {
next unless substr($text, $i, 1) eq "\xe9";
my $rel = unpack("V", substr($text, $i + 1, 4));
$rel -= 4294967296 if $rel >= 2147483648;
my $target = $i + 5 + $rel;
my $has_int3 = ($i + 5 < $len && substr($text, $i + 5, 1) eq "\xcc") ? 1 : 0;
if (exists $indirect_thunks{$target}) {
$ind_total++;
$ind_sls += $has_int3;
}
if (exists $return_thunks{$target}) {
$ret_total++;
$ret_sls += $has_int3;
}
}
# Use whichever thunk type has jmps; prefer indirect thunks if both have data
my ($total, $sls, $n_thunks);
if ($ind_total > 0) {
($total, $sls, $n_thunks) = ($ind_total, $ind_sls, $n_indirect);
} elsif ($ret_total > 0) {
($total, $sls, $n_thunks) = ($ret_total, $ret_sls, $n_return);
} else {
($total, $sls, $n_thunks) = (0, 0, $n_indirect + $n_return);
}
printf "thunks=%d jmps=%d sls=%d\n", $n_thunks, $total, $sls;
' "$1" 2>/dev/null
}
# Awk fallback implementation of the SLS heuristic byte scanner.
# Slower than perl but uses only POSIX tools (od + awk).
# Args: $1 = path to raw .text binary (from objcopy -O binary -j .text)
# Output: thunks=N jmps=N sls=N
_sls_heuristic_awk() {
od -An -tu1 -v "$1" | awk '
{
for (i = 1; i <= NF; i++) b[n++] = $i + 0
}
END {
# Pattern 1: indirect call/jmp thunks
# 232 1 0 0 0 204 72 137 XX 36 (e8 01 00 00 00 cc 48 89 XX 24)
for (i = 0; i + 9 < n; i++) {
if (b[i]==232 && b[i+1]==1 && b[i+2]==0 && b[i+3]==0 && \
b[i+4]==0 && b[i+5]==204 && b[i+6]==72 && b[i+7]==137 && \
b[i+9]==36) {
ind[i] = 1
n_ind++
}
}
# Pattern 2: return thunk (ret; nop*4; int3*5)
# 195 144 144 144 144 204 204 204 204 204 (c3 90 90 90 90 cc cc cc cc cc)
for (i = 0; i + 9 < n; i++) {
if (b[i]==195 && b[i+1]==144 && b[i+2]==144 && b[i+3]==144 && \
b[i+4]==144 && b[i+5]==204 && b[i+6]==204 && b[i+7]==204 && \
b[i+8]==204 && b[i+9]==204) {
ret[i] = 1
n_ret++
}
}
if (n_ind + n_ret == 0) { print "thunks=0 jmps=0 sls=0"; exit }
# Count jmps to each thunk type separately
ind_total = 0; ind_sls = 0
ret_total = 0; ret_sls = 0
for (i = 0; i + 5 < n; i++) {
if (b[i] != 233) continue
rel = b[i+1] + b[i+2]*256 + b[i+3]*65536 + b[i+4]*16777216
if (rel >= 2147483648) rel -= 4294967296
target = i + 5 + rel
has_int3 = (b[i+5] == 204) ? 1 : 0
if (target in ind) { ind_total++; ind_sls += has_int3 }
if (target in ret) { ret_total++; ret_sls += has_int3 }
}
# Prefer indirect thunks if they have data, else fall back to return thunk
if (ind_total > 0)
printf "thunks=%d jmps=%d sls=%d\n", n_ind, ind_total, ind_sls
else if (ret_total > 0)
printf "thunks=%d jmps=%d sls=%d\n", n_ret, ret_total, ret_sls
else
printf "thunks=%d jmps=0 sls=0\n", n_ind + n_ret
}' 2>/dev/null
}
check_CVE_0000_0001_linux() {
local status sys_interface_available msg
status=UNK
sys_interface_available=0
msg=''
# No sysfs interface for SLS
# sys_interface_available stays 0
if [ "$opt_sysfs_only" != 1 ]; then
# --- CPU affection check ---
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU is not affected"
return
fi
# --- ARM: no kernel mitigation available ---
if is_arm_kernel; 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" \
"or DSB+ISB after RET and BR instructions. However, the Linux kernel does not enable this flag:\n" \
"patches to add CONFIG_HARDEN_SLS_ALL were submitted in 2021 but were rejected upstream.\n" \
"There is currently no kernel-level mitigation for SLS on arm64."
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
local _sls_config=''
if [ -n "$opt_config" ] && [ -r "$opt_config" ]; then
pr_info_nol " * Kernel compiled with SLS mitigation: "
if grep -qE '^CONFIG_(MITIGATION_)?SLS=y' "$opt_config"; then
_sls_config=1
pstatus green YES
else
_sls_config=0
pstatus yellow NO
fi
fi
# --- method 2: kernel image heuristic (fallback when no config) ---
local _sls_heuristic=''
if [ -z "$_sls_config" ]; then
pr_info_nol " * Kernel compiled with SLS mitigation: "
if [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "$g_kernel_err"
elif [ -z "$g_kernel" ]; then
pstatus yellow UNKNOWN "no kernel image available"
elif ! command -v "${opt_arch_prefix}objcopy" >/dev/null 2>&1; then
pstatus yellow UNKNOWN "missing '${opt_arch_prefix}objcopy' tool, usually in the binutils package"
else
local _sls_result
g_sls_text_tmp=$(mktemp -t smc-sls-text-XXXXXX)
if ! "${opt_arch_prefix}objcopy" -O binary -j .text "$g_kernel" "$g_sls_text_tmp" 2>/dev/null || [ ! -s "$g_sls_text_tmp" ]; then
pstatus yellow UNKNOWN "failed to extract .text section from kernel image"
rm -f "$g_sls_text_tmp"
g_sls_text_tmp=''
else
_sls_result=''
if command -v perl >/dev/null 2>&1; then
_sls_result=$(_sls_heuristic_perl "$g_sls_text_tmp")
elif command -v awk >/dev/null 2>&1; then
_sls_result=$(_sls_heuristic_awk "$g_sls_text_tmp")
fi
rm -f "$g_sls_text_tmp"
g_sls_text_tmp=''
if [ -z "$_sls_result" ]; then
pstatus yellow UNKNOWN "missing 'perl' or 'awk' tool for heuristic scan"
else
local _sls_thunks _sls_jmps _sls_int3
_sls_thunks=$(echo "$_sls_result" | sed -n 's/.*thunks=\([0-9]*\).*/\1/p')
_sls_jmps=$(echo "$_sls_result" | sed -n 's/.*jmps=\([0-9]*\).*/\1/p')
_sls_int3=$(echo "$_sls_result" | sed -n 's/.*sls=\([0-9]*\).*/\1/p')
pr_debug "sls heuristic: thunks=$_sls_thunks jmps=$_sls_jmps int3=$_sls_int3"
if [ "${_sls_thunks:-0}" = 0 ] || [ "${_sls_jmps:-0}" = 0 ]; then
pstatus yellow UNKNOWN "no retpoline indirect thunks found in kernel image"
else
local _sls_pct=$((_sls_int3 * 100 / _sls_jmps))
if [ "$_sls_pct" -ge 80 ]; then
_sls_heuristic=1
pstatus green YES "$_sls_int3/$_sls_jmps indirect tail-call JMPs hardened (${_sls_pct}%%)"
elif [ "$_sls_pct" -le 20 ]; then
_sls_heuristic=0
pstatus yellow NO "$_sls_int3/$_sls_jmps indirect tail-call JMPs hardened (${_sls_pct}%%)"
else
pstatus yellow UNKNOWN "$_sls_int3/$_sls_jmps indirect tail-call JMPs hardened (${_sls_pct}%%, inconclusive)"
fi
fi
fi
fi
fi
fi
# --- verdict (x86_64) ---
if [ "$_sls_config" = 1 ] || [ "$_sls_heuristic" = 1 ]; then
pvulnstatus "$cve" OK "kernel compiled with SLS mitigation"
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" \
"This enables the GCC flag -mharden-sls=all, which inserts INT3 after unconditional control flow\n" \
"instructions to block straight-line speculation. Note: this option defaults to off in most kernels\n" \
"and incurs ~2.4%% text size overhead."
else
pvulnstatus "$cve" UNK "couldn't determine SLS mitigation status"
fi
elif [ "$sys_interface_available" = 0 ]; then
msg="/sys vulnerability interface use forced, but there is no sysfs entry for SLS"
status=UNK
pvulnstatus "$cve" "$status" "$msg"
fi
}
check_CVE_0000_0001_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
}

View File

@@ -0,0 +1,15 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-0000-0001, SLS, Straight-Line Speculation
# Supplementary check, only runs under --extra
# shellcheck disable=SC2034
check_CVE_0000_0001() {
# SLS is a supplementary check: skip it in the default "all CVEs" run
# unless --extra is passed, but always run when explicitly selected
# via --variant sls or --cve CVE-0000-0001
if [ "$opt_cve_all" = 1 ] && [ "$opt_extra" != 1 ]; then
return 0
fi
check_cve 'CVE-0000-0001'
}

1269
src/vulns/CVE-2017-5715.sh Normal file

File diff suppressed because it is too large Load Diff

276
src/vulns/CVE-2017-5753.sh Normal file
View File

@@ -0,0 +1,276 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2017-5753, Spectre V1, Bounds Check Bypass
# Sets: (none directly, delegates to check_cve)
check_CVE_2017_5753() {
check_cve 'CVE-2017-5753'
}
# Sets: g_redhat_canonical_spectre (via check_redhat_canonical_spectre)
check_CVE_2017_5753_linux() {
local status sys_interface_available msg v1_kernel_mitigated v1_kernel_mitigated_err v1_mask_nospec ret explain_text
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "$VULN_SYSFS_BASE/spectre_v1"; then
# this kernel has the /sys interface, trust it over everything
# v0.33+: don't. some kernels have backported the array_index_mask_nospec() workaround without
# modifying the vulnerabilities/spectre_v1 file. that's bad. we can't trust it when it says Vulnerable :(
# see "silent backport" detection at the bottom of this func
sys_interface_available=1
#
# Complete sysfs message inventory for spectre_v1, traced via git blame:
#
# all versions:
# "Not affected" (cpu_show_common, pre-existing)
#
# --- x86 mainline ---
# 61dc0f555b5c (v4.15, initial spectre_v1 sysfs):
# "Vulnerable"
# edfbae53dab8 (v4.16, report get_user mitigation):
# "Mitigation: __user pointer sanitization"
# a2059825986a (v5.3, swapgs awareness via spectre_v1_strings[]):
# "Vulnerable: __user pointer sanitization and usercopy barriers only; no swapgs barriers"
# "Mitigation: usercopy/swapgs barriers and __user pointer sanitization"
# ca01c0d8d030 (v6.12, CONFIG_MITIGATION_SPECTRE_V1 controls default):
# same strings as v5.3+
# All stable branches (4.4.y through 6.12.y) have v5.3+ strings backported.
#
# --- x86 RHEL (centos6, centos7 branches) ---
# "Vulnerable: Load fences, __user pointer sanitization and usercopy barriers only; no swapgs barriers"
# "Mitigation: Load fences, usercopy/swapgs barriers and __user pointer sanitization"
#
# --- ARM64 ---
# 3891ebccace1 (v5.2, first arm64 spectre_v1 sysfs, backported to 4.14.y+):
# "Mitigation: __user pointer sanitization" (hardcoded)
# 455697adefdb (v5.10, moved to proton-pack.c):
# same string
# Before v5.2: no sysfs override (generic "Not affected" fallback).
# Actual mitigation (array_index_mask_nospec with CSDB) landed in v4.16.
#
# --- ARM32 ---
# 9dd78194a372 (v5.17+):
# "Mitigation: __user pointer sanitization" (hardcoded)
#
# all messages start with either "Not affected", "Mitigation", or "Vulnerable"
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
# 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.
pr_info_nol "* Kernel has spectre_v1 mitigation (kernel image): "
v1_kernel_mitigated=''
v1_kernel_mitigated_err=''
if [ -n "$g_kernel_err" ]; then
v1_kernel_mitigated_err="$g_kernel_err"
elif grep -q '__user pointer sanitization' "$g_kernel"; then
if grep -q 'usercopy/swapgs barriers' "$g_kernel"; then
v1_kernel_mitigated="usercopy/swapgs barriers and target sanitization"
elif grep -q 'Load fences' "$g_kernel"; then
v1_kernel_mitigated="RHEL Load fences mitigation"
else
v1_kernel_mitigated="__user pointer sanitization"
fi
fi
if [ -z "$v1_kernel_mitigated" ] && [ -r "$opt_config" ]; then
if grep -q '^CONFIG_MITIGATION_SPECTRE_V1=y' "$opt_config"; then
v1_kernel_mitigated="CONFIG_MITIGATION_SPECTRE_V1 found in kernel config"
fi
fi
if [ -z "$v1_kernel_mitigated" ] && [ -n "$opt_map" ]; then
if grep -q 'spectre_v1_select_mitigation' "$opt_map"; then
v1_kernel_mitigated="found spectre_v1_select_mitigation in System.map"
fi
fi
if [ -n "$v1_kernel_mitigated" ]; then
pstatus green YES "$v1_kernel_mitigated"
elif [ -n "$v1_kernel_mitigated_err" ]; then
pstatus yellow UNKNOWN "couldn't check ($v1_kernel_mitigated_err)"
else
pstatus yellow NO
fi
# 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.
if [ -z "$v1_kernel_mitigated" ]; then
pr_info_nol "* Kernel has array_index_mask_nospec (v4.15 binary pattern): "
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"
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 '/\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"
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
pr_info_nol "* Kernel has the Red Hat/Ubuntu patch: "
check_redhat_canonical_spectre
if [ "$g_redhat_canonical_spectre" = -1 ]; then
pstatus yellow UNKNOWN "missing '${opt_arch_prefix}strings' tool, please install it, usually it's in the binutils package"
elif [ "$g_redhat_canonical_spectre" = -2 ]; then
pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)"
elif [ "$g_redhat_canonical_spectre" = 1 ]; then
pstatus green YES
elif [ "$g_redhat_canonical_spectre" = 2 ]; then
pstatus green YES "but without IBRS"
else
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"
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
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"
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
fi
fi # is_arm_kernel
elif [ "$sys_interface_available" = 0 ]; then
msg="/sys vulnerability interface use forced, but it's not available!"
status=UNK
fi
# report status
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 [ -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 [ -n "$v1_kernel_mitigated" ]; then
pvulnstatus "$cve" OK "Kernel source has been patched to mitigate the vulnerability ($v1_kernel_mitigated)"
elif [ -n "$v1_mask_nospec" ]; then
pvulnstatus "$cve" OK "Kernel source has been patched to mitigate the vulnerability ($v1_mask_nospec)"
elif [ "$g_redhat_canonical_spectre" = 1 ] || [ "$g_redhat_canonical_spectre" = 2 ]; then
pvulnstatus "$cve" OK "Kernel source has been patched to mitigate the vulnerability (Red Hat/Ubuntu patch)"
elif [ -n "$g_kernel_err" ]; then
pvulnstatus "$cve" UNK "Couldn't find kernel image or tools missing to execute the checks"
explain "Re-run this script with root privileges, after installing the missing tools indicated above"
else
pvulnstatus "$cve" VULN "Kernel source needs to be patched to mitigate the vulnerability"
explain "Your kernel is too old to have the mitigation for Variant 1, you should upgrade to a newer kernel. If you're using a Linux distro and didn't compile the kernel yourself, you should upgrade your distro to get a newer kernel."
fi
else
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
fi
else
if [ "$msg" = "Vulnerable" ] && { [ -n "$v1_kernel_mitigated" ] || [ -n "$v1_mask_nospec" ]; }; then
pvulnstatus "$cve" OK "Kernel source has been patched to mitigate the vulnerability (silent backport of spectre_v1 mitigation)"
else
if [ "$msg" = "Vulnerable" ]; then
msg="Kernel source needs to be patched to mitigate the vulnerability"
explain_text="Your kernel is too old to have the mitigation for Variant 1, you should upgrade to a newer kernel. If you're using a Linux distro and didn't compile the kernel yourself, you should upgrade your distro to get a newer kernel."
fi
pvulnstatus "$cve" "$status" "$msg"
[ -n "${explain_text:-}" ] && explain "$explain_text"
unset explain_text
fi
fi
}
check_CVE_2017_5753_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
}

281
src/vulns/CVE-2017-5754.sh Normal file
View File

@@ -0,0 +1,281 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2017-5754, Meltdown, Rogue Data Cache Load
# no security impact but give a hint to the user in verbose mode
# about PCID/INVPCID cpuid features that must be present to avoid
# Check whether PCID/INVPCID are available to reduce PTI performance impact
# refs:
# https://marc.info/?t=151532047900001&r=1&w=2
# https://groups.google.com/forum/m/#!topic/mechanical-sympathy/L9mHTbeQLNU
pti_performance_check() {
local ret pcid invpcid
pr_info_nol " * Reduced performance impact of PTI: "
if [ -e "$g_procfs/cpuinfo" ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw pcid; then
pcid=1
else
read_cpuid 0x1 0x0 "$ECX" 17 1 1
ret=$?
if [ "$ret" = "$READ_CPUID_RET_OK" ]; then
pcid=1
fi
fi
if [ -e "$g_procfs/cpuinfo" ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw invpcid; then
invpcid=1
else
read_cpuid 0x7 0x0 "$EBX" 10 1 1
ret=$?
if [ "$ret" = "$READ_CPUID_RET_OK" ]; then
invpcid=1
fi
fi
if [ "$invpcid" = 1 ]; then
pstatus green YES 'CPU supports INVPCID, performance impact of PTI will be greatly reduced'
elif [ "$pcid" = 1 ]; then
pstatus green YES 'CPU supports PCID, performance impact of PTI will be reduced'
else
pstatus blue NO 'PCID/INVPCID not supported, performance impact of PTI will be significant'
fi
}
check_CVE_2017_5754() {
check_cve 'CVE-2017-5754'
}
check_CVE_2017_5754_linux() {
local status sys_interface_available msg kpti_support kpti_can_tell kpti_enabled dmesg_grep pti_xen_pv_domU xen_pv_domo xen_pv_domu explain_text
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "$VULN_SYSFS_BASE/meltdown"; then
# this kernel has the /sys interface, trust it over everything
sys_interface_available=1
status=$ret_sys_interface_check_status
fi
if [ "$opt_sysfs_only" != 1 ]; then
pr_info_nol "* Kernel supports Page Table Isolation (PTI): "
kpti_support=''
kpti_can_tell=0
if [ -n "$opt_config" ]; then
kpti_can_tell=1
kpti_support=$(grep -E -w -e 'CONFIG_(MITIGATION_)?PAGE_TABLE_ISOLATION=y' -e CONFIG_KAISER=y -e CONFIG_UNMAP_KERNEL_AT_EL0=y "$opt_config")
if [ -n "$kpti_support" ]; then
pr_debug "kpti_support: found option '$kpti_support' in $opt_config"
fi
fi
if [ -z "$kpti_support" ] && [ -n "$opt_map" ]; then
# it's not an elif: some backports don't have the PTI config but still include the patch
# so we try to find an exported symbol that is part of the PTI patch in System.map
# parse_kpti: arm
kpti_can_tell=1
kpti_support=$(grep -w -e kpti_force_enabled -e parse_kpti "$opt_map")
if [ -n "$kpti_support" ]; then
pr_debug "kpti_support: found '$kpti_support' in $opt_map"
fi
fi
if [ -z "$kpti_support" ] && [ -n "$g_kernel" ]; then
# same as above but in case we don't have System.map and only kernel, look for the
# nopti option that is part of the patch (kernel command line option)
# 'kpti=': arm
kpti_can_tell=1
if ! command -v "${opt_arch_prefix}strings" >/dev/null 2>&1; then
pstatus yellow UNKNOWN "missing '${opt_arch_prefix}strings' tool, please install it, usually it's in the binutils package"
else
kpti_support=$("${opt_arch_prefix}strings" "$g_kernel" | grep -w -e nopti -e kpti=)
if [ -n "$kpti_support" ]; then
pr_debug "kpti_support: found '$kpti_support' in $g_kernel"
fi
fi
fi
if [ -n "$kpti_support" ]; then
if [ "$opt_verbose" -ge 2 ]; then
pstatus green YES "found '$kpti_support'"
else
pstatus green YES
fi
elif [ "$kpti_can_tell" = 1 ]; then
pstatus yellow NO
else
pstatus yellow UNKNOWN "couldn't read your kernel configuration nor System.map file"
fi
mount_debugfs
pr_info_nol " * PTI enabled and active: "
if [ "$g_mode" = live ]; 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"
# aarch64
dmesg_grep="$dmesg_grep|CPU features: detected( feature)?: Kernel page table isolation \(KPTI\)"
if grep ^flags "$g_procfs/cpuinfo" | grep -qw pti; then
# vanilla PTI patch sets the 'pti' flag in cpuinfo
pr_debug "kpti_enabled: found 'pti' flag in $g_procfs/cpuinfo"
kpti_enabled=1
elif grep ^flags "$g_procfs/cpuinfo" | grep -qw kaiser; then
# kernel line 4.9 sets the 'kaiser' flag in cpuinfo
pr_debug "kpti_enabled: found 'kaiser' flag in $g_procfs/cpuinfo"
kpti_enabled=1
elif [ -e "$DEBUGFS_BASE/x86/pti_enabled" ]; then
# Red Hat Backport creates a dedicated file, see https://access.redhat.com/articles/3311301
kpti_enabled=$(cat "$DEBUGFS_BASE/x86/pti_enabled" 2>/dev/null)
pr_debug "kpti_enabled: file $DEBUGFS_BASE/x86/pti_enabled exists and says: $kpti_enabled"
elif is_xen_dom0; then
pti_xen_pv_domU=$(xl dmesg 2>/dev/null | grep 'XPTI' | grep 'DomU enabled' | head -n1)
[ -n "$pti_xen_pv_domU" ] && kpti_enabled=1
fi
if [ -z "$kpti_enabled" ]; then
dmesg_grep "$dmesg_grep"
ret=$?
if [ "$ret" -eq 0 ]; then
pr_debug "kpti_enabled: found hint in dmesg: $ret_dmesg_grep_grepped"
kpti_enabled=1
elif [ "$ret" -eq 2 ]; then
pr_debug "kpti_enabled: dmesg truncated"
kpti_enabled=-1
fi
fi
if [ -z "$kpti_enabled" ]; then
pr_debug "kpti_enabled: couldn't find any hint that PTI is enabled"
kpti_enabled=0
fi
if [ "$kpti_enabled" = 1 ]; then
pstatus green YES
elif [ "$kpti_enabled" = -1 ]; then
pstatus yellow UNKNOWN "dmesg truncated, please reboot and relaunch this script"
else
pstatus yellow NO
fi
else
pstatus blue N/A "not testable in no-runtime mode"
fi
# PCID/INVPCID are x86-only CPU features
if is_x86_cpu; then
pti_performance_check
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!"
status=UNK
fi
# Test if the current host is a Xen PV Dom0 / DomU
xen_pv_domo=0
xen_pv_domu=0
is_xen_dom0 && xen_pv_domo=1
is_xen_domU && xen_pv_domu=1
if [ "$g_mode" = live ]; 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: "
if [ "$xen_pv_domu" = 1 ]; then
pstatus yellow YES
else
pstatus blue NO
fi
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 [ -z "$msg" ]; then
# if msg is empty, sysfs check didn't fill it, rely on our own test
if [ "$g_mode" = live ]; then
if [ "$kpti_enabled" = 1 ]; then
pvulnstatus "$cve" OK "PTI mitigates the vulnerability"
elif [ "$xen_pv_domo" = 1 ]; then
pvulnstatus "$cve" OK "Xen Dom0s are safe and do not require PTI"
elif [ "$xen_pv_domu" = 1 ]; then
pvulnstatus "$cve" VULN "Xen PV DomUs are vulnerable and need to be run in HVM, PVHVM, PVH mode, or the Xen hypervisor must have the Xen's own PTI patch"
explain "Go to https://blog.xenproject.org/2018/01/22/xen-project-spectre-meltdown-faq-jan-22-update/ for more information"
elif [ "$kpti_enabled" = -1 ]; then
pvulnstatus "$cve" UNK "couldn't find any clue of PTI activation due to a truncated dmesg, please reboot and relaunch this script"
else
pvulnstatus "$cve" VULN "PTI is needed to mitigate the vulnerability"
if [ -n "$kpti_support" ]; then
if [ -e "$DEBUGFS_BASE/x86/pti_enabled" ]; then
explain "Your kernel supports PTI but it's disabled, you can enable it with \`echo 1 > $DEBUGFS_BASE/x86/pti_enabled\`"
elif echo "$g_kernel_cmdline" | grep -q -w -e nopti -e pti=off; then
explain "Your kernel supports PTI but it has been disabled on command-line, remove the nopti or pti=off option from your bootloader configuration"
else
explain "Your kernel supports PTI but it has been disabled, check \`dmesg\` right after boot to find clues why the system disabled it"
fi
else
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)"
fi
fi
else
if [ -n "$kpti_support" ]; then
pvulnstatus "$cve" OK "no-runtime 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"
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
else
if [ "$xen_pv_domo" = 1 ]; then
msg="Xen Dom0s are safe and do not require PTI"
status="OK"
elif [ "$xen_pv_domu" = 1 ]; then
msg="Xen PV DomUs are vulnerable and need to be run in HVM, PVHVM, PVH mode, or the Xen hypervisor must have the Xen's own PTI patch"
status="VULN"
explain_text="Go to https://blog.xenproject.org/2018/01/22/xen-project-spectre-meltdown-faq-jan-22-update/ for more information"
elif [ "$msg" = "Vulnerable" ]; then
msg="PTI is needed to mitigate the vulnerability"
explain_text="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)"
fi
pvulnstatus "$cve" "$status" "$msg"
[ -z "${explain_text:-}" ] && [ "$msg" = "Vulnerable" ] && explain_text="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)"
[ -n "${explain_text:-}" ] && explain "$explain_text"
unset explain_text
fi
# Warn the user about XSA-254 recommended mitigations
if [ "$xen_pv_domo" = 1 ]; then
pr_warn
pr_warn "This host is a Xen Dom0. Please make sure that you are running your DomUs"
pr_warn "in HVM, PVHVM or PVH mode to prevent any guest-to-host / host-to-guest attacks."
pr_warn
pr_warn "See https://blog.xenproject.org/2018/01/22/xen-project-spectre-meltdown-faq-jan-22-update/ and XSA-254 for details."
fi
}
check_CVE_2017_5754_bsd() {
local kpti_enabled
pr_info_nol "* Kernel supports Page Table Isolation (PTI): "
kpti_enabled=$(sysctl -n vm.pmap.pti 2>/dev/null)
if [ -z "$kpti_enabled" ]; then
pstatus yellow NO
else
pstatus green YES
fi
pr_info_nol " * PTI enabled and active: "
if [ "$kpti_enabled" = 1 ]; then
pstatus green YES
else
pstatus yellow NO
fi
pti_performance_check
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 [ "$kpti_enabled" = 1 ]; then
pvulnstatus "$cve" OK "PTI mitigates the vulnerability"
elif [ -n "$kpti_enabled" ]; then
pvulnstatus "$cve" VULN "PTI is supported but disabled on your system"
else
pvulnstatus "$cve" VULN "PTI is needed to mitigate the vulnerability"
fi
}

View File

@@ -0,0 +1,7 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2018-12126, MSBDS, Fallout, Microarchitectural Store Buffer Data Sampling
check_CVE_2018_12126() {
check_cve 'CVE-2018-12126' check_mds
}

View File

@@ -0,0 +1,7 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2018-12127, MLPDS, RIDL, Microarchitectural Load Port Data Sampling
check_CVE_2018_12127() {
check_cve 'CVE-2018-12127' check_mds
}

View File

@@ -0,0 +1,7 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2018-12130, MFBDS, ZombieLoad, Microarchitectural Fill Buffer Data Sampling
check_CVE_2018_12130() {
check_cve 'CVE-2018-12130' check_mds
}

114
src/vulns/CVE-2018-12207.sh Normal file
View File

@@ -0,0 +1,114 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2018-12207, iTLB Multihit, No eXcuses, Machine Check Exception on Page Size Changes
check_CVE_2018_12207() {
check_cve 'CVE-2018-12207'
}
check_CVE_2018_12207_linux() {
local status sys_interface_available msg kernel_itlbmh kernel_itlbmh_err
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "$VULN_SYSFS_BASE/itlb_multihit"; then
# this kernel has the /sys interface, trust it over everything
sys_interface_available=1
status=$ret_sys_interface_check_status
fi
if [ "$opt_sysfs_only" != 1 ]; then
check_has_vmm
pr_info_nol "* iTLB Multihit mitigation is supported by kernel: "
kernel_itlbmh=''
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
kernel_itlbmh="found itlb_multihit in kernel image"
fi
if [ -n "$kernel_itlbmh" ]; then
pstatus green YES "$kernel_itlbmh"
elif [ -n "$kernel_itlbmh_err" ]; then
pstatus yellow UNKNOWN "$kernel_itlbmh_err"
else
pstatus yellow NO
fi
pr_info_nol "* iTLB Multihit mitigation enabled and active: "
if [ "$g_mode" = live ]; 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"
else
pstatus yellow NO
fi
else
pstatus yellow NO "itlb_multihit not found in sysfs hierarchy"
fi
else
pstatus blue N/A "not testable in no-runtime mode"
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!"
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 [ "$g_has_vmm" = 0 ]; then
pvulnstatus "$cve" OK "this system is not running a hypervisor"
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 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
if [ -n "$kernel_itlbmh" ]; then
pvulnstatus "$cve" OK "Your kernel supports iTLB Multihit mitigation"
else
pvulnstatus "$cve" VULN "Your kernel doesn't support iTLB Multihit mitigation, update it"
fi
fi
else
# --sysfs-only: sysfs was available (otherwise msg would be set), use its result
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
fi
else
# msg was set explicitly: either sysfs-not-available error, or a sysfs override
pvulnstatus "$cve" "$status" "$msg"
fi
}
check_CVE_2018_12207_bsd() {
local kernel_2m_x_ept
pr_info_nol "* Kernel supports disabling superpages for executable mappings under EPT: "
kernel_2m_x_ept=$(sysctl -n vm.pmap.allow_2m_x_ept 2>/dev/null)
if [ -z "$kernel_2m_x_ept" ]; then
pstatus yellow NO
else
pstatus green YES
fi
pr_info_nol "* Superpages are disabled for executable mappings under EPT: "
if [ "$kernel_2m_x_ept" = 0 ]; then
pstatus green YES
else
pstatus yellow NO
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 [ -z "$kernel_2m_x_ept" ]; then
pvulnstatus "$cve" VULN "Your kernel doesn't support mitigating this CVE, you should update it"
elif [ "$kernel_2m_x_ept" != 0 ]; then
pvulnstatus "$cve" VULN "Your kernel supports mitigating this CVE, but the mitigation is disabled"
explain "To enable the mitigation, use \`sysctl vm.pmap.allow_2m_x_ept=0\`"
else
pvulnstatus "$cve" OK "Your kernel has support for mitigation and the mitigation is enabled"
fi
}

View File

@@ -0,0 +1,30 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2018-3615, Foreshadow (SGX), L1 Terminal Fault
check_CVE_2018_3615() {
local cve
cve='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
pstatus green YES
elif [ "$cap_sgx" = 1 ]; then
pstatus red NO
else
pstatus blue N/A
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 [ "$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"
fi
}

View File

@@ -0,0 +1,31 @@
--- 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"

117
src/vulns/CVE-2018-3620.sh Normal file
View File

@@ -0,0 +1,117 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2018-3620, Foreshadow-NG (OS/SMM), L1 Terminal Fault
check_CVE_2018_3620() {
check_cve 'CVE-2018-3620'
}
check_CVE_2018_3620_linux() {
local status sys_interface_available msg pteinv_supported pteinv_active
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "$VULN_SYSFS_BASE/l1tf"; then
# this kernel has the /sys interface, trust it over everything
sys_interface_available=1
status=$ret_sys_interface_check_status
msg=$ret_sys_interface_check_fullmsg
fi
if [ "$opt_sysfs_only" != 1 ]; then
pr_info_nol "* Kernel supports PTE inversion: "
if ! command -v "${opt_arch_prefix}strings" >/dev/null 2>&1; then
pstatus yellow UNKNOWN "missing 'strings' tool, please install it"
pteinv_supported=-1
elif [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "$g_kernel_err"
pteinv_supported=-1
else
if "${opt_arch_prefix}strings" "$g_kernel" | grep -Fq 'PTE Inversion'; then
pstatus green YES "found in kernel image"
pr_debug "pteinv: found pte inversion evidence in kernel image"
pteinv_supported=1
else
pstatus yellow NO
pteinv_supported=0
fi
fi
pr_info_nol "* PTE inversion enabled and active: "
if [ "$g_mode" = live ]; 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
pteinv_active=1
else
pstatus yellow NO
pteinv_active=0
fi
else
pstatus yellow UNKNOWN "sysfs interface not available"
pteinv_active=-1
fi
else
pstatus blue N/A "not testable in no-runtime mode"
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!"
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 [ -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 [ "$pteinv_supported" = 1 ]; then
if [ "$pteinv_active" = 1 ] || [ "$g_mode" != live ]; 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"
fi
else
pvulnstatus "$cve" VULN "Your kernel doesn't support PTE inversion, update it"
fi
else
# --sysfs-only: sysfs was available (otherwise msg would be set), use its result
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
fi
else
# msg was set explicitly: either sysfs-not-available error, or a sysfs override
pvulnstatus "$cve" "$status" "$msg"
fi
}
check_CVE_2018_3620_bsd() {
local bsd_zero_reserved
pr_info_nol "* Kernel reserved the memory page at physical address 0x0: "
if ! kldstat -q -m vmm; then
kldload vmm 2>/dev/null && g_kldload_vmm=1
pr_debug "attempted to load module vmm, g_kldload_vmm=$g_kldload_vmm"
else
pr_debug "vmm module already loaded"
fi
if sysctl hw.vmm.vmx.l1d_flush >/dev/null 2>&1; then
# https://security.FreeBSD.org/patches/SA-18:09/l1tf-11.2.patch
# this is very difficult to detect that the kernel reserved the 0 page, but this fix
# is part of the exact same patch than the other L1TF CVE, so we detect it
# and deem it as OK if the other patch is there
pstatus green YES
bsd_zero_reserved=1
else
pstatus yellow NO
bsd_zero_reserved=0
fi
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
else
if [ "$bsd_zero_reserved" = 1 ]; then
pvulnstatus "$cve" OK "kernel mitigates the vulnerability"
else
pvulnstatus "$cve" VULN "your kernel needs to be updated"
fi
fi
}

195
src/vulns/CVE-2018-3639.sh Normal file
View File

@@ -0,0 +1,195 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2018-3639, Variant 4, SSB, Speculative Store Bypass
check_CVE_2018_3639() {
check_cve 'CVE-2018-3639'
}
check_CVE_2018_3639_linux() {
local status sys_interface_available msg kernel_ssb kernel_ssbd_enabled mitigated_processes
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "$VULN_SYSFS_BASE/spec_store_bypass"; then
# this kernel has the /sys interface, trust it over everything
sys_interface_available=1
status=$ret_sys_interface_check_status
fi
if [ "$opt_sysfs_only" != 1 ]; then
pr_info_nol "* Kernel supports disabling speculative store bypass (SSB): "
if [ "$g_mode" = live ]; 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
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
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
# arm64 only:
if [ -z "$kernel_ssb" ] && [ -n "$opt_map" ]; then
kernel_ssb=$(grep -w cpu_enable_ssbs "$opt_map" | awk '{print $3}' | head -n1)
[ -n "$kernel_ssb" ] && kernel_ssb="found $kernel_ssb in System.map"
fi
if [ -z "$kernel_ssb" ] && [ -n "$opt_config" ]; then
kernel_ssb=$(grep -w 'CONFIG_ARM64_SSBD=y' "$opt_config")
[ -n "$kernel_ssb" ] && kernel_ssb="CONFIG_ARM64_SSBD enabled in kconfig"
fi
if [ -z "$kernel_ssb" ] && [ -n "$g_kernel" ]; then
# this string only appears in kernel if CONFIG_ARM64_SSBD is set
kernel_ssb=$(grep -w "Speculative Store Bypassing Safe (SSBS)" "$g_kernel")
[ -n "$kernel_ssb" ] && kernel_ssb="found 'Speculative Store Bypassing Safe (SSBS)' in kernel"
fi
# /arm64 only
if [ -n "$kernel_ssb" ]; then
pstatus green YES "$kernel_ssb"
else
pstatus yellow NO
fi
kernel_ssbd_enabled=-1
if [ "$g_mode" = live ]; 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
kernel_ssbd_enabled=1
pstatus green YES "per-thread through prctl"
elif grep -Eq 'Speculation.?Store.?Bypass:[[:space:]]+globally mitigated' "$g_procfs/self/status" 2>/dev/null; then
kernel_ssbd_enabled=2
pstatus green YES "global"
elif grep -Eq 'Speculation.?Store.?Bypass:[[:space:]]+vulnerable' "$g_procfs/self/status" 2>/dev/null; then
kernel_ssbd_enabled=0
pstatus yellow NO
elif grep -Eq 'Speculation.?Store.?Bypass:[[:space:]]+not vulnerable' "$g_procfs/self/status" 2>/dev/null; then
kernel_ssbd_enabled=-2
pstatus blue NO "not vulnerable"
elif grep -Eq 'Speculation.?Store.?Bypass:[[:space:]]+unknown' "$g_procfs/self/status" 2>/dev/null; then
kernel_ssbd_enabled=0
pstatus blue NO
else
pstatus blue UNKNOWN "unknown value: $(grep -E 'Speculation.?Store.?Bypass:' "$g_procfs/self/status" 2>/dev/null | cut -d: -f2-)"
fi
if [ "$kernel_ssbd_enabled" = 1 ]; then
pr_info_nol "* SSB mitigation currently active for selected processes: "
# silence grep's stderr here to avoid ENOENT errors from processes that have exited since the shell's expansion of the *
mitigated_processes=$(find /proc -mindepth 2 -maxdepth 2 -type f -name status -print0 2>/dev/null |
xargs -r0 grep -El 'Speculation.?Store.?Bypass:[[:space:]]+thread (force )?mitigated' 2>/dev/null |
sed s/status/exe/ | xargs -r -n1 readlink -f 2>/dev/null | xargs -r -n1 basename | sort -u | tr "\n" " " | sed 's/ $//')
if [ -n "$mitigated_processes" ]; then
pstatus green YES "$mitigated_processes"
else
pstatus yellow NO "no process found using SSB mitigation through prctl"
fi
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!"
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 [ -z "$msg" ] || [ "$msg" = "Vulnerable" ]; then
# 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 [ "$kernel_ssbd_enabled" -gt 0 ]; then
pvulnstatus "$cve" OK "your CPU and kernel both support SSBD and mitigation is enabled"
else
pvulnstatus "$cve" VULN "your CPU and kernel both support SSBD but the mitigation is not active"
fi
else
pvulnstatus "$cve" OK "your system provides the necessary tools for software mitigation"
fi
else
pvulnstatus "$cve" VULN "your kernel needs to be updated"
explain "You have a recent-enough CPU microcode but your kernel is too old to use the new features exported by your CPU's microcode. If you're using a distro kernel, upgrade your distro to get the latest kernel available. Otherwise, recompile the kernel from recent-enough sources."
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
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
fi
fi
else
pvulnstatus "$cve" "$status" "$msg"
fi
}
check_CVE_2018_3639_bsd() {
local kernel_ssb ssb_enabled ssb_active
pr_info_nol "* Kernel supports speculation store bypass: "
if sysctl hw.spec_store_bypass_disable >/dev/null 2>&1; then
kernel_ssb=1
pstatus green YES
else
kernel_ssb=0
pstatus yellow NO
fi
pr_info_nol "* Speculation store bypass is administratively enabled: "
ssb_enabled=$(sysctl -n hw.spec_store_bypass_disable 2>/dev/null)
pr_debug "hw.spec_store_bypass_disable=$ssb_enabled"
case "$ssb_enabled" in
0) pstatus yellow NO "disabled" ;;
1) pstatus green YES "enabled" ;;
2) pstatus green YES "auto mode" ;;
*) pstatus yellow NO "unavailable" ;;
esac
pr_info_nol "* Speculation store bypass is currently active: "
ssb_active=$(sysctl -n hw.spec_store_bypass_disable_active 2>/dev/null)
pr_debug "hw.spec_store_bypass_disable_active=$ssb_active"
case "$ssb_active" in
1) pstatus green YES ;;
*) pstatus yellow NO ;;
esac
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
else
if [ "$ssb_active" = 1 ]; then
pvulnstatus "$cve" OK "SSBD mitigates the vulnerability"
elif [ -n "$cap_ssbd" ]; then
if [ "$kernel_ssb" = 1 ]; then
pvulnstatus "$cve" VULN "you need to enable SSBD through sysctl to mitigate the vulnerability"
explain "To enable SSBD right now, you can run \`sysctl hw.spec_store_bypass_disable=2'. To make this change persistent across reboots, you can add 'sysctl hw.spec_store_bypass_disable=2' to /etc/sysctl.conf."
else
pvulnstatus "$cve" VULN "your kernel needs to be updated"
fi
else
if [ "$kernel_ssb" = 1 ]; then
pvulnstatus "$cve" VULN "Your CPU doesn't support SSBD"
else
pvulnstatus "$cve" VULN "Neither your CPU nor your kernel support SSBD"
fi
fi
fi
}

View File

@@ -0,0 +1,62 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2018-3640, Variant 3a, Rogue System Register Read
check_CVE_2018_3640() {
local status sys_interface_available msg cve arm_v3a_mitigation
cve='CVE-2018-3640'
pr_info "\033[1;34m$cve aka '$(cve2name "$cve")'\033[0m"
status=UNK
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
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
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
fi
}

274
src/vulns/CVE-2018-3646.sh Normal file
View File

@@ -0,0 +1,274 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2018-3646, Foreshadow-NG (VMM), L1 Terminal Fault
check_CVE_2018_3646() {
check_cve 'CVE-2018-3646'
}
check_CVE_2018_3646_linux() {
local status sys_interface_available msg l1d_mode ept_disabled l1d_kernel l1d_kernel_err l1d_xen_hardware l1d_xen_hypervisor l1d_xen_pv_domU smt_enabled
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "$VULN_SYSFS_BASE/l1tf" '.*' quiet; then
# this kernel has the /sys interface, trust it over everything
sys_interface_available=1
# quiet mode doesn't set ret_sys_interface_check_status, derive it ourselves.
#
# Complete sysfs message inventory for l1tf, traced via git blame
# on mainline (~/linux) and stable (~/linux-stable):
#
# all versions:
# "Not affected" (cpu_show_common, d1059518b4789)
# "Vulnerable" (cpu_show_common fallthrough, d1059518b4789)
#
# --- mainline ---
# 17dbca119312 (v4.18-rc1, initial l1tf sysfs):
# "Mitigation: Page Table Inversion"
# 72c6d2db64fa (v4.18-rc1, renamed + added VMX reporting):
# "Mitigation: PTE Inversion" (no KVM_INTEL, or VMX=AUTO)
# "Mitigation: PTE Inversion; VMX: SMT <smt>, L1D <flush>" (KVM_INTEL enabled)
# <flush>: auto | vulnerable | conditional cache flushes | cache flushes
# a7b9020b06ec (v4.18-rc1, added EPT disabled state):
# <flush>: + EPT disabled
# ea156d192f52 (v4.18-rc7, reordered VMX/SMT fields):
# "Mitigation: PTE Inversion; VMX: EPT disabled" (no SMT part)
# "Mitigation: PTE Inversion; VMX: vulnerable" (NEVER + SMT active, no SMT part)
# "Mitigation: PTE Inversion; VMX: <flush>, SMT <smt>" (all other cases)
# 8e0b2b916662 (v4.18, added flush not necessary):
# <flush>: + flush not necessary
# 130d6f946f6f (v4.20-rc4, no string change):
# SMT detection changed from cpu_smt_control to sched_smt_active()
#
# --- stable backports ---
# 4.4.y: no VMX reporting (only "PTE Inversion" / "Vulnerable" / "Not affected").
# initially backported as "Page Table Inversion" (bf0cca01b873),
# renamed to "PTE Inversion" in stable-only commit 6db8c0882912 (May 2019).
# 4.9.y, 4.14.y: full VMX reporting, post-reorder format.
# the pre-reorder format ("SMT <smt>, L1D <flush>") and the post-reorder
# format ("VMX: <flush>, SMT <smt>") landed in the same stable release
# (4.9.120, 4.14.63), so no stable release ever shipped the pre-reorder format.
# sched_smt_active() backported (same strings, different runtime behavior).
# 4.17.y, 4.18.y: full VMX reporting, post-reorder format.
# still uses cpu_smt_control (sched_smt_active() not backported to these EOL branches).
#
# <smt> is one of: vulnerable | disabled
#
# all messages start with either "Not affected", "Mitigation", or "Vulnerable"
if echo "$ret_sys_interface_check_fullmsg" | grep -qEi '^(Not affected|Mitigation)'; then
status=OK
elif echo "$ret_sys_interface_check_fullmsg" | grep -qi '^Vulnerable'; then
status=VULN
fi
fi
l1d_mode=-1
if [ "$opt_sysfs_only" != 1 ]; then
check_has_vmm
pr_info "* Mitigation 1 (KVM)"
pr_info_nol " * EPT is disabled: "
ept_disabled=-1
if [ "$g_mode" = live ]; then
if ! [ -r "$SYS_MODULE_BASE/kvm_intel/parameters/ept" ]; then
pstatus blue N/A "the kvm_intel module is not loaded"
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
fi
else
pstatus blue N/A "not testable in no-runtime 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
l1d_kernel="found flush_l1d in $g_procfs/cpuinfo"
fi
if [ -z "$l1d_kernel" ]; then
if ! command -v "${opt_arch_prefix}strings" >/dev/null 2>&1; then
l1d_kernel_err="missing '${opt_arch_prefix}strings' tool, please install it, usually it's in the binutils package"
elif [ -n "$g_kernel_err" ]; then
l1d_kernel_err="$g_kernel_err"
elif "${opt_arch_prefix}strings" "$g_kernel" | grep -qw flush_l1d; then
l1d_kernel='found flush_l1d in kernel image'
fi
fi
if [ -n "$l1d_kernel" ]; then
pstatus green YES "$l1d_kernel"
elif [ -n "$l1d_kernel_err" ]; then
pstatus yellow UNKNOWN "$l1d_kernel_err"
else
pstatus yellow NO
fi
pr_info_nol " * L1D flush enabled: "
if [ "$g_mode" = live ]; then
if [ -n "$ret_sys_interface_check_fullmsg" ]; then
# vanilla: VMX: $l1dstatus, SMT $smtstatus
# Red Hat: VMX: SMT $smtstatus, L1D $l1dstatus
# $l1dstatus is one of (auto|vulnerable|conditional cache flushes|cache flushes|EPT disabled|flush not necessary)
# $smtstatus is one of (vulnerable|disabled)
# can also just be "Not affected"
if echo "$ret_sys_interface_check_fullmsg" | grep -Eq -e 'Not affected' -e '(VMX:|L1D) (EPT disabled|vulnerable|flush not necessary)'; then
l1d_mode=0
pstatus yellow NO
elif echo "$ret_sys_interface_check_fullmsg" | grep -Eq '(VMX:|L1D) conditional cache flushes'; then
l1d_mode=1
pstatus green YES "conditional flushes"
elif echo "$ret_sys_interface_check_fullmsg" | grep -Eq '(VMX:|L1D) cache flushes'; then
l1d_mode=2
pstatus green YES "unconditional flushes"
else
if is_xen_dom0; then
l1d_xen_hardware=$(xl dmesg 2>/dev/null | grep 'Hardware features:' | grep 'L1D_FLUSH' | head -n1)
l1d_xen_hypervisor=$(xl dmesg 2>/dev/null | grep 'Xen settings:' | grep 'L1D_FLUSH' | head -n1)
l1d_xen_pv_domU=$(xl dmesg 2>/dev/null | grep 'PV L1TF shadowing:' | grep 'DomU enabled' | head -n1)
if [ -n "$l1d_xen_hardware" ] && [ -n "$l1d_xen_hypervisor" ] && [ -n "$l1d_xen_pv_domU" ]; then
l1d_mode=5
pstatus green YES "for XEN guests"
elif [ -n "$l1d_xen_hardware" ] && [ -n "$l1d_xen_hypervisor" ]; then
l1d_mode=4
pstatus yellow YES "for XEN guests (HVM only)"
elif [ -n "$l1d_xen_pv_domU" ]; then
l1d_mode=3
pstatus yellow YES "for XEN guests (PV only)"
else
l1d_mode=0
pstatus yellow NO "for XEN guests"
fi
else
l1d_mode=-1
pstatus yellow UNKNOWN "unrecognized mode"
fi
fi
else
l1d_mode=-1
pstatus yellow UNKNOWN "can't find or read $VULN_SYSFS_BASE/l1tf"
fi
else
l1d_mode=-1
pstatus blue N/A "not testable in no-runtime mode"
fi
pr_info_nol " * Hardware-backed L1D flush supported: "
if [ "$g_mode" = live ]; 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"
fi
pr_info_nol " * Hyper-Threading (SMT) is enabled: "
is_cpu_smt_enabled
smt_enabled=$?
if [ "$smt_enabled" = 0 ]; then
pstatus yellow YES
elif [ "$smt_enabled" = 1 ]; then
pstatus green NO
else
pstatus yellow UNKNOWN
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!"
status=UNK
l1d_mode=-1
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 [ "$ret_sys_interface_check_fullmsg" = "Not affected" ]; then
# just in case a very recent kernel knows better than we do
pvulnstatus "$cve" OK "your kernel reported your CPU model as not affected"
elif [ -z "$msg" ]; then
if [ "$opt_sysfs_only" != 1 ]; then
if [ "$g_has_vmm" = 0 ]; then
pvulnstatus "$cve" OK "this system is not running a hypervisor"
elif [ "$ept_disabled" = 1 ]; then
pvulnstatus "$cve" OK "EPT is disabled which mitigates the vulnerability"
elif [ "$opt_paranoid" = 0 ]; then
if [ "$l1d_mode" -ge 1 ]; then
pvulnstatus "$cve" OK "L1D flushing is enabled and mitigates the vulnerability"
else
pvulnstatus "$cve" VULN "disable EPT or enable L1D flushing to mitigate the vulnerability"
fi
else
if [ "$l1d_mode" -ge 2 ]; then
if [ "$smt_enabled" = 1 ]; then
pvulnstatus "$cve" OK "L1D unconditional flushing and Hyper-Threading disabled are mitigating the vulnerability"
else
pvulnstatus "$cve" VULN "Hyper-Threading must be disabled to fully mitigate the vulnerability"
fi
else
if [ "$smt_enabled" = 1 ]; then
pvulnstatus "$cve" VULN "L1D unconditional flushing should be enabled to fully mitigate the vulnerability"
else
pvulnstatus "$cve" VULN "enable L1D unconditional flushing and disable Hyper-Threading to fully mitigate the vulnerability"
fi
fi
fi
if [ "$l1d_mode" -gt 3 ]; then
pr_warn
pr_warn "This host is a Xen Dom0. Please make sure that you are running your DomUs"
pr_warn "with a kernel which contains CVE-2018-3646 mitigations."
pr_warn
pr_warn "See https://www.suse.com/support/kb/doc/?id=7023078 and XSA-273 for details."
fi
else
# --sysfs-only: sysfs was available (otherwise msg would be set), use its result
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
fi
else
# msg was set explicitly: either sysfs-not-available error, or a sysfs override
pvulnstatus "$cve" "$status" "$msg"
fi
}
check_CVE_2018_3646_bsd() {
local kernel_l1d_supported kernel_l1d_enabled
pr_info_nol "* Kernel supports L1D flushing: "
if sysctl hw.vmm.vmx.l1d_flush >/dev/null 2>&1; then
pstatus green YES
kernel_l1d_supported=1
else
pstatus yellow NO
kernel_l1d_supported=0
fi
pr_info_nol "* L1D flushing is enabled: "
kernel_l1d_enabled=$(sysctl -n hw.vmm.vmx.l1d_flush 2>/dev/null)
case "$kernel_l1d_enabled" in
0) pstatus yellow NO ;;
1) pstatus green YES ;;
"") pstatus yellow NO ;;
*) pstatus yellow UNKNOWN ;;
esac
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
else
if [ "$kernel_l1d_enabled" = 1 ]; then
pvulnstatus "$cve" OK "L1D flushing mitigates the vulnerability"
elif [ "$kernel_l1d_supported" = 1 ]; then
pvulnstatus "$cve" VULN "L1D flushing is supported by your kernel but is disabled"
else
pvulnstatus "$cve" VULN "your kernel needs to be updated"
fi
fi
}

View File

@@ -0,0 +1,7 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2019-11091, MDSUM, RIDL, Microarchitectural Data Sampling Uncacheable Memory
check_CVE_2019_11091() {
check_cve 'CVE-2019-11091' check_mds
}

152
src/vulns/CVE-2019-11135.sh Normal file
View File

@@ -0,0 +1,152 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2019-11135, TAA, ZombieLoad V2, TSX Asynchronous Abort
check_CVE_2019_11135() {
check_cve 'CVE-2019-11135'
}
check_CVE_2019_11135_linux() {
local status sys_interface_available msg kernel_taa kernel_taa_err
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "$VULN_SYSFS_BASE/tsx_async_abort"; then
# this kernel has the /sys interface, trust it over everything
sys_interface_available=1
status=$ret_sys_interface_check_status
fi
if [ "$opt_sysfs_only" != 1 ]; then
pr_info_nol "* TAA mitigation is supported by kernel: "
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
kernel_taa="found tsx_async_abort in kernel image"
fi
if [ -n "$kernel_taa" ]; then
pstatus green YES "$kernel_taa"
elif [ -n "$kernel_taa_err" ]; then
pstatus yellow UNKNOWN "$kernel_taa_err"
else
pstatus yellow NO
fi
pr_info_nol "* TAA mitigation enabled and active: "
if [ "$g_mode" = live ]; 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"
else
pstatus yellow NO
fi
else
pstatus yellow NO "tsx_async_abort not found in sysfs hierarchy"
fi
else
pstatus blue N/A "not testable in no-runtime mode"
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!"
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 [ -z "$msg" ]; then
# if msg is empty, sysfs check didn't fill it, rely on our own test
if [ "$g_mode" = live ]; 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
if [ -n "$kernel_taa" ]; then
pvulnstatus "$cve" OK "Your kernel supports TAA mitigation"
else
pvulnstatus "$cve" VULN "Your kernel doesn't support TAA mitigation, update it"
fi
fi
else
if [ "$opt_paranoid" = 1 ]; then
# in paranoid mode, TSX or SMT enabled are not OK, even if TAA is mitigated
# first check sysfs, then fall back to MSR-based detection for older kernels
# that may not report TSX as disabled even when microcode has done so
tsx_disabled=0
if echo "$ret_sys_interface_check_fullmsg" | grep -qF 'TSX disabled'; then
tsx_disabled=1
elif [ "$cap_tsx_ctrl_rtm_disable" = 1 ] && [ "$cap_tsx_ctrl_cpuid_clear" = 1 ]; then
# TSX disabled via IA32_TSX_CTRL MSR (0x122)
tsx_disabled=1
elif [ "$cap_tsx_force_abort_rtm_disable" = 1 ] && [ "$cap_tsx_force_abort_cpuid_clear" = 1 ]; then
# TSX disabled via IA32_TSX_FORCE_ABORT MSR (0x10F), for older Skylake-era CPUs
tsx_disabled=1
fi
if [ "$tsx_disabled" = 0 ]; then
pvulnstatus "$cve" VULN "TSX must be disabled for full mitigation"
elif echo "$ret_sys_interface_check_fullmsg" | grep -qF 'SMT vulnerable'; then
pvulnstatus "$cve" VULN "SMT (HyperThreading) must be disabled for full mitigation"
else
pvulnstatus "$cve" "$status" "$msg"
fi
else
pvulnstatus "$cve" "$status" "$msg"
fi
fi
}
check_CVE_2019_11135_bsd() {
local taa_enable taa_state mds_disable kernel_taa kernel_mds
pr_info_nol "* Kernel supports TAA mitigation (machdep.mitigations.taa.enable): "
taa_enable=$(sysctl -n machdep.mitigations.taa.enable 2>/dev/null)
if [ -n "$taa_enable" ]; then
kernel_taa=1
case "$taa_enable" in
0) pstatus yellow YES "disabled" ;;
1) pstatus green YES "TSX disabled via MSR" ;;
2) pstatus green YES "VERW mitigation" ;;
3) pstatus green YES "auto" ;;
*) pstatus yellow YES "unknown value: $taa_enable" ;;
esac
else
kernel_taa=0
pstatus yellow NO
fi
pr_info_nol "* TAA mitigation state: "
taa_state=$(sysctl -n machdep.mitigations.taa.state 2>/dev/null)
if [ -n "$taa_state" ]; then
if echo "$taa_state" | grep -qi 'not.affected\|mitigation'; then
pstatus green YES "$taa_state"
else
pstatus yellow NO "$taa_state"
fi
else
# fallback: TAA is also mitigated by MDS VERW if enabled
mds_disable=$(sysctl -n hw.mds_disable 2>/dev/null)
if [ -z "$mds_disable" ]; then
mds_disable=$(sysctl -n machdep.mitigations.mds.disable 2>/dev/null)
fi
if [ -n "$mds_disable" ] && [ "$mds_disable" != 0 ]; then
kernel_mds=1
pstatus green YES "MDS VERW mitigation active (also covers TAA)"
else
kernel_mds=0
pstatus yellow NO "no TAA or MDS sysctl found"
fi
fi
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif [ "$kernel_taa" = 1 ] && [ "$taa_enable" != 0 ]; then
pvulnstatus "$cve" OK "TAA mitigation is enabled"
elif [ "$kernel_mds" = 1 ]; then
pvulnstatus "$cve" OK "MDS VERW mitigation is active and also covers TAA"
elif [ "$kernel_taa" = 1 ] && [ "$taa_enable" = 0 ]; then
pvulnstatus "$cve" VULN "TAA mitigation is supported but disabled"
explain "To enable TAA mitigation, run \`sysctl machdep.mitigations.taa.enable=3' for auto mode.\n " \
"To make this persistent, add 'machdep.mitigations.taa.enable=3' to /etc/sysctl.conf."
else
pvulnstatus "$cve" VULN "your kernel doesn't support TAA mitigation, update it"
fi
}

145
src/vulns/CVE-2020-0543.sh Normal file
View File

@@ -0,0 +1,145 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2020-0543, SRBDS, CROSSTalk, Special Register Buffer Data Sampling
check_CVE_2020_0543() {
check_cve 'CVE-2020-0543'
}
check_CVE_2020_0543_linux() {
local status sys_interface_available msg kernel_srbds kernel_srbds_err
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "$VULN_SYSFS_BASE/srbds"; then
# this kernel has the /sys interface, trust it over everything
sys_interface_available=1
status=$ret_sys_interface_check_status
fi
if [ "$opt_sysfs_only" != 1 ]; then
pr_info_nol "* SRBDS mitigation control is supported by the kernel: "
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
kernel_srbds="found SRBDS implementation evidence in kernel image. Your kernel is up to date for SRBDS mitigation"
fi
if [ -n "$kernel_srbds" ]; then
pstatus green YES "$kernel_srbds"
elif [ -n "$kernel_srbds_err" ]; then
pstatus yellow UNKNOWN "$kernel_srbds_err"
else
pstatus yellow NO
fi
pr_info_nol "* SRBDS mitigation control is enabled and active: "
if [ "$g_mode" = live ]; 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"
else
pstatus yellow NO
fi
else
pstatus yellow NO "SRBDS not found in sysfs hierarchy"
fi
else
pstatus blue N/A "not testable in no-runtime mode"
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!"
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"
else
if [ "$opt_sysfs_only" != 1 ]; then
if [ "$cap_srbds" = 1 ]; then
# SRBDS mitigation control exists
if [ "$cap_srbds_on" = 1 ]; then
# 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 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
else
if [ -n "$kernel_srbds" ]; then
pvulnstatus "$cve" OK "Your microcode and kernel are both up to date for SRBDS mitigation control. Mitigation is enabled"
else
pvulnstatus "$cve" OK "Your microcode is up to date for SRBDS mitigation control. The kernel needs to be updated"
fi
fi
elif [ "$cap_srbds_on" = 0 ]; then
# SRBDS mitigation control is disabled
if [ -z "$msg" ]; then
if [ "$g_mode" = live ]; 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
else
if [ -n "$kernel_srbds" ]; then
pvulnstatus "$cve" VULN "Your microcode and kernel are both up to date for SRBDS mitigation control. Mitigation is disabled"
else
pvulnstatus "$cve" VULN "Your microcode is up to date for SRBDS mitigation control. The kernel needs to be updated. Mitigation is disabled"
fi
fi
else
# rdmsr: CPU 0 cannot read MSR 0x00000123
pvulnstatus "$cve" UNK "Not able to enumerate MSR for SRBDS mitigation control"
fi
else
# [ $cap_srbds != 1 ]
pvulnstatus "$cve" VULN "Your CPU microcode may need to be updated to mitigate the vulnerability"
fi
else
# sysfs only: return the status/msg we got
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
return
fi
fi
}
# FreeBSD uses the name "rngds" (Random Number Generator Data Sampling) for SRBDS
check_CVE_2020_0543_bsd() {
local rngds_enable rngds_state kernel_rngds
pr_info_nol "* Kernel supports SRBDS mitigation (machdep.mitigations.rngds.enable): "
rngds_enable=$(sysctl -n machdep.mitigations.rngds.enable 2>/dev/null)
if [ -n "$rngds_enable" ]; then
kernel_rngds=1
case "$rngds_enable" in
0) pstatus yellow YES "optimized (RDRAND/RDSEED not locked, faster but vulnerable)" ;;
1) pstatus green YES "mitigated" ;;
*) pstatus yellow YES "unknown value: $rngds_enable" ;;
esac
else
kernel_rngds=0
pstatus yellow NO
fi
pr_info_nol "* SRBDS mitigation state: "
rngds_state=$(sysctl -n machdep.mitigations.rngds.state 2>/dev/null)
if [ -n "$rngds_state" ]; then
if echo "$rngds_state" | grep -qi 'not.affected\|mitigat'; then
pstatus green YES "$rngds_state"
else
pstatus yellow NO "$rngds_state"
fi
else
pstatus yellow NO "sysctl not available"
fi
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif [ "$kernel_rngds" = 1 ] && [ "$rngds_enable" = 1 ]; then
pvulnstatus "$cve" OK "SRBDS mitigation is enabled"
elif [ "$kernel_rngds" = 1 ] && [ "$rngds_enable" = 0 ]; then
pvulnstatus "$cve" VULN "SRBDS mitigation is supported but set to optimized mode (disabled for RDRAND/RDSEED)"
explain "To enable full SRBDS mitigation, run \`sysctl machdep.mitigations.rngds.enable=1'.\n " \
"To make this persistent, add 'machdep.mitigations.rngds.enable=1' to /etc/sysctl.conf."
else
pvulnstatus "$cve" VULN "your kernel doesn't support SRBDS mitigation, update it"
fi
}

View File

@@ -0,0 +1,7 @@
# 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

@@ -0,0 +1,7 @@
# 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

@@ -0,0 +1,7 @@
# 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
}

254
src/vulns/CVE-2022-29900.sh Normal file
View File

@@ -0,0 +1,254 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2022-29900, Retbleed (AMD), Arbitrary Speculative Code Execution with Return Instructions
check_CVE_2022_29900() {
check_cve 'CVE-2022-29900'
}
check_CVE_2022_29900_linux() {
local status sys_interface_available msg kernel_retbleed kernel_retbleed_err kernel_unret kernel_ibpb_entry smt_enabled
status=UNK
sys_interface_available=0
msg=''
#
# Kernel source inventory for retbleed (CVE-2022-29900 / CVE-2022-29901)
#
# --- sysfs messages ---
# all versions:
# "Not affected" (cpu_show_common, pre-existing)
#
# --- mainline ---
# 6b80b59b3555 (v5.19-rc7, initial retbleed sysfs):
# "Vulnerable\n" (hardcoded, no enum yet)
# 7fbf47c7ce50 (v5.19-rc7, retbleed= boot parameter):
# "Vulnerable" (RETBLEED_MITIGATION_NONE)
# "Mitigation: untrained return thunk" (RETBLEED_MITIGATION_UNRET)
# "Vulnerable: untrained return thunk on non-Zen uarch" (UNRET on non-AMD/Hygon)
# 6ad0ad2bf8a6 (v5.19-rc7, Intel mitigations):
# "Mitigation: IBRS" (RETBLEED_MITIGATION_IBRS)
# "Mitigation: Enhanced IBRS" (RETBLEED_MITIGATION_EIBRS)
# 3ebc17006888 (v5.19-rc7, retbleed=ibpb):
# "Mitigation: IBPB" (RETBLEED_MITIGATION_IBPB)
# e8ec1b6e08a2 (v5.19-rc7, STIBP for JMP2RET):
# UNRET now appends SMT status:
# "Mitigation: untrained return thunk; SMT disabled"
# "Mitigation: untrained return thunk; SMT enabled with STIBP protection"
# "Mitigation: untrained return thunk; SMT vulnerable"
# e6cfcdda8cbe (v6.0-rc1, STIBP for IBPB):
# IBPB now appends SMT status, non-AMD message changed:
# "Vulnerable: untrained return thunk / IBPB on non-AMD based uarch"
# "Mitigation: IBPB; SMT disabled"
# "Mitigation: IBPB; SMT enabled with STIBP protection"
# "Mitigation: IBPB; SMT vulnerable"
# d82a0345cf21 (v6.2-rc1, call depth tracking):
# "Mitigation: Stuffing" (RETBLEED_MITIGATION_STUFF)
# e3b78a7ad5ea (v6.16-rc1, restructure):
# added RETBLEED_MITIGATION_AUTO (internal, resolved before display)
# no new sysfs strings
#
# all messages start with either "Not affected", "Vulnerable", or "Mitigation"
#
# --- stable backports ---
# 4.14.y, 4.19.y, 5.4.y: Intel-only mitigations (IBRS, eIBRS); no UNRET, IBPB, STUFF;
# no SMT status display; simplified retbleed_show_state().
# 5.10.y, 5.15.y, 6.1.y: full mitigations (NONE, UNRET, IBPB, IBRS, EIBRS);
# SMT status appended for UNRET/IBPB; no STUFF.
# 6.6.y, 6.12.y: adds STUFF (call depth tracking). 6.12.y uses INTEL_ model prefix.
# all stable: single retbleed_select_mitigation() (no update/apply split).
#
# --- RHEL/CentOS ---
# centos7 (~4.18): NONE, UNRET, IBPB, IBRS, EIBRS; no STUFF; SMT status for UNRET;
# no Hygon check; no UNRET_ENTRY/IBPB_ENTRY/IBRS_ENTRY Kconfig symbols;
# unique cpu_in_retbleed_whitelist() function for Intel.
# rocky8 (~4.18/5.14): NONE, UNRET, IBPB, IBRS, EIBRS; no STUFF;
# CONFIG_CPU_UNRET_ENTRY, CONFIG_CPU_IBPB_ENTRY, CONFIG_CPU_IBRS_ENTRY (old names).
# rocky9 (~6.x): same as mainline; CONFIG_MITIGATION_* names; has STUFF.
# rocky10 (~6.12+): same as mainline; has select/update/apply split.
#
# --- Kconfig symbols ---
# f43b9876e857 (v5.19-rc7): CONFIG_CPU_UNRET_ENTRY, CONFIG_CPU_IBPB_ENTRY,
# CONFIG_CPU_IBRS_ENTRY
# 80e4c1cd42ff (v6.2-rc1): CONFIG_CALL_DEPTH_TRACKING
# ac61d43983a4 (v6.9-rc1): renamed to CONFIG_MITIGATION_UNRET_ENTRY,
# CONFIG_MITIGATION_IBPB_ENTRY, CONFIG_MITIGATION_IBRS_ENTRY,
# CONFIG_MITIGATION_CALL_DEPTH_TRACKING
# 894e28857c11 (v6.12-rc1): CONFIG_MITIGATION_RETBLEED (master switch)
#
# --- kernel functions (for $opt_map / System.map) ---
# 7fbf47c7ce50 (v5.19-rc7): retbleed_select_mitigation()
# e3b78a7ad5ea (v6.16-rc1): split into retbleed_select_mitigation() +
# retbleed_update_mitigation() + retbleed_apply_mitigation()
# vendor kernels: centos7/rocky8/rocky9 have retbleed_select_mitigation() only;
# rocky10 has the full split.
#
# --- CPU affection logic (for is_cpu_affected) ---
# X86_BUG_RETBLEED is set when X86_FEATURE_BTC_NO is NOT set AND either:
# (a) CPU matches cpu_vuln_blacklist[] RETBLEED entries, OR
# (b) ARCH_CAP_RSBA is set in IA32_ARCH_CAPABILITIES MSR
# 6b80b59b3555 (v5.19-rc7, initial AMD):
# AMD: family 0x15, 0x16, 0x17; Hygon: family 0x18
# 6ad0ad2bf8a6 (v5.19-rc7, Intel):
# Intel: SKYLAKE_L, SKYLAKE, SKYLAKE_X, KABYLAKE_L, KABYLAKE,
# ICELAKE_L, COMETLAKE, COMETLAKE_L, LAKEFIELD, ROCKETLAKE
# + any Intel with ARCH_CAP_RSBA set
# 26aae8ccbc19 (v5.19-rc7, BTC_NO):
# AMD Zen 3+ with BTC_NO are excluded
# f54d45372c6a (post-v5.19, Cannon Lake):
# Intel: + CANNONLAKE_L
# immunity: X86_FEATURE_BTC_NO (AMD) — Zen 3+ declare not affected
# vendor scope: AMD (0x15-0x17), Hygon (0x18), Intel (Skylake through Rocket Lake + RSBA)
#
if sys_interface_check "$VULN_SYSFS_BASE/retbleed"; then
# this kernel has the /sys interface, trust it over everything
sys_interface_available=1
status=$ret_sys_interface_check_status
fi
if [ "$opt_sysfs_only" != 1 ]; then
pr_info_nol "* Kernel supports mitigation: "
if [ -n "$g_kernel_err" ]; then
kernel_retbleed_err="$g_kernel_err"
elif grep -q 'retbleed' "$g_kernel"; then
kernel_retbleed="found retbleed mitigation logic in kernel image"
fi
if [ -z "$kernel_retbleed" ] && [ -n "$opt_map" ]; then
if grep -q 'retbleed_select_mitigation' "$opt_map"; then
kernel_retbleed="found retbleed_select_mitigation in System.map"
fi
fi
if [ -n "$kernel_retbleed" ]; then
pstatus green YES "$kernel_retbleed"
elif [ -n "$kernel_retbleed_err" ]; then
pstatus yellow UNKNOWN "$kernel_retbleed_err"
else
pstatus yellow NO
fi
pr_info_nol "* Kernel compiled with UNRET_ENTRY support (untrained return thunk): "
if [ -r "$opt_config" ]; then
# CONFIG_CPU_UNRET_ENTRY: Linux < 6.9
# CONFIG_MITIGATION_UNRET_ENTRY: Linux >= 6.9
if grep -Eq '^CONFIG_(CPU|MITIGATION)_UNRET_ENTRY=y' "$opt_config"; then
pstatus green YES
kernel_unret="CONFIG_(CPU|MITIGATION)_UNRET_ENTRY=y found in kernel config"
else
pstatus yellow NO
fi
else
if [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "$g_kernel_err"
elif [ -n "$kernel_retbleed" ]; then
# if the kernel has retbleed logic, assume UNRET_ENTRY is likely compiled in
# (we can't tell for certain without the config)
kernel_unret="retbleed mitigation logic present in kernel (UNRET_ENTRY status unknown)"
pstatus yellow UNKNOWN "kernel has retbleed mitigation but config not available to verify"
else
pstatus yellow NO "your kernel is too old and doesn't have the retbleed mitigation logic"
fi
fi
pr_info_nol "* Kernel compiled with IBPB_ENTRY support: "
if [ -r "$opt_config" ]; then
# CONFIG_CPU_IBPB_ENTRY: Linux < 6.9
# CONFIG_MITIGATION_IBPB_ENTRY: Linux >= 6.9
if grep -Eq '^CONFIG_(CPU|MITIGATION)_IBPB_ENTRY=y' "$opt_config"; then
pstatus green YES
kernel_ibpb_entry="CONFIG_(CPU|MITIGATION)_IBPB_ENTRY=y found in kernel config"
else
pstatus yellow NO
fi
else
if [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "$g_kernel_err"
elif [ -n "$kernel_retbleed" ]; then
kernel_ibpb_entry="retbleed mitigation logic present in kernel (IBPB_ENTRY status unknown)"
pstatus yellow UNKNOWN "kernel has retbleed mitigation but config not available to verify"
else
pstatus yellow NO "your kernel is too old and doesn't have the retbleed mitigation logic"
fi
fi
# 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 [ -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"
fi
pr_info_nol "* Hyper-Threading (SMT) is enabled: "
is_cpu_smt_enabled
smt_enabled=$?
if [ "$smt_enabled" = 0 ]; then
pstatus yellow YES
else
pstatus green 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!"
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 [ -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 [ "$cpu_family" = $((0x17)) ]; then
# Zen/Zen+/Zen2
if [ -z "$kernel_retbleed" ]; then
pvulnstatus "$cve" VULN "Your kernel is too old and doesn't have the retbleed mitigation logic"
elif [ "$opt_paranoid" = 1 ] && [ "$smt_enabled" = 0 ]; then
pvulnstatus "$cve" VULN "SMT is enabled, which weakens the IBPB-based mitigation"
explain "For Zen/Zen+/Zen2 CPUs in paranoid mode, proper mitigation needs SMT to be disabled\n" \
"(this can be done by adding \`nosmt\` to your kernel command line), because IBPB alone\n" \
"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
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."
else
pvulnstatus "$cve" OK "Your kernel and CPU support mitigation"
fi
elif [ "$cpu_family" = $((0x15)) ] || [ "$cpu_family" = $((0x16)) ]; then
# older AMD families: basic mitigation check
if [ -z "$kernel_retbleed" ]; then
pvulnstatus "$cve" VULN "Your kernel is too old and doesn't have the retbleed mitigation logic"
elif [ -n "$kernel_unret" ] || [ -n "$kernel_ibpb_entry" ]; then
pvulnstatus "$cve" OK "Your kernel supports mitigation"
else
pvulnstatus "$cve" VULN "Your kernel doesn't have UNRET_ENTRY or IBPB_ENTRY compiled-in"
fi
else
# not supposed to happen
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
fi
else
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
fi
else
pvulnstatus "$cve" "$status" "$msg"
fi
}
check_CVE_2022_29900_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
}

157
src/vulns/CVE-2022-29901.sh Normal file
View File

@@ -0,0 +1,157 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2022-29901, Retbleed (Intel), RSB Alternate Behavior (RSBA)
check_CVE_2022_29901() {
check_cve 'CVE-2022-29901'
}
check_CVE_2022_29901_linux() {
local status sys_interface_available msg kernel_retbleed kernel_retbleed_err kernel_ibrs_entry
status=UNK
sys_interface_available=0
msg=''
#
# Kernel source inventory for retbleed (CVE-2022-29900 / CVE-2022-29901)
#
# See CVE-2022-29900.sh for the full sysfs/Kconfig/function/stable/vendor inventory.
#
# Intel-specific notes:
# - eIBRS (IBRS_ALL) mitigates the vulnerability on Intel
# - plain retpoline does NOT mitigate on RSBA-capable CPUs (Retbleed bypasses retpoline)
# - IBRS entry also mitigates
# - call depth tracking / stuffing mitigates (v6.2+)
#
# --- Kconfig symbols (Intel-relevant) ---
# CONFIG_CPU_IBRS_ENTRY (< 6.9) / CONFIG_MITIGATION_IBRS_ENTRY (>= 6.9): Intel IBRS
# CONFIG_CALL_DEPTH_TRACKING (< 6.9) / CONFIG_MITIGATION_CALL_DEPTH_TRACKING (>= 6.9): stuffing
#
# --- CPU affection logic (Intel) ---
# 6ad0ad2bf8a6 (v5.19-rc7, initial Intel list):
# SKYLAKE_L, SKYLAKE, SKYLAKE_X, KABYLAKE_L, KABYLAKE,
# ICELAKE_L, COMETLAKE, COMETLAKE_L, LAKEFIELD, ROCKETLAKE
# f54d45372c6a (post-v5.19): + CANNONLAKE_L
# + any Intel with ARCH_CAP_RSBA set in IA32_ARCH_CAPABILITIES MSR (bit 2)
# immunity: none (no _NO bit for RETBLEED on Intel; eIBRS is a mitigation, not immunity)
#
if sys_interface_check "$VULN_SYSFS_BASE/retbleed"; then
# this kernel has the /sys interface, trust it over everything
sys_interface_available=1
status=$ret_sys_interface_check_status
fi
if [ "$opt_sysfs_only" != 1 ]; then
pr_info_nol "* Kernel supports mitigation: "
if [ -n "$g_kernel_err" ]; then
kernel_retbleed_err="$g_kernel_err"
elif grep -q 'retbleed' "$g_kernel"; then
kernel_retbleed="found retbleed mitigation logic in kernel image"
fi
if [ -z "$kernel_retbleed" ] && [ -n "$opt_map" ]; then
if grep -q 'retbleed_select_mitigation' "$opt_map"; then
kernel_retbleed="found retbleed_select_mitigation in System.map"
fi
fi
if [ -n "$kernel_retbleed" ]; then
pstatus green YES "$kernel_retbleed"
elif [ -n "$kernel_retbleed_err" ]; then
pstatus yellow UNKNOWN "$kernel_retbleed_err"
else
pstatus yellow NO
fi
pr_info_nol "* Kernel compiled with IBRS_ENTRY support: "
if [ -r "$opt_config" ]; then
# CONFIG_CPU_IBRS_ENTRY: Linux < 6.9
# CONFIG_MITIGATION_IBRS_ENTRY: Linux >= 6.9
if grep -Eq '^CONFIG_(CPU|MITIGATION)_IBRS_ENTRY=y' "$opt_config"; then
pstatus green YES
kernel_ibrs_entry="CONFIG_(CPU|MITIGATION)_IBRS_ENTRY=y found in kernel config"
else
pstatus yellow NO
fi
else
if [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "$g_kernel_err"
elif [ -n "$kernel_retbleed" ]; then
kernel_ibrs_entry="retbleed mitigation logic present in kernel (IBRS_ENTRY status unknown)"
pstatus yellow UNKNOWN "kernel has retbleed mitigation but config not available to verify"
else
pstatus yellow NO "your kernel is too old and doesn't have the retbleed mitigation logic"
fi
fi
pr_info_nol "* CPU supports Enhanced IBRS (IBRS_ALL): "
if [ "$g_mode" = live ] || [ "$cap_ibrs_all" != -1 ]; then
if [ "$cap_ibrs_all" = 1 ]; then
pstatus green YES
elif [ "$cap_ibrs_all" = 0 ]; then
pstatus yellow NO
else
pstatus yellow UNKNOWN
fi
else
pstatus blue N/A "not testable in no-runtime mode"
fi
pr_info_nol "* CPU has RSB Alternate Behavior (RSBA): "
if [ "$g_mode" = live ] || [ "$cap_rsba" != -1 ]; then
if [ "$cap_rsba" = 1 ]; then
pstatus yellow YES "this CPU is affected by RSB underflow"
elif [ "$cap_rsba" = 0 ]; then
pstatus green NO
else
pstatus yellow UNKNOWN
fi
else
pstatus blue N/A "not testable in no-runtime mode"
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!"
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 [ -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 [ -z "$kernel_retbleed" ]; then
pvulnstatus "$cve" VULN "Your kernel is too old and doesn't have the retbleed mitigation logic"
elif [ "$cap_ibrs_all" = 1 ]; then
if [ "$opt_paranoid" = 1 ] && [ "$cap_rrsba" = 1 ]; then
pvulnstatus "$cve" VULN "eIBRS is enabled but RRSBA is present, which may weaken the mitigation"
explain "In paranoid mode, the combination of eIBRS and RRSBA (Restricted RSB Alternate Behavior)\n" \
"is flagged because RRSBA means the RSB can still be influenced in some scenarios.\n" \
"Check if your firmware/kernel supports disabling RRSBA via RRSBA_CTRL."
else
pvulnstatus "$cve" OK "Enhanced IBRS (IBRS_ALL) mitigates the vulnerability"
fi
elif [ -n "$kernel_ibrs_entry" ]; then
pvulnstatus "$cve" OK "Your kernel has IBRS_ENTRY mitigation compiled-in"
else
pvulnstatus "$cve" VULN "Your kernel has retbleed mitigation but IBRS_ENTRY is not compiled-in and eIBRS is not available"
explain "Retpoline alone does NOT mitigate Retbleed on RSBA-capable Intel CPUs.\n" \
"You need either Enhanced IBRS (eIBRS, via firmware/microcode update) or a kernel\n" \
"compiled with IBRS_ENTRY support (Linux 5.19+, CONFIG_(CPU|MITIGATION)_IBRS_ENTRY)."
fi
else
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
fi
else
pvulnstatus "$cve" "$status" "$msg"
fi
}
check_CVE_2022_29901_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
}

229
src/vulns/CVE-2022-40982.sh Normal file
View File

@@ -0,0 +1,229 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2022-40982, Downfall, GDS, Gather Data Sampling
check_CVE_2022_40982() {
check_cve 'CVE-2022-40982'
}
check_CVE_2022_40982_linux() {
local status sys_interface_available msg kernel_gds kernel_gds_err kernel_avx_disabled dmesgret ret
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "$VULN_SYSFS_BASE/gather_data_sampling"; then
# this kernel has the /sys interface, trust it over everything
sys_interface_available=1
#
# Kernel source inventory for gather_data_sampling (GDS/Downfall)
#
# --- sysfs messages ---
# all versions:
# "Not affected" (cpu_show_common, pre-existing)
#
# --- mainline ---
# 8974eb588283 (v6.5-rc6, initial GDS sysfs):
# "Vulnerable" (GDS_MITIGATION_OFF)
# "Vulnerable: No microcode" (GDS_MITIGATION_UCODE_NEEDED)
# "Mitigation: Microcode" (GDS_MITIGATION_FULL)
# "Mitigation: Microcode (locked)" (GDS_MITIGATION_FULL_LOCKED)
# "Unknown: Dependent on hypervisor status" (GDS_MITIGATION_HYPERVISOR)
# 553a5c03e90a (v6.5-rc6, added force option):
# "Mitigation: AVX disabled, no microcode" (GDS_MITIGATION_FORCE)
# 53cf5797f114 (v6.5-rc6, added CONFIG_GDS_FORCE_MITIGATION):
# no string changes; default becomes FORCE when Kconfig enabled
# 81ac7e5d7417 (v6.5-rc6, KVM GDS_NO plumbing):
# no string changes
# be83e809ca67 (v6.9-rc1, Kconfig rename):
# no string changes; CONFIG_GDS_FORCE_MITIGATION => CONFIG_MITIGATION_GDS_FORCE
# 03267a534bb3 (v6.12-rc1, removed force Kconfig):
# no string changes; CONFIG_MITIGATION_GDS_FORCE removed
# 225f2bd064c3 (v6.12-rc1, added on/off Kconfig):
# no string changes; added CONFIG_MITIGATION_GDS (default y)
# 9dcad2fb31bd (v6.16-rc1, restructured select/apply):
# no string changes; added GDS_MITIGATION_AUTO (internal, resolved before display)
# split gds_select_mitigation() + gds_apply_mitigation()
# d4932a1b148b (v6.17-rc3, bug fix):
# no string changes; CPUs without ARCH_CAP_GDS_CTRL were incorrectly classified
# as OFF ("Vulnerable") instead of UCODE_NEEDED ("Vulnerable: No microcode"),
# and locked-mitigation detection was skipped.
# NOT backported to any stable or RHEL branch as of 2026-04.
#
# --- stable backports ---
# 5.4.y, 5.10.y, 5.15.y, 6.1.y, 6.6.y: same 7 strings as mainline.
# use CONFIG_GDS_FORCE_MITIGATION; no GDS_MITIGATION_AUTO enum;
# missing d4932a1b148b bug fix (UCODE_NEEDED vs OFF misclassification).
# 6.12.y: same 7 strings as mainline.
# uses CONFIG_MITIGATION_GDS; no GDS_MITIGATION_AUTO enum;
# missing d4932a1b148b bug fix.
#
# --- RHEL/CentOS ---
# centos7 (3.10), rocky8 (4.18): same 7 strings; CONFIG_GDS_FORCE_MITIGATION.
# centos7 uses sprintf (not sysfs_emit) and __read_mostly.
# rocky9 (5.14): same 7 strings; CONFIG_MITIGATION_GDS (skipped FORCE rename).
# rocky10 (6.12): same 7 strings; CONFIG_MITIGATION_GDS; has gds_apply_mitigation().
#
# --- Kconfig symbols ---
# 53cf5797f114 (v6.5-rc6): CONFIG_GDS_FORCE_MITIGATION (default n)
# be83e809ca67 (v6.9-rc1): renamed to CONFIG_MITIGATION_GDS_FORCE
# 03267a534bb3 (v6.12-rc1): CONFIG_MITIGATION_GDS_FORCE removed
# 225f2bd064c3 (v6.12-rc1): CONFIG_MITIGATION_GDS (default y)
# vendor kernels: rocky9 uses CONFIG_MITIGATION_GDS on 5.14-based kernel
#
# --- kernel functions (for $opt_map / System.map) ---
# 8974eb588283 (v6.5-rc6): gds_select_mitigation(), update_gds_msr(),
# gds_parse_cmdline(), gds_show_state()
# 81ac7e5d7417 (v6.5-rc6): gds_ucode_mitigated() (exported for KVM)
# 9dcad2fb31bd (v6.16-rc1): split into gds_select_mitigation() + gds_apply_mitigation()
# stable 5.4.y-6.12.y: same 5 functions (no gds_apply_mitigation)
# rocky10 (6.12): has gds_apply_mitigation()
#
# --- CPU affection logic (for is_cpu_affected) ---
# X86_BUG_GDS is set when ALL three conditions are true:
# 1. CPU matches model blacklist (cpu_vuln_blacklist[] in common.c)
# 2. ARCH_CAP_GDS_NO (bit 26 of IA32_ARCH_CAPABILITIES) is NOT set
# 3. X86_FEATURE_AVX is present (GATHER instructions require AVX)
# 8974eb588283 (v6.5-rc6, initial model list):
# Intel: SKYLAKE_X, KABYLAKE_L, KABYLAKE, ICELAKE_L, ICELAKE_D,
# ICELAKE_X, COMETLAKE, COMETLAKE_L, TIGERLAKE_L, TIGERLAKE,
# ROCKETLAKE (all steppings)
# c9f4c45c8ec3 (v6.5-rc6, added missing client Skylake):
# Intel: + SKYLAKE_L, SKYLAKE
# 159013a7ca18 (v6.10-rc1, ITS stepping splits):
# no GDS model changes; some entries split by stepping for ITS but
# GDS flag remains on all stepping ranges for these models
# immunity: ARCH_CAP_GDS_NO (bit 26 of IA32_ARCH_CAPABILITIES)
# feature dependency: requires AVX (if AVX absent, CPU is immune)
# vendor scope: Intel only
#
# all messages start with either "Not affected", "Vulnerable", "Mitigation",
# or "Unknown"
status=$ret_sys_interface_check_status
fi
if [ "$opt_sysfs_only" != 1 ]; then
pr_info_nol "* GDS is mitigated by microcode: "
if [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 0 ]; then
pstatus green OK "microcode mitigation is supported and enabled"
elif [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 1 ]; then
pstatus yellow NO "microcode mitigation is supported but disabled"
elif [ "$cap_gds_ctrl" = 0 ]; then
pstatus yellow NO "microcode doesn't support GDS mitigation"
else
pstatus yellow UNKNOWN "couldn't read MSR for GDS capability"
fi
pr_info_nol "* Kernel supports software mitigation by disabling AVX: "
kernel_gds=''
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
kernel_gds="found gather_data_sampling in kernel image"
fi
if [ -z "$kernel_gds" ] && is_x86_kernel && [ -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 grep -q 'gds_select_mitigation' "$opt_map"; then
kernel_gds="found gds_select_mitigation in System.map"
fi
fi
if [ -n "$kernel_gds" ]; then
pstatus green YES "$kernel_gds"
elif [ -n "$kernel_gds_err" ]; then
pstatus yellow UNKNOWN "$kernel_gds_err"
else
pstatus yellow NO
fi
if [ -n "$kernel_gds" ]; then
pr_info_nol "* Kernel has disabled AVX as a mitigation: "
if [ "$g_mode" = live ]; 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
# Find out by ourselves
# cpuinfo says we don't have AVX2, query
# the CPU directly about AVX2 support (x86-only)
read_cpuid 0x7 0x0 "$EBX" 5 1 1
ret=$?
if [ "$ret" -eq "$READ_CPUID_RET_OK" ]; then
kernel_avx_disabled="AVX disabled by the kernel (cpuid)"
pstatus green YES "$kernel_avx_disabled"
elif [ "$ret" -eq "$READ_CPUID_RET_KO" ]; then
pstatus yellow NO "CPU doesn't support AVX"
elif [ "$dmesgret" -eq 2 ]; then
pstatus yellow UNKNOWN "dmesg truncated, can't tell whether mitigation is active, please reboot and relaunch this script"
else
pstatus yellow UNKNOWN "No sign of mitigation in dmesg and couldn't read cpuid info"
fi
else
pstatus yellow NO "AVX support is enabled"
fi
else
pstatus blue N/A "not testable in no-runtime mode"
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!"
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 [ -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 [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 0 ]; then
if [ "$opt_paranoid" = 1 ] && [ "$cap_gds_mitg_lock" != 1 ]; then
pvulnstatus "$cve" VULN "Microcode mitigation is enabled but not locked"
explain "In paranoid mode, the GDS mitigation must be locked to prevent a privileged attacker\n " \
"(e.g. in a guest VM) from disabling it. Check your firmware/BIOS for an option to lock the\n " \
"GDS mitigation, or update your microcode."
else
pvulnstatus "$cve" OK "Your microcode is up to date and mitigation is enabled"
fi
elif [ "$cap_gds_ctrl" = 1 ] && [ "$cap_gds_mitg_dis" = 1 ]; then
pvulnstatus "$cve" VULN "Your microcode is up to date but mitigation is disabled"
explain "The GDS mitigation has been explicitly disabled (gather_data_sampling=off or mitigations=off).\n " \
"Remove the kernel parameter to re-enable it."
elif [ -z "$kernel_gds" ]; then
pvulnstatus "$cve" VULN "Your microcode doesn't mitigate the vulnerability, and your kernel doesn't support mitigation"
explain "Update both your CPU microcode (via BIOS/firmware update from your OEM) and your kernel\n " \
"to a version that supports GDS mitigation (Linux 6.5+, or check if your distro has a backport)."
elif [ -z "$kernel_avx_disabled" ]; then
pvulnstatus "$cve" VULN "Your microcode doesn't mitigate the vulnerability, your kernel supports the mitigation but AVX was not disabled"
explain "Update your CPU microcode (via BIOS/firmware update from your OEM). If no microcode update\n " \
"is available, use gather_data_sampling=force on the kernel command line to disable AVX as a workaround."
else
pvulnstatus "$cve" OK "Your microcode doesn't mitigate the vulnerability, but your kernel has disabled AVX support"
fi
else
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
fi
else
pvulnstatus "$cve" "$status" "$msg"
fi
}
check_CVE_2022_40982_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
}

243
src/vulns/CVE-2023-20569.sh Normal file
View File

@@ -0,0 +1,243 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2023-20569, Inception, SRSO, Return Address Security
check_CVE_2023_20569() {
check_cve 'CVE-2023-20569'
}
check_CVE_2023_20569_linux() {
local status sys_interface_available msg kernel_sro kernel_sro_err kernel_srso kernel_ibpb_entry kernel_ibpb_no_ret smt_enabled
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "$VULN_SYSFS_BASE/spec_rstack_overflow"; then
# this kernel has the /sys interface, trust it over everything
sys_interface_available=1
status=$ret_sys_interface_check_status
# kernels before the fix from dc6306ad5b0d (v6.6-rc6, backported to v6.5.6)
# incorrectly reported "Mitigation: safe RET, no microcode" as mitigated,
# when in fact userspace is still vulnerable because IBPB doesn't flush
# branch type predictions without the extending microcode.
# override the sysfs status in that case.
if echo "$ret_sys_interface_check_fullmsg" | grep -qi 'Mitigation:.*safe RET.*no microcode'; then
status=VULN
msg="Vulnerable: Safe RET, no microcode (your kernel incorrectly reports this as mitigated, it was fixed in more recent kernels)"
fi
# kernels before the IBPB_NO_RET fix (v6.12, backported to v6.11.5/v6.6.58/v6.1.114/v5.15.169/v5.10.228)
# don't fill the RSB after IBPB, so when sysfs reports an IBPB-based mitigation, the return predictor
# can still be poisoned cross-process (PB-Inception). Override sysfs in that case.
if [ "$status" = OK ] && echo "$ret_sys_interface_check_fullmsg" | grep -qi 'IBPB'; then
if [ "$cap_ibpb_ret" != 1 ] && ! grep -q 'ibpb_no_ret' "$g_kernel" 2>/dev/null; then
status=VULN
msg="Vulnerable: IBPB-based mitigation active but kernel lacks return prediction clearing after IBPB (PB-Inception, upgrade to kernel 6.12+)"
fi
fi
fi
if [ "$opt_sysfs_only" != 1 ]; then
pr_info_nol "* Kernel supports mitigation: "
if [ -n "$g_kernel_err" ]; then
kernel_sro_err="$g_kernel_err"
elif grep -q 'spec_rstack_overflow' "$g_kernel"; then
kernel_sro="found spec_rstack_overflow in kernel image"
fi
if [ -n "$kernel_sro" ]; then
pstatus green YES "$kernel_sro"
elif [ -n "$kernel_sro_err" ]; then
pstatus yellow UNKNOWN "$kernel_sro_err"
else
pstatus yellow NO
fi
pr_info_nol "* Kernel compiled with SRSO support: "
if [ -r "$opt_config" ]; then
# CONFIG_CPU_SRSO: Linux < 6.9
# CONFIG_MITIGATION_SRSO: Linux >= 6.9
if grep -Eq '^CONFIG_(CPU|MITIGATION)_SRSO=y' "$opt_config"; then
pstatus green YES
kernel_srso="CONFIG_(CPU|MITIGATION)_SRSO=y found in kernel config"
else
pstatus yellow NO "required for safe RET and ibpb_on_vmexit mitigations"
fi
else
# https://github.com/torvalds/linux/commit/138bcddb86d8a4f842e4ed6f0585abc9b1a764ff#diff-17bd24a7a7850613cced545790ac30646097e8d6207348c2bd1845f397acb390R2313
if [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "$g_kernel_err"
elif grep -Eq 'WARNING: kernel not compiled with (CPU|MITIGATION)_SRSO' "$g_kernel"; then
# this msg is optimized out at compile time if the option is not enabled, see commit referenced above
# if it's present, then SRSO is NOT compiled in
pstatus yellow NO "kernel not compiled with (CPU|MITIGATION)_SRSO"
else
# if it's not present, then SRSO is compiled in IF kernel_sro is set, otherwise we're just
# in front of an old kernel that doesn't have the mitigation logic at all
if [ -n "$kernel_sro" ]; then
kernel_srso="SRSO mitigation logic is compiled in the kernel"
pstatus green OK "$kernel_srso"
else
pstatus yellow NO "your kernel is too old and doesn't have the mitigation logic"
fi
fi
fi
# check whether the running kernel has the corrected SRSO reporting
# (dc6306ad5b0d, v6.6-rc6, backported to v6.5.6): kernels with the fix
# contain the string "Vulnerable: Safe RET, no microcode" in their image,
# while older kernels only have "safe RET" (and append ", no microcode" dynamically).
pr_info_nol "* Kernel has accurate SRSO reporting: "
if [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "$g_kernel_err"
elif grep -q 'Vulnerable: Safe RET, no microcode' "$g_kernel"; then
pstatus green YES
elif [ -n "$kernel_sro" ]; then
pstatus yellow NO "your kernel reports partial SRSO mitigations as fully mitigated, upgrade recommended"
else
pstatus yellow NO "your kernel is too old and doesn't have the SRSO mitigation logic"
fi
pr_info_nol "* Kernel compiled with IBPB_ENTRY support: "
if [ -r "$opt_config" ]; then
# CONFIG_CPU_IBPB_ENTRY: Linux < 6.9
# CONFIG_MITIGATION_IBPB_ENTRY: Linux >= 6.9
if grep -Eq '^CONFIG_(CPU|MITIGATION)_IBPB_ENTRY=y' "$opt_config"; then
pstatus green YES
kernel_ibpb_entry="CONFIG_(CPU|MITIGATION)_IBPB_ENTRY=y found in kernel config"
else
pstatus yellow NO
fi
else
# https://github.com/torvalds/linux/commit/138bcddb86d8a4f842e4ed6f0585abc9b1a764ff#diff-17bd24a7a7850613cced545790ac30646097e8d6207348c2bd1845f397acb390R2325
if [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "$g_kernel_err"
elif grep -Eq 'WARNING: kernel not compiled with (CPU|MITIGATION)_IBPB_ENTRY' "$g_kernel"; then
# this msg is optimized out at compile time if the option is not enabled, see commit referenced above
# if it's present, then IBPB_ENTRY is NOT compiled in
pstatus yellow NO "kernel not compiled with (CPU|MITIGATION)_IBPB_ENTRY"
else
# if it's not present, then IBPB_ENTRY is compiled in IF kernel_sro is set, otherwise we're just
# in front of an old kernel that doesn't have the mitigation logic at all
if [ -n "$kernel_sro" ]; then
kernel_ibpb_entry="IBPB_ENTRY mitigation logic is compiled in the kernel"
pstatus green OK "$kernel_ibpb_entry"
else
pstatus yellow NO "your kernel is too old and doesn't have the mitigation logic"
fi
fi
fi
# check whether the kernel is aware of the IBPB return predictor bypass (PB-Inception).
# kernels with the fix (v6.12+, backported) contain the "ibpb_no_ret" bug flag string,
# and add an RSB fill after every IBPB on affected CPUs (Zen 1-3).
pr_info_nol "* Kernel is aware of IBPB return predictor bypass: "
if [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "$g_kernel_err"
elif grep -q 'ibpb_no_ret' "$g_kernel"; then
kernel_ibpb_no_ret="ibpb_no_ret found in kernel image"
pstatus green YES "$kernel_ibpb_no_ret"
else
pstatus yellow NO
fi
# Zen & Zen2 : if the right IBPB microcode applied + SMT off --> not vuln
if [ "$cpu_family" = $((0x17)) ]; then
pr_info_nol "* CPU supports IBPB: "
if [ -n "$cap_ibpb" ]; then
pstatus green YES "$cap_ibpb"
else
pstatus yellow NO
fi
pr_info_nol "* Hyper-Threading (SMT) is enabled: "
is_cpu_smt_enabled
smt_enabled=$?
if [ "$smt_enabled" = 0 ]; then
pstatus yellow YES
else
pstatus green NO
fi
# Zen 3/4 microcode brings SBPB mitigation
elif [ "$cpu_family" = $((0x19)) ]; then
pr_info_nol "* CPU supports SBPB: "
if [ "$cap_sbpb" = 1 ]; then
pstatus green YES
elif [ "$cap_sbpb" = 3 ]; then
pstatus yellow UNKNOWN "cannot write MSR, rerun with --allow-msr-write"
else
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!"
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 [ -z "$msg" ]; then
# if msg is empty, sysfs check didn't fill it, rely on our own test
if [ "$opt_sysfs_only" != 1 ]; then
# Zen/Zen2
if [ "$cpu_family" = $((0x17)) ]; then
if [ "$smt_enabled" = 0 ]; then
pvulnstatus "$cve" VULN "SMT is enabled on your Zen/Zen2 CPU, which makes mitigation ineffective"
explain "For Zen/Zen2 CPUs, proper mitigation needs an up to date microcode, and SMT needs to be disabled (this can be done by adding \`nosmt\` to your kernel command line)"
elif [ -z "$kernel_sro" ]; then
pvulnstatus "$cve" VULN "Your kernel is too old and doesn't have the SRSO mitigation logic"
elif [ -n "$cap_ibpb" ]; then
if [ "$cap_ibpb_ret" != 1 ] && [ -z "$kernel_ibpb_no_ret" ]; then
pvulnstatus "$cve" VULN "IBPB alone doesn't flush return predictions on this CPU, kernel update needed (PB-Inception, fixed in 6.12+)"
else
pvulnstatus "$cve" OK "SMT is disabled and both your kernel and microcode support mitigation"
fi
else
pvulnstatus "$cve" VULN "Your microcode is too old"
fi
# Zen3/Zen4
elif [ "$cpu_family" = $((0x19)) ]; then
if [ -z "$kernel_sro" ]; then
pvulnstatus "$cve" VULN "Your kernel is too old and doesn't have the SRSO mitigation logic"
elif [ -z "$kernel_srso" ] && [ -z "$kernel_ibpb_entry" ]; then
pvulnstatus "$cve" VULN "Your kernel doesn't have either SRSO or IBPB_ENTRY compiled-in"
elif [ "$cap_sbpb" = 3 ]; then
pvulnstatus "$cve" UNK "Couldn't verify if your microcode supports IBPB (rerun with --allow-msr-write)"
elif [ "$cap_sbpb" = 2 ]; then
pvulnstatus "$cve" VULN "Your microcode doesn't support SBPB"
else
if [ "$cap_ibpb_ret" != 1 ] && [ -z "$kernel_ibpb_no_ret" ] && [ -n "$kernel_ibpb_entry" ]; then
pvulnstatus "$cve" VULN "IBPB alone doesn't flush return predictions on this CPU, kernel update needed (PB-Inception, fixed in 6.12+)"
else
pvulnstatus "$cve" OK "Your kernel and microcode both support mitigation"
fi
fi
else
# not supposed to happen, as normally this CPU should not be affected and not run this code
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
fi
else
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
fi
else
pvulnstatus "$cve" "$status" "$msg"
if echo "$msg" | grep -qi 'your kernel incorrectly reports this as mitigated'; then
explain "Your kernel's /sys interface reports 'Mitigation: safe RET, no microcode' for the SRSO vulnerability.\n" \
"This was a bug in the kernel's reporting (fixed in v6.5.6/v6.6-rc6, commit dc6306ad5b0d):\n" \
"the Safe RET mitigation alone only protects the kernel from userspace attacks, but without\n" \
"the IBPB-extending microcode, userspace itself remains vulnerable because IBPB doesn't flush\n" \
"branch type predictions. Newer kernels correctly report this as 'Vulnerable: Safe RET, no microcode'.\n" \
"To fully mitigate, you need both the Safe RET kernel support AND an updated CPU microcode.\n" \
"Updating your kernel to v6.5.6+ or v6.6+ will also give you accurate vulnerability reporting."
fi
fi
}
check_CVE_2023_20569_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
}

177
src/vulns/CVE-2023-20588.sh Normal file
View File

@@ -0,0 +1,177 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2023-20588, DIV0, AMD Division by Zero Speculative Data Leak
check_CVE_2023_20588() {
check_cve 'CVE-2023-20588'
}
# shellcheck disable=SC2034
_cve_2023_20588_pvulnstatus_smt() {
# common logic for both live (cpuinfo) and live (kernel image fallback) paths:
# if --paranoid and SMT is on, report VULN; otherwise OK.
# $1 = mitigation detail message
if [ "$opt_paranoid" != 1 ] || ! is_cpu_smt_enabled; then
pvulnstatus "$cve" OK "Mitigation: amd_clear_divider on exit to user/guest"
else
pvulnstatus "$cve" VULN "DIV0 mitigation is active but SMT is enabled, data leak possible between sibling threads"
explain "Disable SMT (Simultaneous Multi-Threading) for full protection against DIV0.\n " \
"The kernel mitigation only covers kernel-to-user and host-to-guest leak paths, not cross-SMT-thread leaks.\n " \
"You can disable SMT by booting with the \`nosmt\` kernel parameter, or at runtime:\n " \
"\`echo off > /sys/devices/system/cpu/smt/control\`"
fi
}
# shellcheck disable=SC2034
_cve_2023_20588_pvulnstatus_no_kernel() {
pvulnstatus "$cve" VULN "your kernel doesn't support DIV0 mitigation"
explain "Update your kernel to a version that includes the amd_clear_divider mitigation (Linux >= 6.5 or a backported stable/vendor kernel).\n " \
"The kernel fix adds a dummy division on every exit to userspace and before VMRUN, preventing stale quotient data from leaking.\n " \
"Also disable SMT for full protection, as the mitigation doesn't cover cross-SMT-thread leaks."
}
check_CVE_2023_20588_linux() {
local status sys_interface_available msg kernel_mitigated cpuinfo_div0 dmesg_div0 ret
status=UNK
sys_interface_available=0
msg=''
# No sysfs interface exists for this CVE (no /sys/devices/system/cpu/vulnerabilities/div0).
# sys_interface_available stays 0.
#
# Kernel source inventory for CVE-2023-20588 (DIV0), 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) ---
# 77245f1c3c64 (v6.5, initial fix): amd_clear_divider()
# initially called from exc_divide_error() (#DE handler)
# f58d6fbcb7c8 (v6.5, follow-up fix): moved amd_clear_divider() call to
# exit-to-userspace path and before VMRUN (SVM)
# bfff3c6692ce (v6.8): moved DIV0 detection from model range check to
# unconditional in init_amd_zen1()
# 501bd734f933 (v6.11): amd_clear_divider() made __always_inline
# (may no longer appear in System.map on newer kernels)
#
# --- dmesg ---
# 77245f1c3c64 (v6.5): "AMD Zen1 DIV0 bug detected. Disable SMT for full protection."
# (present since the initial fix, printed via pr_notice_once)
#
# --- /proc/cpuinfo bugs field ---
# 77245f1c3c64 (v6.5): X86_BUG_DIV0 mapped to "div0" in bugs field
#
# --- CPU affection logic (for is_cpu_affected) ---
# 77245f1c3c64 (v6.5, initial model list):
# AMD: family 0x17 models 0x00-0x2f, 0x50-0x5f
# bfff3c6692ce (v6.8): moved to init_amd_zen1(), unconditional for all Zen1
# (same model ranges, just different detection path)
# vendor scope: AMD only (Zen1 microarchitecture)
#
# --- stable backports ---
# 5.10.y, 5.15.y, 6.1.y, 6.4.y: backported via cpu_has_amd_erratum() path
# (same as mainline v6.5 initial implementation)
# 6.5.y, 6.7.y: same erratum-table detection as mainline v6.5
# 6.6.y: stable-specific commit 824549816609 backported the init_amd_zen1()
# move (equivalent to mainline bfff3c6692ce but adapted to 6.6 context)
# 6.8.y, 6.9.y, 6.10.y: carry mainline bfff3c6692ce directly
# 6.7.y missed the init_amd_zen1() move (EOL before backport landed)
# 501bd734f933 (__always_inline) was NOT backported to any stable branch
# 4.14.y, 4.19.y, 5.4.y: do NOT have the fix (EOL or not backported)
# no stable-specific string or behavior differences; all branches use the
# same dmesg message and /proc/cpuinfo bugs field as mainline
if [ "$opt_sysfs_only" != 1 ]; then
pr_info_nol "* Kernel supports DIV0 mitigation: "
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
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
kernel_mitigated="found amd_clear_divider in System.map"
pstatus green YES "$kernel_mitigated"
else
pstatus yellow NO
fi
pr_info_nol "* DIV0 mitigation enabled and active: "
cpuinfo_div0=''
dmesg_div0=''
if [ "$g_mode" = live ]; 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"
else
# cpuinfo flag not found, fall back to dmesg
dmesg_grep 'AMD Zen1 DIV0 bug detected'
ret=$?
if [ "$ret" -eq 0 ]; then
dmesg_div0=1
pstatus green YES "DIV0 bug detected message found in dmesg"
elif [ "$ret" -eq 2 ]; then
pstatus yellow UNKNOWN "dmesg truncated, cannot check for DIV0 message"
else
pstatus yellow NO "div0 not found in $g_procfs/cpuinfo bug flags or dmesg"
fi
fi
else
pstatus blue N/A "not testable in no-runtime mode"
fi
pr_info_nol "* SMT (Simultaneous Multi-Threading) is enabled: "
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
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
# 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
elif [ -n "$kernel_mitigated" ]; then
# kernel has the code but the bug flag is not set, it shouldn't happen on affected CPUs,
# but if it does, trust the kernel image evidence
_cve_2023_20588_pvulnstatus_smt
else
_cve_2023_20588_pvulnstatus_no_kernel
fi
else
# no-runtime 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
_cve_2023_20588_pvulnstatus_no_kernel
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_2023_20588_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
}

171
src/vulns/CVE-2023-20593.sh Normal file
View File

@@ -0,0 +1,171 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2023-20593, Zenbleed, Cross-Process Information Leak
check_CVE_2023_20593() {
check_cve 'CVE-2023-20593'
}
check_CVE_2023_20593_linux() {
local status sys_interface_available msg kernel_zenbleed kernel_zenbleed_err fp_backup_fix ucode_zenbleed zenbleed_print_vuln ret
status=UNK
sys_interface_available=0
msg=''
if [ "$opt_sysfs_only" != 1 ]; then
pr_info_nol "* Zenbleed mitigation is supported by kernel: "
kernel_zenbleed=''
if [ -n "$g_kernel_err" ]; then
kernel_zenbleed_err="$g_kernel_err"
# commit 522b1d69219d8f083173819fde04f994aa051a98
elif grep -q 'Zenbleed:' "$g_kernel"; then
kernel_zenbleed="found zenbleed message in kernel image"
fi
if [ -n "$kernel_zenbleed" ]; then
pstatus green YES "$kernel_zenbleed"
elif [ -n "$kernel_zenbleed_err" ]; then
pstatus yellow UNKNOWN "$kernel_zenbleed_err"
else
pstatus yellow NO
fi
pr_info_nol "* Zenbleed kernel mitigation enabled and active: "
if [ "$g_mode" = live ]; 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
if is_amd && [ "$cpu_family" -ge $((0x17)) ]; then
read_msr 0xc0011029
ret=$?
if [ "$ret" = "$READ_MSR_RET_OK" ]; then
if [ $((ret_read_msr_value_lo >> 9 & 1)) -eq 1 ]; then
pstatus green YES "FP_BACKUP_FIX bit set in DE_CFG"
fp_backup_fix=1
else
pstatus yellow NO "FP_BACKUP_FIX is cleared in DE_CFG"
fp_backup_fix=0
fi
elif [ "$ret" = "$READ_MSR_RET_KO" ]; then
pstatus yellow UNKNOWN "Couldn't read the DE_CFG MSR"
else
pstatus yellow UNKNOWN "$ret_read_msr_msg"
fi
else
fp_backup_fix=0
pstatus blue N/A "CPU is incompatible"
fi
else
pstatus blue N/A "not testable in no-runtime mode"
fi
pr_info_nol "* Zenbleed mitigation is supported by CPU microcode: "
has_zenbleed_fixed_firmware
ret=$?
if [ "$ret" -eq 0 ]; then
pstatus green YES
ucode_zenbleed=1
elif [ "$ret" -eq 1 ]; then
pstatus yellow NO
ucode_zenbleed=2
else
pstatus yellow UNKNOWN
ucode_zenbleed=3
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!"
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 [ -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 [ "$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"
elif [ "$ucode_zenbleed" = 1 ]; then
pvulnstatus "$cve" OK "Your CPU microcode mitigates Zenbleed"
elif [ "$fp_backup_fix" = 1 ]; then
pvulnstatus "$cve" OK "Your kernel mitigates Zenbleed"
else
zenbleed_print_vuln=1
fi
else
if [ "$ucode_zenbleed" = 1 ]; then
pvulnstatus "$cve" OK "Your CPU microcode mitigates Zenbleed"
elif [ -n "$kernel_zenbleed" ]; then
pvulnstatus "$cve" OK "Your kernel mitigates Zenbleed"
else
zenbleed_print_vuln=1
fi
fi
if [ "$zenbleed_print_vuln" = 1 ]; then
pvulnstatus "$cve" VULN "Your kernel is too old to mitigate Zenbleed and your CPU microcode doesn't mitigate it either"
explain "Your CPU vendor may have a new microcode for your CPU model that mitigates this issue (refer to the hardware section above).\n " \
"Otherwise, the Linux kernel is able to mitigate this issue regardless of the microcode version you have, but in this case\n " \
"your kernel is too old to support this, your Linux distribution vendor might have a more recent version you should upgrade to.\n " \
"Note that either having an up to date microcode OR an up to date kernel is enough to mitigate this issue.\n " \
"To manually mitigate the issue right now, you may use the following command: \`wrmsr -a 0xc0011029 \$((\$(rdmsr -c 0xc0011029) | (1<<9)))\`,\n " \
"however note that this manual mitigation will only be active until the next reboot."
fi
unset zenbleed_print_vuln
else
pvulnstatus "$cve" "$status" "$msg"
fi
}
check_CVE_2023_20593_bsd() {
local zenbleed_enable zenbleed_state kernel_zenbleed
pr_info_nol "* Kernel supports Zenbleed mitigation (machdep.mitigations.zenbleed.enable): "
zenbleed_enable=$(sysctl -n machdep.mitigations.zenbleed.enable 2>/dev/null)
if [ -n "$zenbleed_enable" ]; then
kernel_zenbleed=1
case "$zenbleed_enable" in
0) pstatus yellow YES "force disabled" ;;
1) pstatus green YES "force enabled" ;;
2) pstatus green YES "automatic (default)" ;;
*) pstatus yellow YES "unknown value: $zenbleed_enable" ;;
esac
else
kernel_zenbleed=0
pstatus yellow NO
fi
pr_info_nol "* Zenbleed mitigation state: "
zenbleed_state=$(sysctl -n machdep.mitigations.zenbleed.state 2>/dev/null)
if [ -n "$zenbleed_state" ]; then
if echo "$zenbleed_state" | grep -qi 'not.applicable\|mitigation.enabled'; then
pstatus green YES "$zenbleed_state"
elif echo "$zenbleed_state" | grep -qi 'mitigation.disabled'; then
pstatus yellow NO "$zenbleed_state"
else
pstatus yellow UNKNOWN "$zenbleed_state"
fi
else
pstatus yellow NO "sysctl not available"
fi
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif [ "$kernel_zenbleed" = 1 ] && [ "$zenbleed_enable" != 0 ]; then
if [ -n "$zenbleed_state" ] && echo "$zenbleed_state" | grep -qi 'mitigation.enabled'; then
pvulnstatus "$cve" OK "Zenbleed mitigation is enabled ($zenbleed_state)"
elif [ -n "$zenbleed_state" ] && echo "$zenbleed_state" | grep -qi 'not.applicable'; then
pvulnstatus "$cve" OK "Zenbleed mitigation not applicable to this CPU ($zenbleed_state)"
else
pvulnstatus "$cve" OK "Zenbleed mitigation is enabled"
fi
elif [ "$kernel_zenbleed" = 1 ] && [ "$zenbleed_enable" = 0 ]; then
pvulnstatus "$cve" VULN "Zenbleed mitigation is supported but force disabled"
explain "To re-enable Zenbleed mitigation, run \`sysctl machdep.mitigations.zenbleed.enable=2' for automatic mode.\n " \
"To make this persistent, add 'machdep.mitigations.zenbleed.enable=2' to /etc/sysctl.conf."
else
pvulnstatus "$cve" VULN "your kernel doesn't support Zenbleed mitigation, update it"
explain "Your CPU vendor may also have a new microcode for your CPU model that mitigates this issue.\n " \
"Updating to FreeBSD 14.0 or later will provide kernel-level Zenbleed mitigation via the\n " \
"machdep.mitigations.zenbleed sysctl."
fi
}

View File

@@ -0,0 +1,46 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2023-23583, Reptar, Redundant Prefix Issue
check_CVE_2023_23583() {
check_cve 'CVE-2023-23583'
}
check_CVE_2023_23583_linux() {
local status sys_interface_available msg
status=UNK
sys_interface_available=0
msg=''
# there is no sysfs file for this vuln, and no kernel patch,
# the mitigation is only ucode-based and there's no flag exposed,
# so most of the work has already been done by is_cpu_affected()
# shellcheck disable=SC2154
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif [ -z "$g_reptar_fixed_ucode_version" ]; then
# CPU matched the model blacklist but has no known fixing microcode
# (likely an EOL stepping that Intel won't release a fix for)
pvulnstatus "$cve" VULN "your CPU is affected and no microcode update is available for your CPU stepping"
else
pr_info_nol "* Reptar is mitigated by microcode: "
if [ -z "$cpu_ucode" ]; then
pstatus yellow UNKNOWN "couldn't get your microcode version"
pvulnstatus "$cve" UNK "couldn't detect microcode version to verify mitigation"
elif [ "$cpu_ucode" -lt "$g_reptar_fixed_ucode_version" ]; then
pstatus yellow NO "You have ucode $(printf "0x%x" "$cpu_ucode") and version $(printf "0x%x" "$g_reptar_fixed_ucode_version") minimum is required"
pvulnstatus "$cve" VULN "Your microcode is too old to mitigate the vulnerability"
else
pstatus green YES "You have ucode $(printf "0x%x" "$cpu_ucode") which is recent enough (>= $(printf "0x%x" "$g_reptar_fixed_ucode_version"))"
pvulnstatus "$cve" OK "Your microcode mitigates the vulnerability"
fi
fi
}
check_CVE_2023_23583_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
}

177
src/vulns/CVE-2023-28746.sh Normal file
View File

@@ -0,0 +1,177 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2023-28746, RFDS, Register File Data Sampling
check_CVE_2023_28746() {
check_cve 'CVE-2023-28746'
}
check_CVE_2023_28746_linux() {
local status sys_interface_available msg kernel_rfds kernel_rfds_err rfds_mitigated
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "$VULN_SYSFS_BASE/reg_file_data_sampling"; then
# this kernel has the /sys interface, trust it over everything
sys_interface_available=1
#
# Kernel source inventory for reg_file_data_sampling (RFDS)
#
# --- sysfs messages ---
# all versions:
# "Not affected" (cpu_show_common, pre-existing)
#
# --- mainline ---
# 8076fcde016c (v6.9-rc1, initial RFDS sysfs):
# "Vulnerable" (RFDS_MITIGATION_OFF)
# "Vulnerable: No microcode" (RFDS_MITIGATION_UCODE_NEEDED)
# "Mitigation: Clear Register File" (RFDS_MITIGATION_VERW)
# b8ce25df2999 (v6.15, added AUTO state):
# no string changes; RFDS_MITIGATION_AUTO is internal, resolved before display
# 203d81f8e167 (v6.17, restructured):
# no string changes; added rfds_update_mitigation() + rfds_apply_mitigation()
#
# --- stable backports ---
# 5.10.215, 5.15.154, 6.1.82, 6.6.22, 6.7.10, 6.8.1:
# same 3 strings as mainline; no structural differences
# macro ALDERLAKE_N (0xBE) used instead of mainline ATOM_GRACEMONT (same model)
#
# --- Kconfig symbols ---
# 8076fcde016c (v6.9-rc1): CONFIG_MITIGATION_RFDS (default y)
# no renames across any version
#
# --- kernel functions (for $opt_map / System.map) ---
# 8076fcde016c (v6.9-rc1): rfds_select_mitigation(), rfds_parse_cmdline(),
# rfds_show_state(), cpu_show_reg_file_data_sampling(), vulnerable_to_rfds()
# 203d81f8e167 (v6.17): + rfds_update_mitigation(), rfds_apply_mitigation()
#
# --- CPU affection logic (for is_cpu_affected) ---
# 8076fcde016c (v6.9-rc1, initial model list):
# Intel: ATOM_GOLDMONT (0x5C), ATOM_GOLDMONT_D (0x5F),
# ATOM_GOLDMONT_PLUS (0x7A), ATOM_TREMONT_D (0x86),
# ATOM_TREMONT (0x96), ATOM_TREMONT_L (0x9C),
# ATOM_GRACEMONT (0xBE), ALDERLAKE (0x97),
# ALDERLAKE_L (0x9A), RAPTORLAKE (0xB7),
# RAPTORLAKE_P (0xBA), RAPTORLAKE_S (0xBF)
# 722fa0dba74f (v6.15, P-only hybrid exclusion):
# ALDERLAKE (0x97) and RAPTORLAKE (0xB7) narrowed to Atom core type only
# via X86_HYBRID_CPU_TYPE_ATOM check in vulnerable_to_rfds(); P-cores on
# these hybrid models are not affected, only E-cores (Gracemont) are.
# (not modeled here, we conservatively flag all steppings per whitelist principle,
# because detecting the active core type at runtime is unreliable from userspace)
# immunity: ARCH_CAP_RFDS_NO (bit 27 of IA32_ARCH_CAPABILITIES)
# mitigation: ARCH_CAP_RFDS_CLEAR (bit 28 of IA32_ARCH_CAPABILITIES)
# vendor scope: Intel only
#
# all messages start with either "Not affected", "Mitigation", or "Vulnerable"
status=$ret_sys_interface_check_status
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
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
fi
fi
if is_x86_cpu && [ "$g_mode" = live ] && [ "$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
pstatus green YES
else
rfds_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!"
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 [ -z "$msg" ]; then
if [ "$opt_sysfs_only" != 1 ]; then
if [ "$cap_rfds_clear" = 1 ]; then
if [ -n "$kernel_rfds" ]; then
if [ "$g_mode" = live ]; 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
pvulnstatus "$cve" VULN "Your microcode and kernel are both up to date for this mitigation, but the mitigation is not active"
explain "The RFDS mitigation has been disabled. Remove 'reg_file_data_sampling=off' or 'mitigations=off'\n " \
"from your kernel command line to re-enable it."
fi
else
pvulnstatus "$cve" OK "Your microcode and kernel are both up to date for this mitigation"
fi
else
pvulnstatus "$cve" VULN "Your microcode supports mitigation, but your kernel doesn't, upgrade it to mitigate the vulnerability"
explain "Update your kernel to a version that supports RFDS mitigation (Linux 6.9+, or check if your distro\n " \
"has a backport). Your CPU microcode already provides the RFDS_CLEAR capability."
fi
else
if [ -n "$kernel_rfds" ]; then
pvulnstatus "$cve" VULN "Your kernel supports mitigation, but your CPU microcode also needs to be updated to mitigate the vulnerability"
explain "Update your CPU microcode (via BIOS/firmware update or linux-firmware package) to a version that\n " \
"provides the RFDS_CLEAR capability."
else
pvulnstatus "$cve" VULN "Neither your kernel or your microcode support mitigation, upgrade both to mitigate the vulnerability"
explain "Update both your CPU microcode (via BIOS/firmware update from your OEM) and your kernel to a version\n " \
"that supports RFDS mitigation (Linux 6.9+, or check if your distro has a backport)."
fi
fi
else
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
fi
else
pvulnstatus "$cve" "$status" "$msg"
fi
}
check_CVE_2023_28746_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
}

163
src/vulns/CVE-2024-28956.sh Normal file
View File

@@ -0,0 +1,163 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2024-28956, ITS, Indirect Target Selection
check_CVE_2024_28956() {
check_cve 'CVE-2024-28956'
}
check_CVE_2024_28956_linux() {
local status sys_interface_available msg kernel_its kernel_its_err ret
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "$VULN_SYSFS_BASE/indirect_target_selection"; then
# this kernel has the /sys interface, trust it over everything
sys_interface_available=1
#
# Kernel source inventory for indirect_target_selection (ITS)
#
# --- sysfs messages ---
# all versions:
# "Not affected" (cpu_show_common, pre-existing)
#
# --- mainline ---
# f4818881c47f (v6.15-rc2, initial ITS sysfs):
# "Vulnerable" (ITS_MITIGATION_OFF)
# "Mitigation: Aligned branch/return thunks" (ITS_MITIGATION_ALIGNED_THUNKS)
# "Mitigation: Retpolines, Stuffing RSB" (ITS_MITIGATION_RETPOLINE_STUFF)
# 2665281a07e1 (v6.15-rc2, added vmexit option):
# "Mitigation: Vulnerable, KVM: Not affected" (ITS_MITIGATION_VMEXIT_ONLY)
# facd226f7e0c (v6.15-rc2, added stuff cmdline option):
# no string changes; added "stuff" boot param value
# 61ab72c2c6bf (v6.16-rc1, restructured select/update/apply):
# no string changes; added ITS_MITIGATION_AUTO (internal, resolved before display)
# split into its_select_mitigation() + its_update_mitigation() + its_apply_mitigation()
# 0cdd2c4f35cf (v6.18-rc1, attack vector controls):
# no string changes; added per-vector on/off control
#
# --- stable backports ---
# 5.10.y, 5.15.y, 6.1.y: 3 strings only (no VMEXIT_ONLY, no RETPOLINE_STUFF
# in 5.10/5.15/6.1). Uses CONFIG_RETPOLINE/CONFIG_RETHUNK (not CONFIG_MITIGATION_*).
# 6.6.y, 6.12.y, 6.14.y, 6.15.y: all 4 strings, full vmexit+stuff support.
# 6.16.y+: restructured 3-phase select/update/apply.
# Not backported to: 5.4.y, 6.11.y, 6.13.y.
#
# --- RHEL/CentOS ---
# rocky9 (5.14): all 4 strings, restructured 3-phase version.
# rocky10 (6.12): all 4 strings, restructured 3-phase version.
# Not backported to: centos7, rocky8.
#
# --- Kconfig symbols ---
# f4818881c47f (v6.15-rc2): CONFIG_MITIGATION_ITS (default y)
# depends on CPU_SUP_INTEL && X86_64 && MITIGATION_RETPOLINE && MITIGATION_RETHUNK
# stable 5.10.y, 5.15.y, 6.1.y: CONFIG_MITIGATION_ITS
# depends on CONFIG_RETPOLINE && CONFIG_RETHUNK (pre-rename names)
#
# --- kernel functions (for $opt_map / System.map) ---
# f4818881c47f (v6.15-rc2): its_select_mitigation(), its_parse_cmdline(),
# its_show_state()
# 61ab72c2c6bf (v6.16-rc1): split into its_select_mitigation() +
# its_update_mitigation() + its_apply_mitigation()
# stable 5.10.y-6.15.y: its_select_mitigation() (no split)
# rocky9, rocky10: its_select_mitigation() + its_update_mitigation() +
# its_apply_mitigation()
#
# --- CPU affection logic (for is_cpu_affected) ---
# X86_BUG_ITS is set when ALL conditions are true:
# 1. Intel vendor, family 6
# 2. CPU matches model blacklist (with stepping constraints)
# 3. ARCH_CAP_ITS_NO (bit 62 of IA32_ARCH_CAPABILITIES) is NOT set
# 4. X86_FEATURE_BHI_CTRL is NOT present
# 159013a7ca18 (v6.15-rc2, initial model list):
# Intel: SKYLAKE_X (stepping > 5), KABYLAKE_L (stepping > 0xb),
# KABYLAKE (stepping > 0xc), ICELAKE_L, ICELAKE_D, ICELAKE_X,
# COMETLAKE, COMETLAKE_L, TIGERLAKE_L, TIGERLAKE, ROCKETLAKE
# (all steppings unless noted)
# ITS_NATIVE_ONLY flag (X86_BUG_ITS_NATIVE_ONLY): set for
# ICELAKE_L, ICELAKE_D, ICELAKE_X, TIGERLAKE_L, TIGERLAKE, ROCKETLAKE
# These CPUs are affected for user-to-kernel but NOT guest-to-host (VMX)
# immunity: ARCH_CAP_ITS_NO (bit 62 of IA32_ARCH_CAPABILITIES)
# immunity: X86_FEATURE_BHI_CTRL (none of the affected CPUs have this)
# vendor scope: Intel only
#
# all messages start with either "Not affected", "Vulnerable", or "Mitigation"
status=$ret_sys_interface_check_status
fi
if [ "$opt_sysfs_only" != 1 ]; then
pr_info_nol "* Kernel supports ITS mitigation: "
kernel_its=''
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
kernel_its="found indirect_target_selection in kernel image"
fi
if [ -z "$kernel_its" ] && is_x86_kernel && [ -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 grep -q 'its_select_mitigation' "$opt_map"; then
kernel_its="found its_select_mitigation in System.map"
fi
fi
if [ -n "$kernel_its" ]; then
pstatus green YES "$kernel_its"
elif [ -n "$kernel_its_err" ]; then
pstatus yellow UNKNOWN "$kernel_its_err"
else
pstatus yellow NO
fi
pr_info_nol "* CPU explicitly indicates not being affected by ITS (ITS_NO): "
if [ "$cap_its_no" = -1 ]; then
pstatus yellow UNKNOWN
elif [ "$cap_its_no" = 1 ]; then
pstatus green YES
else
pstatus yellow NO
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!"
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 [ -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 [ "$cap_its_no" = 1 ]; then
pvulnstatus "$cve" OK "CPU is not affected (ITS_NO)"
elif [ -n "$kernel_its" ]; then
pvulnstatus "$cve" OK "Kernel mitigates the vulnerability"
elif [ -z "$kernel_its" ] && [ -z "$kernel_its_err" ]; then
pvulnstatus "$cve" VULN "Your kernel doesn't support ITS mitigation"
explain "Update your kernel to a version that includes ITS mitigation (Linux 6.15+, or check\n" \
"if your distro has a backport). Also update your CPU microcode to ensure IBPB fully\n" \
"flushes indirect branch predictions (microcode-20250512+)."
else
pvulnstatus "$cve" UNK "couldn't determine mitigation status: $kernel_its_err"
fi
else
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
fi
else
pvulnstatus "$cve" "$status" "$msg"
fi
}
check_CVE_2024_28956_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
}

176
src/vulns/CVE-2024-36350.sh Normal file
View File

@@ -0,0 +1,176 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2024-36350, TSA-SQ, Transient Scheduler Attack Store Queue
check_CVE_2024_36350() {
check_cve 'CVE-2024-36350'
}
check_CVE_2024_36350_linux() {
local status sys_interface_available msg kernel_tsa kernel_tsa_err smt_enabled
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "$VULN_SYSFS_BASE/tsa"; then
# this kernel has the /sys interface, trust it over everything
sys_interface_available=1
#
# Complete sysfs message inventory for tsa
#
# all versions:
# "Not affected" (cpu_show_common, pre-existing)
#
# --- mainline ---
# d8010d4ba43e (v6.16-rc6, initial TSA sysfs):
# "Vulnerable" (TSA_MITIGATION_NONE)
# "Vulnerable: No microcode" (TSA_MITIGATION_UCODE_NEEDED)
# "Mitigation: Clear CPU buffers: user/kernel boundary" (TSA_MITIGATION_USER_KERNEL)
# "Mitigation: Clear CPU buffers: VM" (TSA_MITIGATION_VM)
# "Mitigation: Clear CPU buffers" (TSA_MITIGATION_FULL)
# 6b21d2f0dc73 (v6.17-rc1, attack vector controls):
# no string changes; only mitigation selection logic changed
# (AUTO can now resolve to USER_KERNEL or VM based on attack vector config)
#
# --- stable backports ---
# 6.16.y: d8010d4ba43e (same as mainline), same strings.
# 6.17.y: has 6b21d2f0dc73 (attack vector controls), same strings.
# 5.10.y (78192f511f40), 5.15.y (f2b75f1368af), 6.1.y (d12145e8454f),
# 6.6.y (90293047df18), 6.12.y (7a0395f6607a), 6.15.y (ab0f6573b211):
# different UCODE_NEEDED string:
# "Vulnerable: Clear CPU buffers attempted, no microcode" (TSA_MITIGATION_UCODE_NEEDED)
# all other strings identical to mainline.
# default is FULL (no AUTO enum); USER_KERNEL/VM only via cmdline tsa=user/tsa=vm.
# VM-forced mitigation: when UCODE_NEEDED and running in a VM, forces FULL
# (stable-only logic, not in mainline).
#
# --- RHEL/CentOS ---
# rocky9 (5.14-based), rocky10 (6.12-based): same strings as mainline.
# "Vulnerable: No microcode" for UCODE_NEEDED (matches mainline, NOT the stable variant).
# rocky8 (4.18-based), centos7 (3.10-based): no TSA support.
#
# all messages start with either "Not affected", "Mitigation", or "Vulnerable"
status=$ret_sys_interface_check_status
fi
if [ "$opt_sysfs_only" != 1 ]; then
check_has_vmm
# Override: when running as a hypervisor, "user/kernel boundary" mode
# (tsa=user) leaves the VM exit boundary uncovered — guests can exploit
# TSA to leak host data. The kernel correctly reports its own mode, but
# the script must flag this as insufficient for a VMM host.
if [ "$sys_interface_available" = 1 ] && [ "$g_has_vmm" != 0 ]; then
if echo "$ret_sys_interface_check_fullmsg" | grep -q 'user/kernel boundary'; then
status=VULN
msg="Vulnerable: TSA mitigation limited to user/kernel boundary (tsa=user), VM exit boundary is not covered"
fi
fi
pr_info_nol "* Kernel supports TSA mitigation: "
kernel_tsa=''
kernel_tsa_err=''
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
kernel_tsa="found TSA mitigation message in kernel image"
fi
if [ -z "$kernel_tsa" ] && is_x86_kernel && [ -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 grep -q 'tsa_select_mitigation' "$opt_map"; then
kernel_tsa="found tsa_select_mitigation in System.map"
fi
fi
if [ -n "$kernel_tsa" ]; then
pstatus green YES "$kernel_tsa"
elif [ -n "$kernel_tsa_err" ]; then
pstatus yellow UNKNOWN "$kernel_tsa_err"
else
pstatus yellow NO
fi
if is_amd || is_hygon; then
pr_info_nol "* CPU explicitly indicates not vulnerable to TSA-SQ (TSA_SQ_NO): "
if [ "$cap_tsa_sq_no" = 1 ]; then
pstatus green YES
elif [ "$cap_tsa_sq_no" = 0 ]; then
pstatus yellow NO
else
pstatus yellow UNKNOWN "couldn't read CPUID leaf 0x80000021"
fi
pr_info_nol "* Microcode supports VERW buffer clearing: "
if [ "$cap_verw_clear" = 1 ]; then
pstatus green YES
elif [ "$cap_verw_clear" = 0 ]; then
pstatus yellow NO
else
pstatus yellow UNKNOWN "couldn't read CPUID leaf 0x80000021"
fi
fi
pr_info_nol "* Hyper-Threading (SMT) is enabled: "
is_cpu_smt_enabled
smt_enabled=$?
if [ "$smt_enabled" = 0 ]; then
pstatus yellow YES
else
pstatus green NO
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!"
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 [ -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 [ "$cap_verw_clear" = 1 ] && [ -n "$kernel_tsa" ]; then
if [ "$opt_paranoid" = 1 ] && [ "$smt_enabled" = 0 ]; then
pvulnstatus "$cve" VULN "Mitigation active but SMT must be disabled for full TSA-SQ protection"
explain "Disable SMT by adding \`nosmt\` to your kernel command line for complete protection against cross-thread TSA-SQ leakage."
else
pvulnstatus "$cve" OK "Both kernel and microcode mitigate the vulnerability"
fi
elif [ "$cap_verw_clear" = 1 ]; then
pvulnstatus "$cve" VULN "Microcode supports mitigation but kernel is too old"
explain "Update your kernel to a version that supports CONFIG_MITIGATION_TSA (Linux 6.16+),\n " \
"or check if your distribution has backported the TSA mitigation."
elif [ -n "$kernel_tsa" ]; then
pvulnstatus "$cve" VULN "Kernel supports mitigation but microcode is too old"
explain "Update your CPU microcode via a BIOS/firmware update from your OEM.\n " \
"The microcode must expose the VERW_CLEAR capability (CPUID 0x80000021 EAX bit 5)."
else
pvulnstatus "$cve" VULN "Neither kernel nor microcode mitigate the vulnerability"
explain "Both a kernel update (CONFIG_MITIGATION_TSA, Linux 6.16+) and a microcode/firmware update\n " \
"from your OEM are needed to mitigate this vulnerability."
fi
else
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
fi
else
pvulnstatus "$cve" "$status" "$msg"
if echo "$msg" | grep -q 'VM exit boundary'; then
explain "This system runs a hypervisor but TSA mitigation only clears CPU buffers at\n " \
"user/kernel transitions (tsa=user). Guests can exploit TSA to leak host data\n " \
"across VM exit. Use \`tsa=on\` (or remove \`tsa=user\`) to cover both boundaries."
fi
fi
}
check_CVE_2024_36350_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
}

169
src/vulns/CVE-2024-36357.sh Normal file
View File

@@ -0,0 +1,169 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2024-36357, TSA-L1, Transient Scheduler Attack L1
check_CVE_2024_36357() {
check_cve 'CVE-2024-36357'
}
check_CVE_2024_36357_linux() {
local status sys_interface_available msg kernel_tsa kernel_tsa_err
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "$VULN_SYSFS_BASE/tsa"; then
# this kernel has the /sys interface, trust it over everything
sys_interface_available=1
#
# Complete sysfs message inventory for tsa
#
# all versions:
# "Not affected" (cpu_show_common, pre-existing)
#
# --- mainline ---
# d8010d4ba43e (v6.16-rc6, initial TSA sysfs):
# "Vulnerable" (TSA_MITIGATION_NONE)
# "Vulnerable: No microcode" (TSA_MITIGATION_UCODE_NEEDED)
# "Mitigation: Clear CPU buffers: user/kernel boundary" (TSA_MITIGATION_USER_KERNEL)
# "Mitigation: Clear CPU buffers: VM" (TSA_MITIGATION_VM)
# "Mitigation: Clear CPU buffers" (TSA_MITIGATION_FULL)
# 6b21d2f0dc73 (v6.17-rc1, attack vector controls):
# no string changes; only mitigation selection logic changed
# (AUTO can now resolve to USER_KERNEL or VM based on attack vector config)
#
# --- stable backports ---
# 6.16.y: d8010d4ba43e (same as mainline), same strings.
# 6.17.y: has 6b21d2f0dc73 (attack vector controls), same strings.
# 5.10.y (78192f511f40), 5.15.y (f2b75f1368af), 6.1.y (d12145e8454f),
# 6.6.y (90293047df18), 6.12.y (7a0395f6607a), 6.15.y (ab0f6573b211):
# different UCODE_NEEDED string:
# "Vulnerable: Clear CPU buffers attempted, no microcode" (TSA_MITIGATION_UCODE_NEEDED)
# all other strings identical to mainline.
# default is FULL (no AUTO enum); USER_KERNEL/VM only via cmdline tsa=user/tsa=vm.
# VM-forced mitigation: when UCODE_NEEDED and running in a VM, forces FULL
# (stable-only logic, not in mainline).
#
# --- RHEL/CentOS ---
# rocky9 (5.14-based), rocky10 (6.12-based): same strings as mainline.
# "Vulnerable: No microcode" for UCODE_NEEDED (matches mainline, NOT the stable variant).
# rocky8 (4.18-based), centos7 (3.10-based): no TSA support.
#
# all messages start with either "Not affected", "Mitigation", or "Vulnerable"
status=$ret_sys_interface_check_status
fi
if [ "$opt_sysfs_only" != 1 ]; then
check_has_vmm
# Override: when running as a hypervisor, "user/kernel boundary" mode
# (tsa=user) leaves the VM exit boundary uncovered — guests can exploit
# TSA to leak host data. The kernel correctly reports its own mode, but
# the script must flag this as insufficient for a VMM host.
if [ "$sys_interface_available" = 1 ] && [ "$g_has_vmm" != 0 ]; then
if echo "$ret_sys_interface_check_fullmsg" | grep -q 'user/kernel boundary'; then
status=VULN
msg="Vulnerable: TSA mitigation limited to user/kernel boundary (tsa=user), VM exit boundary is not covered"
fi
fi
pr_info_nol "* Kernel supports TSA mitigation: "
kernel_tsa=''
kernel_tsa_err=''
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
kernel_tsa="found TSA mitigation message in kernel image"
fi
if [ -z "$kernel_tsa" ] && is_x86_kernel && [ -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 grep -q 'tsa_select_mitigation' "$opt_map"; then
kernel_tsa="found tsa_select_mitigation in System.map"
fi
fi
if [ -n "$kernel_tsa" ]; then
pstatus green YES "$kernel_tsa"
elif [ -n "$kernel_tsa_err" ]; then
pstatus yellow UNKNOWN "$kernel_tsa_err"
else
pstatus yellow NO
fi
if is_amd || is_hygon; then
pr_info_nol "* CPU explicitly indicates not vulnerable to TSA-L1 (TSA_L1_NO): "
if [ "$cap_tsa_l1_no" = 1 ]; then
pstatus green YES
elif [ "$cap_tsa_l1_no" = 0 ]; then
pstatus yellow NO
else
pstatus yellow UNKNOWN "couldn't read CPUID leaf 0x80000021"
fi
pr_info_nol "* Microcode supports VERW buffer clearing: "
if [ "$cap_verw_clear" = 1 ]; then
pstatus green YES
elif [ "$cap_verw_clear" = 0 ]; then
pstatus yellow NO
else
pstatus yellow UNKNOWN "couldn't read CPUID leaf 0x80000021"
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!"
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 [ -z "$msg" ]; then
# if msg is empty, sysfs check didn't fill it, rely on our own test
if [ "$opt_sysfs_only" != 1 ]; then
# No --paranoid SMT check here, unlike TSA-SQ (CVE-2024-36350).
# The kernel's cpu_bugs_smt_update() enables cpu_buf_idle_clear
# (VERW before idle) specifically for TSA-SQ cross-thread leakage,
# with the comment "TSA-SQ can potentially lead to info leakage
# between SMT threads" — TSA-L1 is not mentioned. Until the kernel
# flags TSA-L1 as having cross-thread SMT exposure, we follow its
# assessment and do not require SMT disabled in paranoid mode.
if [ "$cap_verw_clear" = 1 ] && [ -n "$kernel_tsa" ]; then
pvulnstatus "$cve" OK "Both kernel and microcode mitigate the vulnerability"
elif [ "$cap_verw_clear" = 1 ]; then
pvulnstatus "$cve" VULN "Microcode supports mitigation but kernel is too old"
explain "Update your kernel to a version that supports CONFIG_MITIGATION_TSA (Linux 6.16+),\n " \
"or check if your distribution has backported the TSA mitigation."
elif [ -n "$kernel_tsa" ]; then
pvulnstatus "$cve" VULN "Kernel supports mitigation but microcode is too old"
explain "Update your CPU microcode via a BIOS/firmware update from your OEM.\n " \
"The microcode must expose the VERW_CLEAR capability (CPUID 0x80000021 EAX bit 5)."
else
pvulnstatus "$cve" VULN "Neither kernel nor microcode mitigate the vulnerability"
explain "Both a kernel update (CONFIG_MITIGATION_TSA, Linux 6.16+) and a microcode/firmware update\n " \
"from your OEM are needed to mitigate this vulnerability."
fi
else
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
fi
else
pvulnstatus "$cve" "$status" "$msg"
if echo "$msg" | grep -q 'VM exit boundary'; then
explain "This system runs a hypervisor but TSA mitigation only clears CPU buffers at\n " \
"user/kernel transitions (tsa=user). Guests can exploit TSA to leak host data\n " \
"across VM exit. Use \`tsa=on\` (or remove \`tsa=user\`) to cover both boundaries."
fi
fi
}
check_CVE_2024_36357_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
}

View File

@@ -0,0 +1,56 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2024-45332, BPI, Branch Privilege Injection
check_CVE_2024_45332() {
check_cve 'CVE-2024-45332'
}
check_CVE_2024_45332_linux() {
local status sys_interface_available msg
status=UNK
sys_interface_available=0
msg=''
# There is no dedicated sysfs file for this vulnerability, and no kernel
# mitigation code. The fix is purely a microcode update that corrects the
# asynchronous branch predictor update timing so that eIBRS and IBPB work
# as originally intended. There is no new CPUID bit, MSR bit, or ARCH_CAP
# flag to detect the fix, so we hardcode known-fixing microcode versions
# per CPU (see bpi_ucode_list in is_cpu_affected).
# shellcheck disable=SC2154
if ! is_cpu_affected "$cve"; then
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif [ -z "$g_bpi_fixed_ucode_version" ]; then
# CPU matched the model blacklist but has no known fixing microcode
# (likely an EOL stepping that Intel won't release a fix for)
pvulnstatus "$cve" VULN "your CPU is affected and no microcode update is available for your CPU stepping"
explain "CVE-2024-45332 (Branch Privilege Injection) is a race condition in the branch predictor\n" \
"that undermines eIBRS and IBPB protections. The fix is a microcode update, but no\n" \
"update is available for your specific CPU stepping."
else
pr_info_nol "* BPI is mitigated by microcode: "
if [ -z "$cpu_ucode" ]; then
pstatus yellow UNKNOWN "couldn't get your microcode version"
pvulnstatus "$cve" UNK "couldn't detect microcode version to verify mitigation"
elif [ "$cpu_ucode" -lt "$g_bpi_fixed_ucode_version" ]; then
pstatus yellow NO "You have ucode $(printf "0x%x" "$cpu_ucode") and version $(printf "0x%x" "$g_bpi_fixed_ucode_version") minimum is required"
pvulnstatus "$cve" VULN "Your microcode is too old to mitigate the vulnerability"
explain "CVE-2024-45332 (Branch Privilege Injection) is a race condition in the branch predictor\n" \
"that undermines eIBRS and IBPB protections. The fix is a microcode update only.\n" \
"No kernel changes are required."
else
pstatus green YES "You have ucode $(printf "0x%x" "$cpu_ucode") which is recent enough (>= $(printf "0x%x" "$g_bpi_fixed_ucode_version"))"
pvulnstatus "$cve" OK "Your microcode mitigates the vulnerability"
fi
fi
}
check_CVE_2024_45332_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
}

147
src/vulns/CVE-2025-40300.sh Normal file
View File

@@ -0,0 +1,147 @@
# vim: set ts=4 sw=4 sts=4 et:
###############################
# CVE-2025-40300, VMScape, VM-Exit Stale Branch Prediction
check_CVE_2025_40300() {
check_cve 'CVE-2025-40300'
}
check_CVE_2025_40300_linux() {
local status sys_interface_available msg kernel_vmscape kernel_vmscape_err
status=UNK
sys_interface_available=0
msg=''
if sys_interface_check "$VULN_SYSFS_BASE/vmscape"; then
# this kernel has the /sys interface, trust it over everything
sys_interface_available=1
#
# Kernel source inventory for vmscape, traced via git blame:
#
# --- sysfs messages ---
# all versions:
# "Not affected" (cpu_show_common, pre-existing)
#
# --- mainline ---
# a508cec6e521 (v6.17-rc6, initial vmscape sysfs):
# "Vulnerable" (VMSCAPE_MITIGATION_NONE)
# "Mitigation: IBPB before exit to userspace" (VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER)
# 2f8f17341 (v6.17-rc6, vmscape_update_mitigation):
# "Mitigation: IBPB on VMEXIT" (VMSCAPE_MITIGATION_IBPB_ON_VMEXIT)
# (when retbleed uses IBPB or srso uses IBPB_ON_VMEXIT)
#
# --- stable backports ---
# 6.16.x (v6.16.7): identical to mainline (d83e6111337f)
# 6.12.x (v6.12.47): identical to mainline (7c62c442b6eb)
# 6.6.x (v6.6.106): identical to mainline (813cb831439c)
# 6.1.x (v6.1.152): identical strings; uses VULNBL_INTEL_STEPPINGS macro,
# missing ARROWLAKE_U, ATOM_CRESTMONT_X, AMD 0x1a.
# Uses ALDERLAKE_N instead of type-specific ALDERLAKE split. (304d1fb275af)
#
# --- RHEL/CentOS ---
# Not yet backported.
#
# --- Kconfig symbols ---
# a508cec6e521 (v6.17-rc6): CONFIG_MITIGATION_VMSCAPE (default y)
# depends on KVM
#
# --- kernel functions (for $opt_map / System.map) ---
# a508cec6e521 (v6.17-rc6): vmscape_select_mitigation(),
# vmscape_update_mitigation(), vmscape_apply_mitigation(),
# vmscape_parse_cmdline(), vmscape_show_state()
#
# --- CPU affection logic (for is_cpu_affected) ---
# X86_BUG_VMSCAPE is set when ALL conditions are true:
# 1. CPU matches model blacklist
# 2. X86_FEATURE_HYPERVISOR is NOT set (bare metal only)
# a508cec6e521 (v6.17-rc6, initial model list):
# Intel: SKYLAKE_X, SKYLAKE_L, SKYLAKE, KABYLAKE_L, KABYLAKE,
# CANNONLAKE_L, COMETLAKE, COMETLAKE_L, ALDERLAKE,
# ALDERLAKE_L, RAPTORLAKE, RAPTORLAKE_P, RAPTORLAKE_S,
# METEORLAKE_L, ARROWLAKE_H, ARROWLAKE, ARROWLAKE_U,
# LUNARLAKE_M, SAPPHIRERAPIDS_X, GRANITERAPIDS_X,
# EMERALDRAPIDS_X, ATOM_GRACEMONT, ATOM_CRESTMONT_X
# AMD: family 0x17 (Zen 1/+/2), family 0x19 (Zen 3/4),
# family 0x1a (Zen 5)
# Hygon: family 0x18
# 8a68d64bb103 (v6.17-rc6, added old Intel CPUs):
# Intel: + SANDYBRIDGE_X, SANDYBRIDGE, IVYBRIDGE_X, IVYBRIDGE,
# HASWELL, HASWELL_L, HASWELL_G, HASWELL_X,
# BROADWELL_D, BROADWELL_X, BROADWELL_G, BROADWELL
# Intel NOT affected: ICELAKE_*, TIGERLAKE_*, LAKEFIELD, ROCKETLAKE,
# ATOM_TREMONT_*, ATOM_GOLDMONT_*
# immunity: no ARCH_CAP bits — determination is purely via blacklist
# note: bare metal only (X86_FEATURE_HYPERVISOR excludes guests)
# vendor scope: Intel + AMD + Hygon
#
# all messages start with either "Not affected", "Vulnerable", or "Mitigation"
status=$ret_sys_interface_check_status
fi
if [ "$opt_sysfs_only" != 1 ]; then
check_has_vmm
pr_info_nol "* Kernel supports VMScape mitigation: "
kernel_vmscape=''
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
kernel_vmscape="found vmscape in kernel image"
fi
if [ -z "$kernel_vmscape" ] && is_x86_kernel && [ -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 grep -q 'vmscape_select_mitigation' "$opt_map"; then
kernel_vmscape="found vmscape_select_mitigation in System.map"
fi
fi
if [ -n "$kernel_vmscape" ]; then
pstatus green YES "$kernel_vmscape"
elif [ -n "$kernel_vmscape_err" ]; then
pstatus yellow UNKNOWN "$kernel_vmscape_err"
else
pstatus yellow NO
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!"
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 [ -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_has_vmm" = 0 ]; then
pvulnstatus "$cve" OK "this system is not running a hypervisor"
elif [ -n "$kernel_vmscape" ]; then
pvulnstatus "$cve" OK "Kernel mitigates the vulnerability"
elif [ -z "$kernel_vmscape" ] && [ -z "$kernel_vmscape_err" ]; then
pvulnstatus "$cve" VULN "Your kernel doesn't support VMScape mitigation"
explain "Update your kernel to a version that includes the VMScape mitigation (Linux 6.18+, or check\n" \
"if your distro has a backport). The mitigation issues IBPB before returning to userspace\n" \
"after a VM exit, preventing stale guest branch predictions from leaking host kernel memory."
else
pvulnstatus "$cve" UNK "couldn't determine mitigation status: $kernel_vmscape_err"
fi
else
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
fi
else
pvulnstatus "$cve" "$status" "$msg"
fi
}
check_CVE_2025_40300_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
}

151
src/vulns/CVE-2025-54505.sh Normal file
View File

@@ -0,0 +1,151 @@
# 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
}