Compare commits

...

3 Commits

Author SHA1 Message Date
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
32 changed files with 1112 additions and 918 deletions

View File

@@ -105,7 +105,8 @@ The entire tool is a single bash script with no external script dependencies. Ke
- **Output/logging functions** (~line 253): `pr_warn`, `pr_info`, `pr_verbose`, `pr_debug`, `explain`, `pstatus`, `pvulnstatus` - verbosity-aware output with color support - **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 - **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_arm64_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 - **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` - **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) - **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) - **Vulnerability checks**: 19 `check_CVE_<year>_<number>()` functions, each with `_linux()` and `_bsd()` variants. Uses whitelist logic (assumes affected unless proven otherwise)
@@ -117,7 +118,7 @@ The entire tool is a single bash script with no external script dependencies. Ke
Two JSON formats are available via `--batch`: Two JSON formats are available via `--batch`:
- **`--batch json`** (comprehensive): A top-level object with five sections: - **`--batch json`** (comprehensive): A top-level object with five sections:
- `meta` — script version, format version, timestamp, run mode flags (`run_as_root`, `reduced_accuracy`, `mocked`, `paranoid`, `sysfs_only`, `extra`) - `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 - `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``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 - `cpu_microcode``installed_version`, `latest_version`, `microcode_up_to_date`, `is_blacklisted`, firmware DB source/info
@@ -160,7 +161,7 @@ This works because the kernel always has direct access to CPUID (it doesn't need
**Rules:** **Rules:**
- This is strictly a fallback: `read_cpuid` via `/dev/cpu/N/cpuid` remains the primary method. - 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 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 (`$opt_runtime = 1`), since `/proc/cpuinfo` is not available in no-runtime mode. - 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. - 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). - 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).
@@ -183,7 +184,7 @@ read_cpuid 0x7 0x0 $EDX 31 1 1
ret=$? ret=$?
if [ $ret = $READ_CPUID_RET_OK ]; then if [ $ret = $READ_CPUID_RET_OK ]; then
cap_ssbd='Intel SSBD' cap_ssbd='Intel SSBD'
elif [ $ret = $READ_CPUID_RET_ERR ] && [ "$opt_runtime" = 1 ]; then elif [ $ret = $READ_CPUID_RET_ERR ] && [ "$g_mode" = live ]; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
if grep ^flags "$g_procfs/cpuinfo" | grep -qw ssbd; then if grep ^flags "$g_procfs/cpuinfo" | grep -qw ssbd; then
cap_ssbd='Intel SSBD (cpuinfo)' cap_ssbd='Intel SSBD (cpuinfo)'
@@ -391,29 +392,42 @@ This is where the real detection lives. Check for mitigations at each layer:
Each source may independently be unavailable (no-runtime mode without the file, or stripped kernel), so check all that are present. A match in any one confirms kernel support. Each source may independently be unavailable (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 ARM64 kernel (or vice versa) in offline mode, so always guard arch-specific checks with `is_arm64_kernel` or `is_x86_kernel` from `src/libs/365_kernel_arch.sh`. This prevents searching for irrelevant strings (e.g. x86 `spec_store_bypass` in an ARM64 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). Example: **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 ```sh
# x86-specific kernel image search: skip on ARM64 kernels # x86-specific kernel image search
if [ -n "$g_kernel" ] && ! is_arm64_kernel; then if [ -n "$g_kernel" ] && is_x86_kernel; then
mitigation=$("${opt_arch_prefix}strings" "$g_kernel" | grep x86_specific_string) mitigation=$("${opt_arch_prefix}strings" "$g_kernel" | grep x86_specific_string)
fi fi
# ARM64-specific System.map search: skip on x86 kernels # ARM-specific System.map search
if [ -n "$opt_map" ] && is_arm64_kernel; then if [ -n "$opt_map" ] && is_arm_kernel; then
mitigation=$(grep -w arm64_mitigation_function "$opt_map") 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 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_arm64_kernel`/`is_x86_kernel` rather than on `cpu_vendor`, because `cpu_vendor` reflects the host, not the target kernel. 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 [ "$opt_runtime" = 1 ]`, both when collecting the evidence in Phase 2 and when using it in Phase 4. In Phase 4, use explicit live/no-runtime branches so that live-only variables (e.g. cpuinfo flags, MSR values) are never referenced in the no-runtime path. - **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 ```sh
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
read_msr 0xADDRESS read_msr 0xADDRESS
ret=$? ret=$?
if [ "$ret" = "$READ_MSR_RET_OK" ]; then if [ "$ret" = "$READ_MSR_RET_OK" ]; then
# check specific bits in ret_read_msr_value_lo / ret_read_msr_value_hi # check specific bits in ret_read_msr_value_lo / ret_read_msr_value_hi
fi fi
else else
pstatus blue N/A "not testable in no-runtime mode" pstatus blue N/A "not testable in non-live mode"
fi fi
``` ```
@@ -798,12 +812,12 @@ CVEs that need VMM context should call `check_has_vmm` early in their `_linux()`
- **Never hardcode kernel or microcode versions** - detect capabilities directly (design principles 2 and 3). Exception: when a microcode fix has no detectable indicator, hardcode fixing versions per CPU (see principle 3). - **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). - **Assume affected by default** - only mark a CPU as unaffected when there is positive evidence (design principle 4).
- **Always handle both live and no-runtime modes** - use `$opt_runtime` to branch, and print `N/A "not testable in no-runtime mode"` for runtime-only checks when in no-runtime mode. - **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). - **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). - **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. - **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). - **All indentation must use 4 spaces** (CI enforces this via `fmt-check`; the vim modeline `et` enables expandtab).
- **Guard arch-specific checks with `is_arm64_kernel`/`is_x86_kernel`** - kernel image strings, kconfig symbols, and System.map functions are architecture-specific. Use the helpers from `src/libs/365_kernel_arch.sh` to avoid searching for irrelevant symbols and to select correct verdict messages. Never use `cpu_vendor` to branch on architecture in Phase 2/4 — it reflects the host, not the target kernel being inspected. - **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. - **Stay POSIX-compatible** - no bashisms, no GNU-only flags in portable code paths.
## Function documentation headers ## Function documentation headers

View File

@@ -59,7 +59,7 @@ Script metadata. Always value `1`; all data is in labels.
| Label | Values | Meaning | | Label | Values | Meaning |
|---|---|---| |---|---|---|
| `version` | string | Script version (e.g. `25.30.0250400123`) | | `version` | string | Script version (e.g. `25.30.0250400123`) |
| `mode` | `live` / `offline` | `live` = running on the active kernel; `offline` = inspecting a kernel image | | `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 | | `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) | | `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 | | `sysfs_only` | `true` / `false` | `--sysfs-only` mode: only the kernel's own sysfs report was used, not independent detection |
@@ -340,16 +340,22 @@ smc_vulnerability_status == 1
## Caveats and edge cases ## Caveats and edge cases
**Offline mode (`--kernel`)** **No-runtime mode (`--no-runtime`)**
`smc_system_info` will have no `kernel_release` or `kernel_arch` labels (those `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). come from `uname`, which reports the running kernel, not the inspected one).
`mode="offline"` in `smc_build_info` signals this. Offline mode is primarily `mode="no-runtime"` in `smc_build_info` signals this. No-runtime mode is
useful for pre-deployment auditing, not fleet runtime monitoring. primarily useful for pre-deployment auditing, not fleet runtime monitoring.
**`--no-hw`** **No-hardware mode (`--no-hw`)**
`smc_cpu_info` is not emitted. CPU and microcode labels are absent from all `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, queries. CVE checks that rely on hardware capability detection (`cap_*` flags,
MSR reads) will report `unknown` status. MSR reads) will report `unknown` status. `mode="no-hw"` in `smc_build_info`
signals this.
**Hardware-only mode (`--hw-only`)**
Only hardware detection is performed; CVE checks are skipped. `smc_cpu_info`
is emitted but no `smc_vuln` metrics appear. `mode="hw-only"` in
`smc_build_info` signals this.
**`--sysfs-only`** **`--sysfs-only`**
The script trusts the kernel's sysfs report (`/sys/devices/system/cpu/vulnerabilities/`) The script trusts the kernel's sysfs report (`/sys/devices/system/cpu/vulnerabilities/`)

View File

@@ -125,6 +125,13 @@ opt_vmm=-1
opt_allow_msr_write=0 opt_allow_msr_write=0
opt_cpu=0 opt_cpu=0
opt_explain=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_paranoid=0
opt_extra=0 opt_extra=0
opt_mock=0 opt_mock=0

View File

@@ -344,3 +344,16 @@ if [ "$opt_runtime" = 0 ] && [ -z "$opt_kernel" ] && [ -z "$opt_config" ] && [ -
pr_warn "Option --no-runtime requires at least one of --kernel, --config, or --map" pr_warn "Option --no-runtime requires at least one of --kernel, --config, or --map"
exit 255 exit 255
fi 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

@@ -66,17 +66,8 @@ _json_bool() {
# Sets: g_json_meta # Sets: g_json_meta
# shellcheck disable=SC2034 # shellcheck disable=SC2034
_build_json_meta() { _build_json_meta() {
local timestamp mode local timestamp
timestamp=$(date -u '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || echo "unknown") timestamp=$(date -u '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || echo "unknown")
if [ "$opt_hw_only" = 1 ]; then
mode="hw-only"
elif [ "$opt_no_hw" = 1 ]; then
mode="no-hw"
elif [ "$opt_runtime" = 0 ]; then
mode="no-runtime"
else
mode="live"
fi
local run_as_root local run_as_root
if [ "$(id -u)" -eq 0 ]; then if [ "$(id -u)" -eq 0 ]; then
run_as_root='true' run_as_root='true'
@@ -87,7 +78,7 @@ _build_json_meta() {
"$(_json_str "$VERSION")" \ "$(_json_str "$VERSION")" \
"$(_json_str "$timestamp")" \ "$(_json_str "$timestamp")" \
"$(_json_str "$g_os")" \ "$(_json_str "$g_os")" \
"$mode" \ "$g_mode" \
"$run_as_root" \ "$run_as_root" \
"$(_json_bool "${g_bad_accuracy:-0}")" \ "$(_json_bool "${g_bad_accuracy:-0}")" \
"$(_json_bool "$opt_paranoid")" \ "$(_json_bool "$opt_paranoid")" \
@@ -100,7 +91,7 @@ _build_json_meta() {
# shellcheck disable=SC2034 # shellcheck disable=SC2034
_build_json_system() { _build_json_system() {
local kernel_release kernel_version kernel_arch smt_val local kernel_release kernel_version kernel_arch smt_val
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
kernel_release=$(uname -r) kernel_release=$(uname -r)
kernel_version=$(uname -v) kernel_version=$(uname -v)
kernel_arch=$(uname -m) kernel_arch=$(uname -m)
@@ -404,7 +395,7 @@ _emit_prometheus() {
# shellcheck disable=SC2034 # shellcheck disable=SC2034
_build_prometheus_system_info() { _build_prometheus_system_info() {
local kernel_release kernel_arch hypervisor_host sys_labels local kernel_release kernel_arch hypervisor_host sys_labels
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
kernel_release=$(uname -r 2>/dev/null || true) kernel_release=$(uname -r 2>/dev/null || true)
kernel_arch=$(uname -m 2>/dev/null || true) kernel_arch=$(uname -m 2>/dev/null || true)
else else

View File

@@ -21,6 +21,28 @@ is_intel() {
return 1 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 # Check whether SMT (HyperThreading) is enabled on the system
# Returns: 0 if SMT enabled, 1 otherwise # Returns: 0 if SMT enabled, 1 otherwise
is_cpu_smt_enabled() { is_cpu_smt_enabled() {

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'
}

View File

@@ -18,7 +18,7 @@ if [ "$g_os" = Darwin ] || [ "$g_os" = VMkernel ]; then
fi fi
# check for mode selection inconsistency # check for mode selection inconsistency
if [ "$opt_hw_only" = 1 ]; then if [ "$g_mode" = hw-only ]; then
if [ "$opt_cve_all" = 0 ]; then if [ "$opt_cve_all" = 0 ]; then
show_usage show_usage
echo "$0: error: incompatible modes specified, --hw-only vs --variant" >&2 echo "$0: error: incompatible modes specified, --hw-only vs --variant" >&2
@@ -89,7 +89,7 @@ if [ "$opt_cpu" != all ] && [ "$opt_cpu" -gt "$g_max_core_id" ]; then
exit 255 exit 255
fi fi
if [ "$opt_runtime" = 1 ]; then if has_runtime; then
pr_info "Checking for vulnerabilities on current system" pr_info "Checking for vulnerabilities on current system"
# try to find the image of the current running kernel # try to find the image of the current running kernel
@@ -226,7 +226,7 @@ if [ -e "$opt_kernel" ]; then
if ! command -v "${opt_arch_prefix}readelf" >/dev/null 2>&1; then if ! command -v "${opt_arch_prefix}readelf" >/dev/null 2>&1; then
pr_debug "readelf not found" pr_debug "readelf not found"
g_kernel_err="missing '${opt_arch_prefix}readelf' tool, please install it, usually it's in the 'binutils' package" g_kernel_err="missing '${opt_arch_prefix}readelf' tool, please install it, usually it's in the 'binutils' package"
elif [ "$opt_sysfs_only" = 1 ] || [ "$opt_hw_only" = 1 ]; then elif [ "$opt_sysfs_only" = 1 ] || [ "$g_mode" = hw-only ]; then
g_kernel_err='kernel image decompression skipped' g_kernel_err='kernel image decompression skipped'
else else
extract_kernel "$opt_kernel" extract_kernel "$opt_kernel"
@@ -251,7 +251,7 @@ else
fi fi
if [ -n "$g_kernel_version" ]; then if [ -n "$g_kernel_version" ]; then
# in live mode, check if the img we found is the correct one # in live mode, check if the img we found is the correct one
if [ "$opt_runtime" = 1 ]; then if has_runtime; then
pr_verbose "Kernel image is \033[35m$g_kernel_version" pr_verbose "Kernel image is \033[35m$g_kernel_version"
if ! echo "$g_kernel_version" | grep -qF "$(uname -r)"; then if ! echo "$g_kernel_version" | grep -qF "$(uname -r)"; then
pr_warn "Possible discrepancy between your running kernel '$(uname -r)' and the image '$g_kernel_version' we found ($opt_kernel), results might be incorrect" pr_warn "Possible discrepancy between your running kernel '$(uname -r)' and the image '$g_kernel_version' we found ($opt_kernel), results might be incorrect"
@@ -283,7 +283,7 @@ sys_interface_check() {
msg='' msg=''
ret_sys_interface_check_fullmsg='' ret_sys_interface_check_fullmsg=''
if [ "$opt_runtime" = 1 ] && [ "$opt_no_sysfs" = 0 ] && [ -r "$file" ]; then if has_runtime && [ "$opt_no_sysfs" = 0 ] && [ -r "$file" ]; then
: :
else else
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_SYSFS_$(basename "$file")_RET=1") g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_SYSFS_$(basename "$file")_RET=1")
@@ -352,7 +352,7 @@ sys_interface_check() {
check_kernel_info() { check_kernel_info() {
local config_display local config_display
pr_info "\033[1;34mKernel information\033[0m" pr_info "\033[1;34mKernel information\033[0m"
if [ "$opt_runtime" = 1 ]; then if has_runtime; then
pr_info "* Kernel is \033[35m$g_os $(uname -r) $(uname -v) $(uname -m)\033[0m" pr_info "* Kernel is \033[35m$g_os $(uname -r) $(uname -v) $(uname -m)\033[0m"
elif [ -n "$g_kernel_version" ]; then elif [ -n "$g_kernel_version" ]; then
pr_info "* Kernel is \033[35m$g_kernel_version\033[0m" pr_info "* Kernel is \033[35m$g_kernel_version\033[0m"
@@ -456,7 +456,7 @@ check_cpu() {
ret=invalid ret=invalid
pstatus yellow NO "unknown CPU" pstatus yellow NO "unknown CPU"
fi fi
if [ -z "$cap_ibrs" ] && [ $ret = $READ_CPUID_RET_ERR ] && [ "$opt_runtime" = 1 ]; then if [ -z "$cap_ibrs" ] && [ $ret = $READ_CPUID_RET_ERR ] && has_runtime; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
if grep ^flags "$g_procfs/cpuinfo" | grep -qw ibrs; then if grep ^flags "$g_procfs/cpuinfo" | grep -qw ibrs; then
cap_ibrs='IBRS (cpuinfo)' cap_ibrs='IBRS (cpuinfo)'
@@ -533,7 +533,7 @@ check_cpu() {
if [ $ret = $READ_CPUID_RET_OK ]; then if [ $ret = $READ_CPUID_RET_OK ]; then
cap_ibpb='IBPB_SUPPORT' cap_ibpb='IBPB_SUPPORT'
pstatus green YES "IBPB_SUPPORT feature bit" pstatus green YES "IBPB_SUPPORT feature bit"
elif [ $ret = $READ_CPUID_RET_ERR ] && [ "$opt_runtime" = 1 ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw ibpb; then elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && grep ^flags "$g_procfs/cpuinfo" | grep -qw ibpb; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
cap_ibpb='IBPB (cpuinfo)' cap_ibpb='IBPB (cpuinfo)'
pstatus green YES "ibpb flag in $g_procfs/cpuinfo" pstatus green YES "ibpb flag in $g_procfs/cpuinfo"
@@ -604,7 +604,7 @@ check_cpu() {
ret=invalid ret=invalid
pstatus yellow UNKNOWN "unknown CPU" pstatus yellow UNKNOWN "unknown CPU"
fi fi
if [ -z "$cap_stibp" ] && [ $ret = $READ_CPUID_RET_ERR ] && [ "$opt_runtime" = 1 ]; then if [ -z "$cap_stibp" ] && [ $ret = $READ_CPUID_RET_ERR ] && has_runtime; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
if grep ^flags "$g_procfs/cpuinfo" | grep -qw stibp; then if grep ^flags "$g_procfs/cpuinfo" | grep -qw stibp; then
cap_stibp='STIBP (cpuinfo)' cap_stibp='STIBP (cpuinfo)'
@@ -676,7 +676,7 @@ check_cpu() {
fi fi
fi fi
if [ -z "$cap_ssbd" ] && [ "$ret24" = $READ_CPUID_RET_ERR ] && [ "$ret25" = $READ_CPUID_RET_ERR ] && [ "$opt_runtime" = 1 ]; then if [ -z "$cap_ssbd" ] && [ "$ret24" = $READ_CPUID_RET_ERR ] && [ "$ret25" = $READ_CPUID_RET_ERR ] && has_runtime; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
if grep ^flags "$g_procfs/cpuinfo" | grep -qw ssbd; then if grep ^flags "$g_procfs/cpuinfo" | grep -qw ssbd; then
cap_ssbd='SSBD (cpuinfo)' cap_ssbd='SSBD (cpuinfo)'
@@ -740,7 +740,7 @@ check_cpu() {
if [ $ret = $READ_CPUID_RET_OK ]; then if [ $ret = $READ_CPUID_RET_OK ]; then
pstatus green YES "L1D flush feature bit" pstatus green YES "L1D flush feature bit"
cap_l1df=1 cap_l1df=1
elif [ $ret = $READ_CPUID_RET_ERR ] && [ "$opt_runtime" = 1 ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw flush_l1d; then elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && grep ^flags "$g_procfs/cpuinfo" | grep -qw flush_l1d; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
pstatus green YES "flush_l1d flag in $g_procfs/cpuinfo" pstatus green YES "flush_l1d flag in $g_procfs/cpuinfo"
cap_l1df=1 cap_l1df=1
@@ -760,7 +760,7 @@ check_cpu() {
if [ $ret = $READ_CPUID_RET_OK ]; then if [ $ret = $READ_CPUID_RET_OK ]; then
cap_md_clear=1 cap_md_clear=1
pstatus green YES "MD_CLEAR feature bit" pstatus green YES "MD_CLEAR feature bit"
elif [ $ret = $READ_CPUID_RET_ERR ] && [ "$opt_runtime" = 1 ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw md_clear; then elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && grep ^flags "$g_procfs/cpuinfo" | grep -qw md_clear; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
cap_md_clear=1 cap_md_clear=1
pstatus green YES "md_clear flag in $g_procfs/cpuinfo" pstatus green YES "md_clear flag in $g_procfs/cpuinfo"
@@ -830,7 +830,7 @@ check_cpu() {
if [ $ret = $READ_CPUID_RET_OK ]; then if [ $ret = $READ_CPUID_RET_OK ]; then
pstatus green YES pstatus green YES
cap_arch_capabilities=1 cap_arch_capabilities=1
elif [ $ret = $READ_CPUID_RET_ERR ] && [ "$opt_runtime" = 1 ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw arch_capabilities; then elif [ $ret = $READ_CPUID_RET_ERR ] && has_runtime && grep ^flags "$g_procfs/cpuinfo" | grep -qw arch_capabilities; then
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo # CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
pstatus green YES "arch_capabilities flag in $g_procfs/cpuinfo" pstatus green YES "arch_capabilities flag in $g_procfs/cpuinfo"
cap_arch_capabilities=1 cap_arch_capabilities=1

View File

@@ -14,7 +14,7 @@ fi
pr_info pr_info
if [ "$opt_no_hw" = 0 ] && [ -z "$opt_arch_prefix" ]; then if [ "$g_mode" != no-hw ] && [ -z "$opt_arch_prefix" ]; then
pr_info "\033[1;34mHardware check\033[0m" pr_info "\033[1;34mHardware check\033[0m"
check_cpu check_cpu
check_cpu_vulnerabilities check_cpu_vulnerabilities
@@ -24,7 +24,7 @@ fi
# Build JSON system/cpu/microcode sections (after check_cpu has populated cap_* vars and VMM detection) # 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 if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "json" ]; then
_build_json_system _build_json_system
if [ "$opt_no_hw" = 0 ] && [ -z "$opt_arch_prefix" ]; then if [ "$g_mode" != no-hw ] && [ -z "$opt_arch_prefix" ]; then
_build_json_cpu _build_json_cpu
_build_json_cpu_microcode _build_json_cpu_microcode
fi fi
@@ -33,18 +33,22 @@ fi
# Build Prometheus info metric lines (same timing requirement as JSON builders above) # Build Prometheus info metric lines (same timing requirement as JSON builders above)
if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "prometheus" ]; then if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "prometheus" ]; then
_build_prometheus_system_info _build_prometheus_system_info
if [ "$opt_no_hw" = 0 ] && [ -z "$opt_arch_prefix" ]; then if [ "$g_mode" != no-hw ] && [ -z "$opt_arch_prefix" ]; then
_build_prometheus_cpu_info _build_prometheus_cpu_info
fi fi
fi fi
# now run the checks the user asked for # now run the checks the user asked for (hw-only mode skips CVE checks)
for cve in $g_supported_cve_list; do 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 if [ "$opt_cve_all" = 1 ] || echo "$opt_cve_list" | grep -qw "$cve"; then
check_"$(echo "$cve" | tr - _)" check_"$(echo "$cve" | tr - _)"
pr_info pr_info
fi fi
done done
fi # g_mode != hw-only
if [ -n "$g_final_summary" ]; then if [ -n "$g_final_summary" ]; then
pr_info "> \033[46m\033[30mSUMMARY:\033[0m$g_final_summary" pr_info "> \033[46m\033[30mSUMMARY:\033[0m$g_final_summary"
@@ -171,15 +175,7 @@ fi
if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "prometheus" ]; then if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "prometheus" ]; then
prom_run_as_root='false' prom_run_as_root='false'
[ "$(id -u)" -eq 0 ] && prom_run_as_root='true' [ "$(id -u)" -eq 0 ] && prom_run_as_root='true'
if [ "$opt_hw_only" = 1 ]; then prom_mode="$g_mode"
prom_mode='hw-only'
elif [ "$opt_no_hw" = 1 ]; then
prom_mode='no-hw'
elif [ "$opt_runtime" = 0 ]; then
prom_mode='no-runtime'
else
prom_mode='live'
fi
prom_paranoid='false' prom_paranoid='false'
[ "$opt_paranoid" = 1 ] && prom_paranoid='true' [ "$opt_paranoid" = 1 ] && prom_paranoid='true'
prom_sysfs_only='false' prom_sysfs_only='false'

View File

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

View File

@@ -125,8 +125,11 @@ check_mmio_linux() {
fi fi
if [ "$opt_sysfs_only" != 1 ]; then if [ "$opt_sysfs_only" != 1 ]; then
pr_info_nol "* Kernel supports MMIO Stale Data mitigation: " # MMIO Stale Data is Intel-only; skip x86-specific kernel/MSR checks on non-x86 kernels
kernel_mmio='' kernel_mmio=''
kernel_mmio_can_tell=0
if is_x86_kernel; then
pr_info_nol "* Kernel supports MMIO Stale Data mitigation: "
kernel_mmio_can_tell=1 kernel_mmio_can_tell=1
if [ -n "$g_kernel_err" ]; then if [ -n "$g_kernel_err" ]; then
kernel_mmio_can_tell=0 kernel_mmio_can_tell=0
@@ -162,7 +165,7 @@ check_mmio_linux() {
pstatus yellow NO pstatus yellow NO
fi fi
if [ "$opt_runtime" = 1 ] && [ "$sys_interface_available" = 1 ]; then if [ "$g_mode" = live ] && [ "$sys_interface_available" = 1 ]; then
pr_info_nol "* Kernel mitigation is enabled and active: " pr_info_nol "* Kernel mitigation is enabled and active: "
if echo "$ret_sys_interface_check_fullmsg" | grep -qi ^mitigation; then if echo "$ret_sys_interface_check_fullmsg" | grep -qi ^mitigation; then
mmio_mitigated=1 mmio_mitigated=1
@@ -180,6 +183,7 @@ check_mmio_linux() {
pstatus yellow NO pstatus yellow NO
fi fi
fi fi
fi # is_x86_kernel
elif [ "$sys_interface_available" = 0 ]; then elif [ "$sys_interface_available" = 0 ]; then
# we have no sysfs but were asked to use it only! # we have no sysfs but were asked to use it only!
msg="/sys vulnerability interface use forced, but it's not available!" msg="/sys vulnerability interface use forced, but it's not available!"
@@ -194,7 +198,7 @@ check_mmio_linux() {
# compute mystatus and mymsg from our own logic # compute mystatus and mymsg from our own logic
if [ "$cap_fb_clear" = 1 ]; then if [ "$cap_fb_clear" = 1 ]; then
if [ -n "$kernel_mmio" ]; then if [ -n "$kernel_mmio" ]; then
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
# mitigation must also be enabled # mitigation must also be enabled
if [ "$mmio_mitigated" = 1 ]; then if [ "$mmio_mitigated" = 1 ]; then
if [ "$opt_paranoid" != 1 ] || [ "$mmio_smt_mitigated" = 1 ]; then if [ "$opt_paranoid" != 1 ] || [ "$mmio_smt_mitigated" = 1 ]; then

View File

@@ -173,10 +173,8 @@ check_CVE_0000_0001_linux() {
return return
fi fi
# --- arm64: no kernel mitigation available --- # --- ARM: no kernel mitigation available ---
local _sls_arch if is_arm_kernel; then
_sls_arch=$(uname -m 2>/dev/null || echo unknown)
if echo "$_sls_arch" | grep -qw 'aarch64'; then
pvulnstatus "$cve" VULN "no kernel mitigation available for arm64 SLS (CVE-2020-13844)" 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" \ 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" \ "GCC and Clang support -mharden-sls=all for aarch64, which inserts SB (Speculation Barrier)\n" \
@@ -186,7 +184,12 @@ check_CVE_0000_0001_linux() {
return return
fi fi
# --- method 1: kernel config check (x86_64) --- # --- 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='' local _sls_config=''
if [ -n "$opt_config" ] && [ -r "$opt_config" ]; then if [ -n "$opt_config" ] && [ -r "$opt_config" ]; then
pr_info_nol " * Kernel compiled with SLS mitigation: " pr_info_nol " * Kernel compiled with SLS mitigation: "

View File

@@ -256,6 +256,10 @@ check_CVE_2017_5715_linux() {
v2_vuln_module='' v2_vuln_module=''
v2_is_autoibrs=0 v2_is_autoibrs=0
# Mitigation 1 (IBRS/IBPB) and Mitigation 3 (sub-mitigations) are x86-only.
# On ARM64, only Mitigation 2 (branch predictor hardening) is relevant.
if is_x86_kernel; then
pr_info "* Mitigation 1" pr_info "* Mitigation 1"
g_ibrs_can_tell=0 g_ibrs_can_tell=0
@@ -265,7 +269,7 @@ check_CVE_2017_5715_linux() {
g_ibpb_supported='' g_ibpb_supported=''
g_ibpb_enabled='' g_ibpb_enabled=''
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
# in live mode, we can check for the ibrs_enabled file in debugfs # in live mode, we can check for the ibrs_enabled file in debugfs
# all versions of the patches have it (NOT the case of IBPB or KPTI) # all versions of the patches have it (NOT the case of IBPB or KPTI)
g_ibrs_can_tell=1 g_ibrs_can_tell=1
@@ -416,7 +420,7 @@ check_CVE_2017_5715_linux() {
fi fi
pr_info_nol " * IBRS enabled and active: " pr_info_nol " * IBRS enabled and active: "
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
if [ "$g_ibpb_enabled" = 2 ]; then if [ "$g_ibpb_enabled" = 2 ]; then
# if ibpb=2, ibrs is forcefully=0 # if ibpb=2, ibrs is forcefully=0
pstatus blue NO "IBPB used instead of IBRS in all kernel entrypoints" pstatus blue NO "IBPB used instead of IBRS in all kernel entrypoints"
@@ -467,7 +471,7 @@ check_CVE_2017_5715_linux() {
fi fi
pr_info_nol " * IBPB enabled and active: " pr_info_nol " * IBPB enabled and active: "
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
case "$g_ibpb_enabled" in case "$g_ibpb_enabled" in
"") "")
if [ "$g_ibrs_supported" = 1 ]; then if [ "$g_ibrs_supported" = 1 ]; then
@@ -487,10 +491,13 @@ check_CVE_2017_5715_linux() {
pstatus blue N/A "not testable in no-runtime mode" pstatus blue N/A "not testable in no-runtime mode"
fi fi
pr_info "* Mitigation 2" fi # is_x86_kernel (Mitigation 1)
pr_info_nol " * Kernel has branch predictor hardening (arm): "
bp_harden_can_tell=0 bp_harden_can_tell=0
bp_harden='' bp_harden=''
if is_arm_kernel; then
pr_info "* Mitigation 2"
pr_info_nol " * Kernel has branch predictor hardening (arm): "
if [ -r "$opt_config" ]; then if [ -r "$opt_config" ]; then
bp_harden_can_tell=1 bp_harden_can_tell=1
bp_harden=$(grep -w 'CONFIG_HARDEN_BRANCH_PREDICTOR=y' "$opt_config") bp_harden=$(grep -w 'CONFIG_HARDEN_BRANCH_PREDICTOR=y' "$opt_config")
@@ -514,6 +521,9 @@ check_CVE_2017_5715_linux() {
pstatus yellow UNKNOWN pstatus yellow UNKNOWN
fi fi
fi fi
fi
if is_x86_kernel; then
pr_info_nol " * Kernel compiled with retpoline option: " pr_info_nol " * Kernel compiled with retpoline option: "
# We check the RETPOLINE kernel options # We check the RETPOLINE kernel options
@@ -544,7 +554,7 @@ check_CVE_2017_5715_linux() {
# #
# since 5.15.28, this is now "Retpolines" as the implementation was switched to a generic one, # since 5.15.28, this is now "Retpolines" as the implementation was switched to a generic one,
# so we look for both "retpoline" and "retpolines" # so we look for both "retpoline" and "retpolines"
if [ "$opt_runtime" = 1 ] && [ -n "$ret_sys_interface_check_fullmsg" ]; then if [ "$g_mode" = live ] && [ -n "$ret_sys_interface_check_fullmsg" ]; then
if echo "$ret_sys_interface_check_fullmsg" | grep -qwi -e retpoline -e retpolines; then if echo "$ret_sys_interface_check_fullmsg" | grep -qwi -e retpoline -e retpolines; then
if echo "$ret_sys_interface_check_fullmsg" | grep -qwi minimal; then if echo "$ret_sys_interface_check_fullmsg" | grep -qwi minimal; then
retpoline_compiler=0 retpoline_compiler=0
@@ -595,7 +605,7 @@ check_CVE_2017_5715_linux() {
# only Red Hat has a tunable to disable it on runtime # only Red Hat has a tunable to disable it on runtime
retp_enabled=-1 retp_enabled=-1
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
if [ -e "$g_specex_knob_dir/retp_enabled" ]; then if [ -e "$g_specex_knob_dir/retp_enabled" ]; then
retp_enabled=$(cat "$g_specex_knob_dir/retp_enabled" 2>/dev/null) retp_enabled=$(cat "$g_specex_knob_dir/retp_enabled" 2>/dev/null)
pr_debug "retpoline: found $g_specex_knob_dir/retp_enabled=$retp_enabled" pr_debug "retpoline: found $g_specex_knob_dir/retp_enabled=$retp_enabled"
@@ -625,7 +635,7 @@ check_CVE_2017_5715_linux() {
if is_vulnerable_to_empty_rsb || [ "$opt_verbose" -ge 2 ]; then if is_vulnerable_to_empty_rsb || [ "$opt_verbose" -ge 2 ]; then
pr_info_nol " * Kernel supports RSB filling: " pr_info_nol " * Kernel supports RSB filling: "
rsb_filling=0 rsb_filling=0
if [ "$opt_runtime" = 1 ] && [ "$opt_no_sysfs" != 1 ]; then if [ "$g_mode" = live ] && [ "$opt_no_sysfs" != 1 ]; then
# if we're live and we aren't denied looking into /sys, let's do it # if we're live and we aren't denied looking into /sys, let's do it
if echo "$ret_sys_interface_check_fullmsg" | grep -qw RSB; then if echo "$ret_sys_interface_check_fullmsg" | grep -qw RSB; then
rsb_filling=1 rsb_filling=1
@@ -718,7 +728,7 @@ check_CVE_2017_5715_linux() {
*", IBPB"* | *"; IBPB"*) v2_ibpb_mode=conditional ;; *", IBPB"* | *"; IBPB"*) v2_ibpb_mode=conditional ;;
*) v2_ibpb_mode=disabled ;; *) v2_ibpb_mode=disabled ;;
esac esac
elif [ "$opt_runtime" = 1 ]; then elif [ "$g_mode" = live ]; then
case "$g_ibpb_enabled" in case "$g_ibpb_enabled" in
2) v2_ibpb_mode=always-on ;; 2) v2_ibpb_mode=always-on ;;
1) v2_ibpb_mode=conditional ;; 1) v2_ibpb_mode=conditional ;;
@@ -816,7 +826,7 @@ check_CVE_2017_5715_linux() {
*"PBRSB-eIBRS: Vulnerable"*) v2_pbrsb_status=vulnerable ;; *"PBRSB-eIBRS: Vulnerable"*) v2_pbrsb_status=vulnerable ;;
*) v2_pbrsb_status=unknown ;; *) v2_pbrsb_status=unknown ;;
esac esac
elif [ "$opt_runtime" != 1 ] && [ -n "$g_kernel" ]; then elif [ "$g_mode" != live ] && [ -n "$g_kernel" ]; then
if grep -q 'PBRSB-eIBRS' "$g_kernel" 2>/dev/null; then if grep -q 'PBRSB-eIBRS' "$g_kernel" 2>/dev/null; then
v2_pbrsb_status=sw-sequence v2_pbrsb_status=sw-sequence
else else
@@ -847,7 +857,7 @@ check_CVE_2017_5715_linux() {
*"BHI: Vulnerable"*) v2_bhi_status=vulnerable ;; *"BHI: Vulnerable"*) v2_bhi_status=vulnerable ;;
*) v2_bhi_status=unknown ;; *) v2_bhi_status=unknown ;;
esac esac
elif [ "$opt_runtime" != 1 ] && [ -n "$opt_config" ] && [ -r "$opt_config" ]; then elif [ "$g_mode" != live ] && [ -n "$opt_config" ] && [ -r "$opt_config" ]; then
if grep -q '^CONFIG_\(MITIGATION_\)\?SPECTRE_BHI' "$opt_config"; then if grep -q '^CONFIG_\(MITIGATION_\)\?SPECTRE_BHI' "$opt_config"; then
if [ "$cap_bhi" = 1 ]; then if [ "$cap_bhi" = 1 ]; then
v2_bhi_status=bhi_dis_s v2_bhi_status=bhi_dis_s
@@ -871,7 +881,7 @@ check_CVE_2017_5715_linux() {
esac esac
# --- v2_vuln_module --- # --- v2_vuln_module ---
if [ "$opt_runtime" = 1 ] && [ -n "$ret_sys_interface_check_fullmsg" ]; then if [ "$g_mode" = live ] && [ -n "$ret_sys_interface_check_fullmsg" ]; then
pr_info_nol " * Non-retpoline module loaded: " pr_info_nol " * Non-retpoline module loaded: "
if echo "$ret_sys_interface_check_fullmsg" | grep -q 'vulnerable module loaded'; then if echo "$ret_sys_interface_check_fullmsg" | grep -q 'vulnerable module loaded'; then
v2_vuln_module=1 v2_vuln_module=1
@@ -882,6 +892,8 @@ check_CVE_2017_5715_linux() {
fi fi
fi fi
fi # is_x86_kernel (retpoline + Mitigation 3)
elif [ "$sys_interface_available" = 0 ]; then elif [ "$sys_interface_available" = 0 ]; then
# we have no sysfs but were asked to use it only! # we have no sysfs but were asked to use it only!
msg="/sys vulnerability interface use forced, but it's not available!" msg="/sys vulnerability interface use forced, but it's not available!"
@@ -903,9 +915,9 @@ check_CVE_2017_5715_linux() {
# ARM branch predictor hardening (unchanged) # ARM branch predictor hardening (unchanged)
if [ -n "$bp_harden" ]; then if [ -n "$bp_harden" ]; then
pvulnstatus "$cve" OK "Branch predictor hardening mitigates the vulnerability" pvulnstatus "$cve" OK "Branch predictor hardening mitigates the vulnerability"
elif [ -z "$bp_harden" ] && is_arm64_kernel; then elif [ -z "$bp_harden" ] && is_arm_kernel; then
pvulnstatus "$cve" VULN "Branch predictor hardening is needed to mitigate the vulnerability" pvulnstatus "$cve" VULN "Branch predictor hardening is needed to mitigate the vulnerability"
explain "Your kernel has not been compiled with the CONFIG_UNMAP_KERNEL_AT_EL0 option, recompile it with this option enabled." explain "Your kernel does not have branch predictor hardening. On kernels v5.10+, this code is compiled unconditionally so you may need a newer kernel. On older kernels (v4.16 to v5.9), recompile with the CONFIG_HARDEN_BRANCH_PREDICTOR option enabled."
# LFENCE-only is always VULN (reclassified in v5.17) # LFENCE-only is always VULN (reclassified in v5.17)
elif [ "$v2_base_mode" = "lfence" ]; then elif [ "$v2_base_mode" = "lfence" ]; then
@@ -970,7 +982,7 @@ check_CVE_2017_5715_linux() {
if [ -n "${SMC_MOCK_UNPRIVILEGED_BPF_DISABLED:-}" ]; then if [ -n "${SMC_MOCK_UNPRIVILEGED_BPF_DISABLED:-}" ]; then
_ebpf_disabled="$SMC_MOCK_UNPRIVILEGED_BPF_DISABLED" _ebpf_disabled="$SMC_MOCK_UNPRIVILEGED_BPF_DISABLED"
g_mocked=1 g_mocked=1
elif [ "$opt_runtime" = 1 ] && [ -r "$g_procfs/sys/kernel/unprivileged_bpf_disabled" ]; then elif [ "$g_mode" = live ] && [ -r "$g_procfs/sys/kernel/unprivileged_bpf_disabled" ]; then
_ebpf_disabled=$(cat "$g_procfs/sys/kernel/unprivileged_bpf_disabled" 2>/dev/null) _ebpf_disabled=$(cat "$g_procfs/sys/kernel/unprivileged_bpf_disabled" 2>/dev/null)
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_UNPRIVILEGED_BPF_DISABLED='$_ebpf_disabled'") g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_UNPRIVILEGED_BPF_DISABLED='$_ebpf_disabled'")
fi fi
@@ -1158,7 +1170,7 @@ check_CVE_2017_5715_linux() {
pvulnstatus "$cve" OK "Full IBPB is mitigating the vulnerability" pvulnstatus "$cve" OK "Full IBPB is mitigating the vulnerability"
# No-runtime mode fallback # No-runtime mode fallback
elif [ "$opt_runtime" != 1 ]; then elif [ "$g_mode" != live ]; then
if [ "$retpoline" = 1 ] && [ -n "$g_ibpb_supported" ]; then if [ "$retpoline" = 1 ] && [ -n "$g_ibpb_supported" ]; then
pvulnstatus "$cve" OK "no-runtime mode: kernel supports retpoline + IBPB to mitigate the vulnerability" pvulnstatus "$cve" OK "no-runtime mode: kernel supports retpoline + IBPB to mitigate the vulnerability"
elif [ -n "$g_ibrs_supported" ] && [ -n "$g_ibpb_supported" ]; then elif [ -n "$g_ibrs_supported" ] && [ -n "$g_ibpb_supported" ]; then

View File

@@ -101,37 +101,14 @@ check_CVE_2017_5753_linux() {
# For no-runtime analysis of these old kernels, match the specific instruction patterns. # For no-runtime analysis of these old kernels, match the specific instruction patterns.
if [ -z "$v1_kernel_mitigated" ]; then if [ -z "$v1_kernel_mitigated" ]; then
pr_info_nol "* Kernel has array_index_mask_nospec (v4.15 binary pattern): " pr_info_nol "* Kernel has array_index_mask_nospec (v4.15 binary pattern): "
# vanilla: look for the Linus' mask aka array_index_mask_nospec()
# that is inlined at least in raw_copy_from_user (__get_user_X symbols)
#mov PER_CPU_VAR(current_task), %_ASM_DX
#cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
#jae bad_get_user
# /* array_index_mask_nospec() are the 2 opcodes that follow */
#+sbb %_ASM_DX, %_ASM_DX
#+and %_ASM_DX, %_ASM_AX
#ASM_STAC
# x86 64bits: jae(0x0f 0x83 0x?? 0x?? 0x?? 0x??) sbb(0x48 0x19 0xd2) and(0x48 0x21 0xd0)
# x86 32bits: cmp(0x3b 0x82 0x?? 0x?? 0x00 0x00) jae(0x73 0x??) sbb(0x19 0xd2) and(0x21 0xd0)
#
# arm32
##ifdef CONFIG_THUMB2_KERNEL
##define CSDB ".inst.w 0xf3af8014"
##else
##define CSDB ".inst 0xe320f014" e320f014
##endif
#asm volatile(
# "cmp %1, %2\n" e1500003
#" sbc %0, %1, %1\n" e0c03000
#CSDB
#: "=r" (mask)
#: "r" (idx), "Ir" (sz)
#: "cc");
#
# http://git.arm.linux.org.uk/cgit/linux-arm.git/commit/?h=spectre&id=a78d156587931a2c3b354534aa772febf6c9e855
v1_mask_nospec='' v1_mask_nospec=''
if [ -n "$g_kernel_err" ]; then if [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)" pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)"
elif ! command -v perl >/dev/null 2>&1; then 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" pstatus yellow UNKNOWN "missing 'perl' binary, please install it"
else else
perl -ne '/\x0f\x83....\x48\x19\xd2\x48\x21\xd0/ and $found++; END { exit($found ? 0 : 1) }' "$g_kernel" perl -ne '/\x0f\x83....\x48\x19\xd2\x48\x21\xd0/ and $found++; END { exit($found ? 0 : 1) }' "$g_kernel"
@@ -145,6 +122,16 @@ check_CVE_2017_5753_linux() {
if [ "$ret" -eq 0 ]; then if [ "$ret" -eq 0 ]; then
pstatus green YES "x86 32 bits array_index_mask_nospec()" pstatus green YES "x86 32 bits array_index_mask_nospec()"
v1_mask_nospec="x86 32 bits array_index_mask_nospec" 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 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) 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 if [ "$ret" -gt 0 ]; then
@@ -154,7 +141,8 @@ check_CVE_2017_5753_linux() {
pstatus yellow NO pstatus yellow NO
fi fi
fi fi
fi else
pstatus yellow NO
fi fi
fi fi
@@ -172,6 +160,7 @@ check_CVE_2017_5753_linux() {
pstatus yellow NO pstatus yellow NO
fi fi
if is_arm_kernel; then
pr_info_nol "* Kernel has mask_nospec64 (arm64): " pr_info_nol "* Kernel has mask_nospec64 (arm64): "
#.macro mask_nospec64, idx, limit, tmp #.macro mask_nospec64, idx, limit, tmp
#sub \tmp, \idx, \limit #sub \tmp, \idx, \limit
@@ -233,6 +222,7 @@ check_CVE_2017_5753_linux() {
pstatus yellow NO pstatus yellow NO
fi fi
fi fi
fi # is_arm_kernel
elif [ "$sys_interface_available" = 0 ]; then elif [ "$sys_interface_available" = 0 ]; then
msg="/sys vulnerability interface use forced, but it's not available!" msg="/sys vulnerability interface use forced, but it's not available!"

View File

@@ -104,7 +104,7 @@ check_CVE_2017_5754_linux() {
mount_debugfs mount_debugfs
pr_info_nol " * PTI enabled and active: " pr_info_nol " * PTI enabled and active: "
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
dmesg_grep="Kernel/User page tables isolation: enabled" dmesg_grep="Kernel/User page tables isolation: enabled"
dmesg_grep="$dmesg_grep|Kernel page table isolation enabled" dmesg_grep="$dmesg_grep|Kernel page table isolation enabled"
dmesg_grep="$dmesg_grep|x86/pti: Unmapping kernel while in userspace" dmesg_grep="$dmesg_grep|x86/pti: Unmapping kernel while in userspace"
@@ -153,7 +153,10 @@ check_CVE_2017_5754_linux() {
pstatus blue N/A "not testable in no-runtime mode" pstatus blue N/A "not testable in no-runtime mode"
fi fi
# PCID/INVPCID are x86-only CPU features
if is_x86_cpu; then
pti_performance_check pti_performance_check
fi
elif [ "$sys_interface_available" = 0 ]; then elif [ "$sys_interface_available" = 0 ]; then
# we have no sysfs but were asked to use it only! # we have no sysfs but were asked to use it only!
@@ -167,7 +170,7 @@ check_CVE_2017_5754_linux() {
is_xen_dom0 && xen_pv_domo=1 is_xen_dom0 && xen_pv_domo=1
is_xen_domU && xen_pv_domu=1 is_xen_domU && xen_pv_domu=1
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
# checking whether we're running under Xen PV 64 bits. If yes, we are affected by affected_variant3 # checking whether we're running under Xen PV 64 bits. If yes, we are affected by affected_variant3
# (unless we are a Dom0) # (unless we are a Dom0)
pr_info_nol "* Running as a Xen PV DomU: " pr_info_nol "* Running as a Xen PV DomU: "
@@ -183,7 +186,7 @@ check_CVE_2017_5754_linux() {
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected" pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif [ -z "$msg" ]; then elif [ -z "$msg" ]; then
# if msg is empty, sysfs check didn't fill it, rely on our own test # if msg is empty, sysfs check didn't fill it, rely on our own test
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
if [ "$kpti_enabled" = 1 ]; then if [ "$kpti_enabled" = 1 ]; then
pvulnstatus "$cve" OK "PTI mitigates the vulnerability" pvulnstatus "$cve" OK "PTI mitigates the vulnerability"
elif [ "$xen_pv_domo" = 1 ]; then elif [ "$xen_pv_domo" = 1 ]; then

View File

@@ -24,7 +24,7 @@ check_CVE_2018_12207_linux() {
if [ -n "$g_kernel_err" ]; then if [ -n "$g_kernel_err" ]; then
kernel_itlbmh_err="$g_kernel_err" kernel_itlbmh_err="$g_kernel_err"
# commit 5219505fcbb640e273a0d51c19c38de0100ec5a9 # commit 5219505fcbb640e273a0d51c19c38de0100ec5a9
elif grep -q 'itlb_multihit' "$g_kernel"; then elif is_x86_kernel && grep -q 'itlb_multihit' "$g_kernel"; then
kernel_itlbmh="found itlb_multihit in kernel image" kernel_itlbmh="found itlb_multihit in kernel image"
fi fi
if [ -n "$kernel_itlbmh" ]; then if [ -n "$kernel_itlbmh" ]; then
@@ -36,7 +36,7 @@ check_CVE_2018_12207_linux() {
fi fi
pr_info_nol "* iTLB Multihit mitigation enabled and active: " pr_info_nol "* iTLB Multihit mitigation enabled and active: "
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
if [ -n "$ret_sys_interface_check_fullmsg" ]; then if [ -n "$ret_sys_interface_check_fullmsg" ]; then
if echo "$ret_sys_interface_check_fullmsg" | grep -qF 'Mitigation'; then if echo "$ret_sys_interface_check_fullmsg" | grep -qF 'Mitigation'; then
pstatus green YES "$ret_sys_interface_check_fullmsg" pstatus green YES "$ret_sys_interface_check_fullmsg"
@@ -63,7 +63,7 @@ check_CVE_2018_12207_linux() {
elif [ -z "$msg" ]; then elif [ -z "$msg" ]; then
# if msg is empty, sysfs check didn't fill it, rely on our own test # if msg is empty, sysfs check didn't fill it, rely on our own test
if [ "$opt_sysfs_only" != 1 ]; then if [ "$opt_sysfs_only" != 1 ]; then
if [ "$opt_runtime" = 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 # 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" pvulnstatus "$cve" VULN "Your kernel doesn't support iTLB Multihit mitigation, update it"
else else

View File

@@ -37,7 +37,7 @@ check_CVE_2018_3620_linux() {
fi fi
pr_info_nol "* PTE inversion enabled and active: " pr_info_nol "* PTE inversion enabled and active: "
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
if [ -n "$ret_sys_interface_check_fullmsg" ]; then if [ -n "$ret_sys_interface_check_fullmsg" ]; then
if echo "$ret_sys_interface_check_fullmsg" | grep -q 'Mitigation: PTE Inversion'; then if echo "$ret_sys_interface_check_fullmsg" | grep -q 'Mitigation: PTE Inversion'; then
pstatus green YES pstatus green YES
@@ -66,7 +66,7 @@ check_CVE_2018_3620_linux() {
# if msg is empty, sysfs check didn't fill it, rely on our own test # if msg is empty, sysfs check didn't fill it, rely on our own test
if [ "$opt_sysfs_only" != 1 ]; then if [ "$opt_sysfs_only" != 1 ]; then
if [ "$pteinv_supported" = 1 ]; then if [ "$pteinv_supported" = 1 ]; then
if [ "$pteinv_active" = 1 ] || [ "$opt_runtime" != 1 ]; then if [ "$pteinv_active" = 1 ] || [ "$g_mode" != live ]; then
pvulnstatus "$cve" OK "PTE inversion mitigates the vulnerability" pvulnstatus "$cve" OK "PTE inversion mitigates the vulnerability"
else else
pvulnstatus "$cve" VULN "Your kernel supports PTE inversion but it doesn't seem to be enabled" pvulnstatus "$cve" VULN "Your kernel supports PTE inversion but it doesn't seem to be enabled"

View File

@@ -18,19 +18,19 @@ check_CVE_2018_3639_linux() {
fi fi
if [ "$opt_sysfs_only" != 1 ]; then if [ "$opt_sysfs_only" != 1 ]; then
pr_info_nol "* Kernel supports disabling speculative store bypass (SSB): " pr_info_nol "* Kernel supports disabling speculative store bypass (SSB): "
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
if grep -Eq 'Speculation.?Store.?Bypass:' "$g_procfs/self/status" 2>/dev/null; then if grep -Eq 'Speculation.?Store.?Bypass:' "$g_procfs/self/status" 2>/dev/null; then
kernel_ssb="found in $g_procfs/self/status" kernel_ssb="found in $g_procfs/self/status"
pr_debug "found Speculation.Store.Bypass: in $g_procfs/self/status" pr_debug "found Speculation.Store.Bypass: in $g_procfs/self/status"
fi fi
fi fi
# arm64 kernels can have cpu_show_spec_store_bypass with ARM64_SSBD, so exclude them # spec_store_bypass is x86-specific; ARM kernels use ARM64_SSBD instead
if [ -z "$kernel_ssb" ] && [ -n "$g_kernel" ] && ! is_arm64_kernel; then 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) kernel_ssb=$("${opt_arch_prefix}strings" "$g_kernel" | grep spec_store_bypass | head -n1)
[ -n "$kernel_ssb" ] && kernel_ssb="found $kernel_ssb in kernel" [ -n "$kernel_ssb" ] && kernel_ssb="found $kernel_ssb in kernel"
fi fi
# arm64 kernels can have cpu_show_spec_store_bypass with ARM64_SSBD, so exclude them # spec_store_bypass is x86-specific; ARM kernels use ARM64_SSBD instead
if [ -z "$kernel_ssb" ] && [ -n "$opt_map" ] && ! is_arm64_kernel; then if [ -z "$kernel_ssb" ] && [ -n "$opt_map" ] && is_x86_kernel; then
kernel_ssb=$(grep spec_store_bypass "$opt_map" | awk '{print $3}' | head -n1) kernel_ssb=$(grep spec_store_bypass "$opt_map" | awk '{print $3}' | head -n1)
[ -n "$kernel_ssb" ] && kernel_ssb="found $kernel_ssb in System.map" [ -n "$kernel_ssb" ] && kernel_ssb="found $kernel_ssb in System.map"
fi fi
@@ -57,7 +57,7 @@ check_CVE_2018_3639_linux() {
fi fi
kernel_ssbd_enabled=-1 kernel_ssbd_enabled=-1
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
# https://elixir.bootlin.com/linux/v5.0/source/fs/proc/array.c#L340 # https://elixir.bootlin.com/linux/v5.0/source/fs/proc/array.c#L340
pr_info_nol "* SSB mitigation is enabled and active: " 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 if grep -Eq 'Speculation.?Store.?Bypass:[[:space:]]+thread' "$g_procfs/self/status" 2>/dev/null; then
@@ -106,7 +106,7 @@ check_CVE_2018_3639_linux() {
# if msg is empty, sysfs check didn't fill it, rely on our own test # if msg is empty, sysfs check didn't fill it, rely on our own test
if [ -n "$cap_ssbd" ]; then if [ -n "$cap_ssbd" ]; then
if [ -n "$kernel_ssb" ]; then if [ -n "$kernel_ssb" ]; then
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
if [ "$kernel_ssbd_enabled" -gt 0 ]; then if [ "$kernel_ssbd_enabled" -gt 0 ]; then
pvulnstatus "$cve" OK "your CPU and kernel both support SSBD and mitigation is enabled" pvulnstatus "$cve" OK "your CPU and kernel both support SSBD and mitigation is enabled"
else else
@@ -121,7 +121,7 @@ check_CVE_2018_3639_linux() {
fi fi
else else
if [ -n "$kernel_ssb" ]; then if [ -n "$kernel_ssb" ]; then
if is_arm64_kernel; then if is_arm_kernel; then
pvulnstatus "$cve" VULN "no SSB mitigation is active on your system" 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." 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 else
@@ -129,7 +129,7 @@ check_CVE_2018_3639_linux() {
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)." 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 fi
else else
if is_arm64_kernel; then if is_arm_kernel; then
pvulnstatus "$cve" VULN "your kernel and firmware do not support SSB mitigation" 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." 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 else

View File

@@ -11,7 +11,7 @@ check_CVE_2018_3640() {
sys_interface_available=0 sys_interface_available=0
msg='' msg=''
if is_arm64_kernel; then if is_arm_kernel; then
# ARM64: mitigation is via an EL2 indirect trampoline (spectre_v3a_enable_mitigation), # ARM64: mitigation is via an EL2 indirect trampoline (spectre_v3a_enable_mitigation),
# applied automatically at boot for affected CPUs (Cortex-A57, Cortex-A72). # applied automatically at boot for affected CPUs (Cortex-A57, Cortex-A72).
# No microcode update is involved. # No microcode update is involved.

View File

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

View File

@@ -21,7 +21,7 @@ check_CVE_2019_11135_linux() {
kernel_taa='' kernel_taa=''
if [ -n "$g_kernel_err" ]; then if [ -n "$g_kernel_err" ]; then
kernel_taa_err="$g_kernel_err" kernel_taa_err="$g_kernel_err"
elif grep -q 'tsx_async_abort' "$g_kernel"; then elif is_x86_kernel && grep -q 'tsx_async_abort' "$g_kernel"; then
kernel_taa="found tsx_async_abort in kernel image" kernel_taa="found tsx_async_abort in kernel image"
fi fi
if [ -n "$kernel_taa" ]; then if [ -n "$kernel_taa" ]; then
@@ -33,7 +33,7 @@ check_CVE_2019_11135_linux() {
fi fi
pr_info_nol "* TAA mitigation enabled and active: " pr_info_nol "* TAA mitigation enabled and active: "
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
if [ -n "$ret_sys_interface_check_fullmsg" ]; then if [ -n "$ret_sys_interface_check_fullmsg" ]; then
if echo "$ret_sys_interface_check_fullmsg" | grep -qE '^Mitigation'; then if echo "$ret_sys_interface_check_fullmsg" | grep -qE '^Mitigation'; then
pstatus green YES "$ret_sys_interface_check_fullmsg" pstatus green YES "$ret_sys_interface_check_fullmsg"
@@ -57,7 +57,7 @@ check_CVE_2019_11135_linux() {
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected" pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif [ -z "$msg" ]; then elif [ -z "$msg" ]; then
# if msg is empty, sysfs check didn't fill it, rely on our own test # if msg is empty, sysfs check didn't fill it, rely on our own test
if [ "$opt_runtime" = 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 # 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" pvulnstatus "$cve" VULN "Your kernel doesn't support TAA mitigation, update it"
else else

View File

@@ -21,7 +21,7 @@ check_CVE_2020_0543_linux() {
kernel_srbds='' kernel_srbds=''
if [ -n "$g_kernel_err" ]; then if [ -n "$g_kernel_err" ]; then
kernel_srbds_err="$g_kernel_err" kernel_srbds_err="$g_kernel_err"
elif grep -q 'Dependent on hypervisor' "$g_kernel"; then 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" kernel_srbds="found SRBDS implementation evidence in kernel image. Your kernel is up to date for SRBDS mitigation"
fi fi
if [ -n "$kernel_srbds" ]; then if [ -n "$kernel_srbds" ]; then
@@ -32,7 +32,7 @@ check_CVE_2020_0543_linux() {
pstatus yellow NO pstatus yellow NO
fi fi
pr_info_nol "* SRBDS mitigation control is enabled and active: " pr_info_nol "* SRBDS mitigation control is enabled and active: "
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
if [ -n "$ret_sys_interface_check_fullmsg" ]; then if [ -n "$ret_sys_interface_check_fullmsg" ]; then
if echo "$ret_sys_interface_check_fullmsg" | grep -qE '^Mitigation'; then if echo "$ret_sys_interface_check_fullmsg" | grep -qE '^Mitigation'; then
pstatus green YES "$ret_sys_interface_check_fullmsg" pstatus green YES "$ret_sys_interface_check_fullmsg"
@@ -61,7 +61,7 @@ check_CVE_2020_0543_linux() {
# SRBDS mitigation control is enabled # SRBDS mitigation control is enabled
if [ -z "$msg" ]; then if [ -z "$msg" ]; then
# if msg is empty, sysfs check didn't fill it, rely on our own test # if msg is empty, sysfs check didn't fill it, rely on our own test
if [ "$opt_runtime" = 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 # 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" pvulnstatus "$cve" OK "Your microcode is up to date for SRBDS mitigation control. The kernel needs to be updated"
fi fi
@@ -75,7 +75,7 @@ check_CVE_2020_0543_linux() {
elif [ "$cap_srbds_on" = 0 ]; then elif [ "$cap_srbds_on" = 0 ]; then
# SRBDS mitigation control is disabled # SRBDS mitigation control is disabled
if [ -z "$msg" ]; then if [ -z "$msg" ]; then
if [ "$opt_runtime" = 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 # 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" pvulnstatus "$cve" VULN "Your microcode is up to date for SRBDS mitigation control. The kernel needs to be updated. Mitigation is disabled"
fi fi

View File

@@ -174,7 +174,7 @@ check_CVE_2022_29900_linux() {
# Zen/Zen+/Zen2: check IBPB microcode support and SMT # Zen/Zen+/Zen2: check IBPB microcode support and SMT
if [ "$cpu_family" = $((0x17)) ]; then if [ "$cpu_family" = $((0x17)) ]; then
pr_info_nol "* CPU supports IBPB: " pr_info_nol "* CPU supports IBPB: "
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
if [ -n "$cap_ibpb" ]; then if [ -n "$cap_ibpb" ]; then
pstatus green YES "$cap_ibpb" pstatus green YES "$cap_ibpb"
else else
@@ -217,7 +217,7 @@ check_CVE_2022_29900_linux() {
"doesn't fully protect cross-thread speculation." "doesn't fully protect cross-thread speculation."
elif [ -z "$kernel_unret" ] && [ -z "$kernel_ibpb_entry" ]; then 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" pvulnstatus "$cve" VULN "Your kernel doesn't have either UNRET_ENTRY or IBPB_ENTRY compiled-in"
elif [ "$smt_enabled" = 0 ] && [ -z "$cap_ibpb" ] && [ "$opt_runtime" = 1 ]; then elif [ "$smt_enabled" = 0 ] && [ -z "$cap_ibpb" ] && [ "$g_mode" = live ]; then
pvulnstatus "$cve" VULN "SMT is enabled and your microcode doesn't support IBPB" 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" \ explain "Update your CPU microcode to get IBPB support, or disable SMT by adding\n" \
"\`nosmt\` to your kernel command line." "\`nosmt\` to your kernel command line."

View File

@@ -84,7 +84,7 @@ check_CVE_2022_29901_linux() {
fi fi
pr_info_nol "* CPU supports Enhanced IBRS (IBRS_ALL): " pr_info_nol "* CPU supports Enhanced IBRS (IBRS_ALL): "
if [ "$opt_runtime" = 1 ] || [ "$cap_ibrs_all" != -1 ]; then if [ "$g_mode" = live ] || [ "$cap_ibrs_all" != -1 ]; then
if [ "$cap_ibrs_all" = 1 ]; then if [ "$cap_ibrs_all" = 1 ]; then
pstatus green YES pstatus green YES
elif [ "$cap_ibrs_all" = 0 ]; then elif [ "$cap_ibrs_all" = 0 ]; then
@@ -97,7 +97,7 @@ check_CVE_2022_29901_linux() {
fi fi
pr_info_nol "* CPU has RSB Alternate Behavior (RSBA): " pr_info_nol "* CPU has RSB Alternate Behavior (RSBA): "
if [ "$opt_runtime" = 1 ] || [ "$cap_rsba" != -1 ]; then if [ "$g_mode" = live ] || [ "$cap_rsba" != -1 ]; then
if [ "$cap_rsba" = 1 ]; then if [ "$cap_rsba" = 1 ]; then
pstatus yellow YES "this CPU is affected by RSB underflow" pstatus yellow YES "this CPU is affected by RSB underflow"
elif [ "$cap_rsba" = 0 ]; then elif [ "$cap_rsba" = 0 ]; then

View File

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

View File

@@ -88,10 +88,10 @@ check_CVE_2023_20588_linux() {
kernel_mitigated='' kernel_mitigated=''
if [ -n "$g_kernel_err" ]; then if [ -n "$g_kernel_err" ]; then
pstatus yellow UNKNOWN "$g_kernel_err" pstatus yellow UNKNOWN "$g_kernel_err"
elif grep -q 'amd_clear_divider' "$g_kernel"; then elif is_x86_kernel && grep -q 'amd_clear_divider' "$g_kernel"; then
kernel_mitigated="found amd_clear_divider in kernel image" kernel_mitigated="found amd_clear_divider in kernel image"
pstatus green YES "$kernel_mitigated" pstatus green YES "$kernel_mitigated"
elif [ -n "$opt_map" ] && grep -q 'amd_clear_divider' "$opt_map"; then elif is_x86_kernel && [ -n "$opt_map" ] && grep -q 'amd_clear_divider' "$opt_map"; then
kernel_mitigated="found amd_clear_divider in System.map" kernel_mitigated="found amd_clear_divider in System.map"
pstatus green YES "$kernel_mitigated" pstatus green YES "$kernel_mitigated"
else else
@@ -101,7 +101,7 @@ check_CVE_2023_20588_linux() {
pr_info_nol "* DIV0 mitigation enabled and active: " pr_info_nol "* DIV0 mitigation enabled and active: "
cpuinfo_div0='' cpuinfo_div0=''
dmesg_div0='' dmesg_div0=''
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
if [ -e "$g_procfs/cpuinfo" ] && grep -qw 'div0' "$g_procfs/cpuinfo" 2>/dev/null; then if [ -e "$g_procfs/cpuinfo" ] && grep -qw 'div0' "$g_procfs/cpuinfo" 2>/dev/null; then
cpuinfo_div0=1 cpuinfo_div0=1
pstatus green YES "div0 found in $g_procfs/cpuinfo bug flags" pstatus green YES "div0 found in $g_procfs/cpuinfo bug flags"
@@ -141,7 +141,7 @@ check_CVE_2023_20588_linux() {
pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected" pvulnstatus "$cve" OK "your CPU vendor reported your CPU model as not affected"
elif [ -z "$msg" ]; then elif [ -z "$msg" ]; then
if [ "$opt_sysfs_only" != 1 ]; then if [ "$opt_sysfs_only" != 1 ]; then
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
# live mode: cpuinfo div0 flag is the strongest proof the mitigation is active # live mode: cpuinfo div0 flag is the strongest proof the mitigation is active
if [ "$cpuinfo_div0" = 1 ] || [ "$dmesg_div0" = 1 ]; then if [ "$cpuinfo_div0" = 1 ] || [ "$dmesg_div0" = 1 ]; then
_cve_2023_20588_pvulnstatus_smt _cve_2023_20588_pvulnstatus_smt

View File

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

View File

@@ -69,6 +69,7 @@ check_CVE_2023_28746_linux() {
fi fi
if [ "$opt_sysfs_only" != 1 ]; then if [ "$opt_sysfs_only" != 1 ]; then
if is_x86_cpu; then
pr_info_nol "* CPU microcode mitigates the vulnerability: " pr_info_nol "* CPU microcode mitigates the vulnerability: "
if [ "$cap_rfds_clear" = 1 ]; then if [ "$cap_rfds_clear" = 1 ]; then
pstatus green YES "RFDS_CLEAR capability indicated by microcode" pstatus green YES "RFDS_CLEAR capability indicated by microcode"
@@ -77,7 +78,9 @@ check_CVE_2023_28746_linux() {
else else
pstatus yellow UNKNOWN "couldn't read MSR" pstatus yellow UNKNOWN "couldn't read MSR"
fi fi
fi
if is_x86_kernel; then
pr_info_nol "* Kernel supports RFDS mitigation (VERW on transitions): " pr_info_nol "* Kernel supports RFDS mitigation (VERW on transitions): "
kernel_rfds='' kernel_rfds=''
kernel_rfds_err='' kernel_rfds_err=''
@@ -105,8 +108,9 @@ check_CVE_2023_28746_linux() {
else else
pstatus yellow NO pstatus yellow NO
fi fi
fi
if [ "$opt_runtime" = 1 ] && [ "$sys_interface_available" = 1 ]; then if is_x86_cpu && [ "$g_mode" = live ] && [ "$sys_interface_available" = 1 ]; then
pr_info_nol "* RFDS mitigation is enabled and active: " pr_info_nol "* RFDS mitigation is enabled and active: "
if echo "$ret_sys_interface_check_fullmsg" | grep -qi '^Mitigation'; then if echo "$ret_sys_interface_check_fullmsg" | grep -qi '^Mitigation'; then
rfds_mitigated=1 rfds_mitigated=1
@@ -129,7 +133,7 @@ check_CVE_2023_28746_linux() {
if [ "$opt_sysfs_only" != 1 ]; then if [ "$opt_sysfs_only" != 1 ]; then
if [ "$cap_rfds_clear" = 1 ]; then if [ "$cap_rfds_clear" = 1 ]; then
if [ -n "$kernel_rfds" ]; then if [ -n "$kernel_rfds" ]; then
if [ "$opt_runtime" = 1 ]; then if [ "$g_mode" = live ]; then
if [ "$rfds_mitigated" = 1 ]; then if [ "$rfds_mitigated" = 1 ]; then
pvulnstatus "$cve" OK "Your microcode and kernel are both up to date for this mitigation, and mitigation is enabled" pvulnstatus "$cve" OK "Your microcode and kernel are both up to date for this mitigation, and mitigation is enabled"
else else

View File

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

View File

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

View File

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

View File

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