mirror of
https://github.com/speed47/spectre-meltdown-checker.git
synced 2026-04-29 03:53:18 +02:00
Compare commits
6 Commits
ac09be87b5
...
954eb13468
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
954eb13468 | ||
|
|
be91749d3a | ||
|
|
d040c0ffc3 | ||
|
|
c143bdb073 | ||
|
|
fc34cb729b | ||
|
|
fe5bf7c003 |
@@ -129,11 +129,54 @@ Never look at the microcode version to determine whether it has the proper mitig
|
||||
|
||||
**Exception**: When a vulnerability is fixed purely by a microcode update and the fix exposes **no** detectable CPUID bit, MSR bit, or ARCH\_CAP flag, then we must hardcode the known-fixing microcode versions for each affected CPU stepping. In this case, build a `<vuln>_ucode_list` table of `FF-MM-SS/platformid_mask,fixed_ucode_version` tuples (sourced from the Intel affected processor list and the Intel-Linux-Processor-Microcode-Data-Files release notes), match against `cpu_cpuid` + `cpu_platformid` in `is_cpu_affected()`, and store the required version in a `g_<vuln>_fixed_ucode_version` global. The CVE check then compares `cpu_ucode` against this threshold. Because Intel never lists EOL CPUs, the microcode list may be incomplete: keep a model blacklist as a fallback so that affected CPUs without a known fix are still flagged as affected (the CVE check should handle the empty `g_<vuln>_fixed_ucode_version` case by reporting VULN with "no microcode update available"). See Reptar (`g_reptar_fixed_ucode_version`) and BPI (`g_bpi_fixed_ucode_version`) for reference implementations.
|
||||
|
||||
### 4. Assume affected unless proven otherwise (whitelist approach)
|
||||
### 4. `/proc/cpuinfo` fallback for CPUID reads
|
||||
|
||||
The primary way to read CPU capability bits is via `read_cpuid` (which uses `/dev/cpu/N/cpuid`). However, this device may be unavailable — most commonly inside virtual machines where the `cpuid` kernel module cannot be loaded. When `read_cpuid` returns `READ_CPUID_RET_ERR` (could not read at all), we can fall back to checking `/proc/cpuinfo` flags as a secondary source, **in live mode only**.
|
||||
|
||||
This works because the kernel always has direct access to CPUID (it doesn't need `/dev/cpu`), and exposes the results as flags in `/proc/cpuinfo`. When a hypervisor virtualizes a CPUID bit for the guest, the guest kernel sees it and reports it in `/proc/cpuinfo`. This is the same information `read_cpuid` would return if the device were available.
|
||||
|
||||
**Rules:**
|
||||
- This is strictly a fallback: `read_cpuid` via `/dev/cpu/N/cpuid` remains the primary method.
|
||||
- Only use it when `read_cpuid` returned `READ_CPUID_RET_ERR` (device unavailable), **never** when it returned `READ_CPUID_RET_KO` (device available but bit is 0 — meaning the CPU/hypervisor explicitly reports the feature as absent).
|
||||
- Only in live mode (`$opt_live = 1`), since `/proc/cpuinfo` is not available in offline mode.
|
||||
- Only for CPUID bits that the kernel exposes as `/proc/cpuinfo` flags. Not all bits have a corresponding flag — only those listed in the kernel's `capflags.c`. If a bit has no `/proc/cpuinfo` flag, no fallback is possible.
|
||||
- The fallback depends on the running kernel being recent enough to know about the CPUID bit in question. An older kernel won't expose a flag it doesn't know about, so the fallback will silently not trigger — which is fine (we just stay at UNKNOWN, same as the ERR case without fallback).
|
||||
|
||||
**Known mappings** (CPUID bit → `/proc/cpuinfo` flag → script `cap_*` variable):
|
||||
|
||||
| CPUID source | `/proc/cpuinfo` flag | `cap_*` variable |
|
||||
|---|---|---|
|
||||
| Intel 0x7.0.EDX[26] / AMD 0x80000008.EBX[14] | `ibrs` | `cap_ibrs` |
|
||||
| AMD 0x80000008.EBX[12] | `ibpb` | `cap_ibpb` |
|
||||
| Intel 0x7.0.EDX[27] / AMD 0x80000008.EBX[15] | `stibp` | `cap_stibp` |
|
||||
| Intel 0x7.0.EDX[31] / AMD 0x80000008.EBX[24,25] | `ssbd` / `virt_ssbd` | `cap_ssbd` |
|
||||
| Intel 0x7.0.EDX[28] | `flush_l1d` | `cap_l1df` |
|
||||
| Intel 0x7.0.EDX[10] | `md_clear` | `cap_md_clear` |
|
||||
| Intel 0x7.0.EDX[29] | `arch_capabilities` | `cap_arch_capabilities` |
|
||||
|
||||
**Implementation pattern** in `check_cpu()`:
|
||||
|
||||
```sh
|
||||
read_cpuid 0x7 0x0 $EDX 31 1 1
|
||||
ret=$?
|
||||
if [ $ret = $READ_CPUID_RET_OK ]; then
|
||||
cap_ssbd='Intel SSBD'
|
||||
elif [ $ret = $READ_CPUID_RET_ERR ] && [ "$opt_live" = 1 ]; then
|
||||
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
|
||||
if grep ^flags "$g_procfs/cpuinfo" | grep -qw ssbd; then
|
||||
cap_ssbd='Intel SSBD (cpuinfo)'
|
||||
ret=$READ_CPUID_RET_OK
|
||||
fi
|
||||
fi
|
||||
```
|
||||
|
||||
When the fallback sets a `cap_*` variable, append ` (cpuinfo)` to the value string so the output makes it clear the information was derived from `/proc/cpuinfo` rather than read directly from hardware. Update `ret` to `READ_CPUID_RET_OK` so downstream status display logic (`pstatus`) reports YES rather than UNKNOWN.
|
||||
|
||||
### 5. Assume affected unless proven otherwise (whitelist approach)
|
||||
|
||||
When a CPU is not explicitly known to be unaffected by a vulnerability, assume that it is affected. This conservative default has been the right call since the early Spectre/Meltdown days and remains sound.
|
||||
|
||||
### 5. Offline mode
|
||||
### 6. Offline mode
|
||||
|
||||
The script can analyze a non-running kernel via `--kernel`, `--config`, `--map` flags, allowing verification before deployment.
|
||||
|
||||
@@ -167,6 +210,7 @@ Common traps to avoid:
|
||||
| `xargs` | `-r` (no-op if empty, GNU only) | Guard with a prior `[ -n "..." ]` check, or accept the harmless empty invocation |
|
||||
| `readlink` | `-f` (canonicalize, GNU only) | Use only in Linux-specific code paths, or reimplement with `cd`/`pwd` |
|
||||
| `dd` | `iflag=`, `oflag=` (GNU only) | Use only in Linux-specific code paths (e.g. `/dev/cpu/*/msr`) |
|
||||
| `base64` | `-w N` (set line-wrap width, GNU only; BusyBox doesn't support it) | Pipe through `tr -d '\n'` to remove newlines instead of `-w0` |
|
||||
|
||||
When a tool genuinely has no portable equivalent, restrict the non-portable call to a platform-specific code path (i.e. inside a BSD-only or Linux-only branch) and document why.
|
||||
|
||||
|
||||
@@ -88,7 +88,9 @@ try_decompress() {
|
||||
fi
|
||||
pos=${pos%%:*}
|
||||
# shellcheck disable=SC2086
|
||||
tail -c+$pos "$6" 2>/dev/null | $3 $4 >"$g_kerneltmp" 2>/dev/null
|
||||
# wrap in subshell so that if $3 segfaults (e.g. old BusyBox unlzma on random data),
|
||||
# the "Segmentation fault" message printed by the shell goes to /dev/null
|
||||
(tail -c+$pos "$6" 2>/dev/null | $3 $4 >"$g_kerneltmp" 2>/dev/null) 2>/dev/null
|
||||
ret=$?
|
||||
if [ ! -s "$g_kerneltmp" ]; then
|
||||
# don't rely on $ret, sometimes it's != 0 but worked
|
||||
|
||||
@@ -5,20 +5,27 @@ readonly WRITE_MSR_RET_ERR=2
|
||||
readonly WRITE_MSR_RET_LOCKDOWN=3
|
||||
# Write a value to an MSR register across one or all cores
|
||||
# Args: $1=msr_address $2=value(optional) $3=cpu_index(optional, default 0)
|
||||
# Sets: ret_write_msr_msg
|
||||
# Sets: ret_write_msr_msg, ret_write_msr_ADDR_msg (where ADDR is the hex address, e.g. ret_write_msr_0x123_msg)
|
||||
# Returns: WRITE_MSR_RET_OK | WRITE_MSR_RET_KO | WRITE_MSR_RET_ERR | WRITE_MSR_RET_LOCKDOWN
|
||||
write_msr() {
|
||||
local ret core first_core_ret
|
||||
local ret core first_core_ret msr_dec msr
|
||||
msr_dec=$(($1))
|
||||
msr=$(printf "0x%x" "$msr_dec")
|
||||
if [ "$opt_cpu" != all ]; then
|
||||
# we only have one core to write to, do it and return the result
|
||||
write_msr_one_core "$opt_cpu" "$@"
|
||||
return $?
|
||||
ret=$?
|
||||
# shellcheck disable=SC2163
|
||||
eval "ret_write_msr_${msr}_msg=\$ret_write_msr_msg"
|
||||
return $ret
|
||||
fi
|
||||
|
||||
# otherwise we must write on all cores
|
||||
for core in $(seq 0 "$g_max_core_id"); do
|
||||
write_msr_one_core "$core" "$@"
|
||||
ret=$?
|
||||
# shellcheck disable=SC2163
|
||||
eval "ret_write_msr_${msr}_msg=\$ret_write_msr_msg"
|
||||
if [ "$core" = 0 ]; then
|
||||
# save the result of the first core, for comparison with the others
|
||||
first_core_ret=$ret
|
||||
@@ -26,6 +33,8 @@ write_msr() {
|
||||
# compare first core with the other ones
|
||||
if [ "$first_core_ret" != "$ret" ]; then
|
||||
ret_write_msr_msg="result is not homogeneous between all cores, at least core 0 and $core differ!"
|
||||
# shellcheck disable=SC2163
|
||||
eval "ret_write_msr_${msr}_msg=\$ret_write_msr_msg"
|
||||
return $WRITE_MSR_RET_ERR
|
||||
fi
|
||||
fi
|
||||
@@ -52,10 +61,17 @@ write_msr_one_core() {
|
||||
mockvarname="SMC_MOCK_WRMSR_${msr}_RET"
|
||||
# shellcheck disable=SC2086,SC1083
|
||||
if [ -n "$(eval echo \${$mockvarname:-})" ]; then
|
||||
pr_debug "write_msr: MOCKING enabled for msr $msr func returns $(eval echo \$$mockvarname)"
|
||||
local mockret
|
||||
mockret="$(eval echo \$$mockvarname)"
|
||||
pr_debug "write_msr: MOCKING enabled for msr $msr func returns $mockret"
|
||||
g_mocked=1
|
||||
[ "$(eval echo \$$mockvarname)" = $WRITE_MSR_RET_LOCKDOWN ] && g_msr_locked_down=1
|
||||
return "$(eval echo \$$mockvarname)"
|
||||
if [ "$mockret" = "$WRITE_MSR_RET_LOCKDOWN" ]; then
|
||||
g_msr_locked_down=1
|
||||
ret_write_msr_msg="kernel lockdown is enabled, MSR writes are restricted"
|
||||
elif [ "$mockret" = "$WRITE_MSR_RET_ERR" ]; then
|
||||
ret_write_msr_msg="could not write MSR"
|
||||
fi
|
||||
return "$mockret"
|
||||
fi
|
||||
|
||||
# proactive lockdown detection via sysfs (vanilla 5.4+, CentOS 8+, Rocky 9+):
|
||||
@@ -76,7 +92,7 @@ write_msr_one_core() {
|
||||
load_msr
|
||||
fi
|
||||
if [ ! -e $CPU_DEV_BASE/0/msr ] && [ ! -e ${BSD_CPUCTL_DEV_BASE}0 ]; then
|
||||
ret_read_msr_msg="is msr kernel module available?"
|
||||
ret_write_msr_msg="msr kernel module is not available"
|
||||
return $WRITE_MSR_RET_ERR
|
||||
fi
|
||||
|
||||
@@ -86,14 +102,13 @@ write_msr_one_core() {
|
||||
ret=$?
|
||||
else
|
||||
# for Linux
|
||||
# convert to decimal
|
||||
if [ ! -w $CPU_DEV_BASE/"$core"/msr ]; then
|
||||
ret_write_msr_msg="No write permission on $CPU_DEV_BASE/$core/msr"
|
||||
return $WRITE_MSR_RET_ERR
|
||||
# if wrmsr is available, use it
|
||||
elif command -v wrmsr >/dev/null 2>&1 && [ "${SMC_NO_WRMSR:-}" != 1 ]; then
|
||||
pr_debug "write_msr: using wrmsr"
|
||||
wrmsr $msr_dec $value_dec 2>/dev/null
|
||||
wrmsr -p "$core" $msr_dec $value_dec 2>/dev/null
|
||||
ret=$?
|
||||
# ret=4: msr doesn't exist, ret=127: msr.allow_writes=off
|
||||
[ "$ret" = 127 ] && write_denied=1
|
||||
@@ -172,22 +187,31 @@ readonly MSR_IA32_MCU_OPT_CTRL=0x123
|
||||
readonly READ_MSR_RET_OK=0
|
||||
readonly READ_MSR_RET_KO=1
|
||||
readonly READ_MSR_RET_ERR=2
|
||||
readonly READ_MSR_RET_LOCKDOWN=3
|
||||
# Read an MSR register value across one or all cores
|
||||
# Args: $1=msr_address $2=cpu_index(optional, default 0)
|
||||
# Sets: ret_read_msr_value, ret_read_msr_value_hi, ret_read_msr_value_lo, ret_read_msr_msg
|
||||
# Returns: READ_MSR_RET_OK | READ_MSR_RET_KO | READ_MSR_RET_ERR
|
||||
# Sets: ret_read_msr_value, ret_read_msr_value_hi, ret_read_msr_value_lo, ret_read_msr_msg,
|
||||
# ret_read_msr_ADDR_msg (where ADDR is the hex address, e.g. ret_read_msr_0x10a_msg)
|
||||
# Returns: READ_MSR_RET_OK | READ_MSR_RET_KO | READ_MSR_RET_ERR | READ_MSR_RET_LOCKDOWN
|
||||
read_msr() {
|
||||
local ret core first_core_ret first_core_value
|
||||
local ret core first_core_ret first_core_value msr_dec msr
|
||||
msr_dec=$(($1))
|
||||
msr=$(printf "0x%x" "$msr_dec")
|
||||
if [ "$opt_cpu" != all ]; then
|
||||
# we only have one core to read, do it and return the result
|
||||
read_msr_one_core "$opt_cpu" "$@"
|
||||
return $?
|
||||
ret=$?
|
||||
# shellcheck disable=SC2163
|
||||
eval "ret_read_msr_${msr}_msg=\$ret_read_msr_msg"
|
||||
return $ret
|
||||
fi
|
||||
|
||||
# otherwise we must read all cores
|
||||
for core in $(seq 0 "$g_max_core_id"); do
|
||||
read_msr_one_core "$core" "$@"
|
||||
ret=$?
|
||||
# shellcheck disable=SC2163
|
||||
eval "ret_read_msr_${msr}_msg=\$ret_read_msr_msg"
|
||||
if [ "$core" = 0 ]; then
|
||||
# save the result of the first core, for comparison with the others
|
||||
first_core_ret=$ret
|
||||
@@ -196,6 +220,8 @@ read_msr() {
|
||||
# compare first core with the other ones
|
||||
if [ "$first_core_ret" != "$ret" ] || [ "$first_core_value" != "$ret_read_msr_value" ]; then
|
||||
ret_read_msr_msg="result is not homogeneous between all cores, at least core 0 and $core differ!"
|
||||
# shellcheck disable=SC2163
|
||||
eval "ret_read_msr_${msr}_msg=\$ret_read_msr_msg"
|
||||
return $READ_MSR_RET_ERR
|
||||
fi
|
||||
fi
|
||||
@@ -207,7 +233,7 @@ read_msr() {
|
||||
# Read an MSR register value from a single CPU core
|
||||
# Args: $1=core $2=msr_address
|
||||
# Sets: ret_read_msr_value, ret_read_msr_value_hi, ret_read_msr_value_lo, ret_read_msr_msg
|
||||
# Returns: READ_MSR_RET_OK | READ_MSR_RET_KO | READ_MSR_RET_ERR
|
||||
# Returns: READ_MSR_RET_OK | READ_MSR_RET_KO | READ_MSR_RET_ERR | READ_MSR_RET_LOCKDOWN
|
||||
read_msr_one_core() {
|
||||
local ret core msr msr_dec mockvarname msr_h msr_l mockval
|
||||
core="$1"
|
||||
@@ -239,21 +265,28 @@ read_msr_one_core() {
|
||||
mockvarname="SMC_MOCK_RDMSR_${msr}_RET"
|
||||
# shellcheck disable=SC2086,SC1083
|
||||
if [ -n "$(eval echo \${$mockvarname:-})" ] && [ "$(eval echo \$$mockvarname)" -ne 0 ]; then
|
||||
pr_debug "read_msr: MOCKING enabled for msr $msr func returns $(eval echo \$$mockvarname)"
|
||||
local mockret
|
||||
mockret="$(eval echo \$$mockvarname)"
|
||||
pr_debug "read_msr: MOCKING enabled for msr $msr func returns $mockret"
|
||||
g_mocked=1
|
||||
return "$(eval echo \$$mockvarname)"
|
||||
if [ "$mockret" = "$READ_MSR_RET_LOCKDOWN" ]; then
|
||||
ret_read_msr_msg="kernel lockdown is enabled, MSR reads are restricted"
|
||||
elif [ "$mockret" = "$READ_MSR_RET_ERR" ]; then
|
||||
ret_read_msr_msg="could not read MSR"
|
||||
fi
|
||||
return "$mockret"
|
||||
fi
|
||||
|
||||
# proactive lockdown detection via sysfs (vanilla 5.4+, CentOS 8+, Rocky 9+):
|
||||
# if the kernel lockdown is set to integrity or confidentiality, MSR writes will be denied,
|
||||
# so we can skip the write attempt entirely and avoid relying on dmesg parsing
|
||||
# if the kernel lockdown is set to integrity or confidentiality, MSR reads will be denied,
|
||||
# so we can skip the read attempt entirely and avoid relying on dmesg parsing
|
||||
if [ -e "$SYSKERNEL_BASE/security/lockdown" ]; then
|
||||
if grep -qE '\[integrity\]|\[confidentiality\]' "$SYSKERNEL_BASE/security/lockdown" 2>/dev/null; then
|
||||
pr_debug "write_msr: kernel lockdown detected via $SYSKERNEL_BASE/security/lockdown"
|
||||
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_WRMSR_${msr}_RET=$WRITE_MSR_RET_LOCKDOWN")
|
||||
pr_debug "read_msr: kernel lockdown detected via $SYSKERNEL_BASE/security/lockdown"
|
||||
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_RDMSR_${msr}_RET=$READ_MSR_RET_LOCKDOWN")
|
||||
g_msr_locked_down=1
|
||||
ret_write_msr_msg="your kernel is locked down, please reboot with lockdown=none in the kernel cmdline and retry"
|
||||
return $WRITE_MSR_RET_LOCKDOWN
|
||||
ret_read_msr_msg="kernel lockdown is enabled, MSR reads are restricted"
|
||||
return $READ_MSR_RET_LOCKDOWN
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -262,7 +295,7 @@ read_msr_one_core() {
|
||||
load_msr
|
||||
fi
|
||||
if [ ! -e $CPU_DEV_BASE/0/msr ] && [ ! -e ${BSD_CPUCTL_DEV_BASE}0 ]; then
|
||||
ret_read_msr_msg="is msr kernel module available?"
|
||||
ret_read_msr_msg="msr kernel module is not available"
|
||||
return $READ_MSR_RET_ERR
|
||||
fi
|
||||
|
||||
|
||||
@@ -446,6 +446,15 @@ check_cpu() {
|
||||
ret=invalid
|
||||
pstatus yellow NO "unknown CPU"
|
||||
fi
|
||||
if [ -z "$cap_ibrs" ] && [ $ret = $READ_CPUID_RET_ERR ] && [ "$opt_live" = 1 ]; then
|
||||
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
|
||||
if grep ^flags "$g_procfs/cpuinfo" | grep -qw ibrs; then
|
||||
cap_ibrs='IBRS (cpuinfo)'
|
||||
cap_spec_ctrl=1
|
||||
pstatus green YES "ibrs flag in $g_procfs/cpuinfo"
|
||||
ret=$READ_CPUID_RET_OK
|
||||
fi
|
||||
fi
|
||||
if [ $ret = $READ_CPUID_RET_KO ]; then
|
||||
pstatus yellow NO
|
||||
elif [ $ret = $READ_CPUID_RET_ERR ]; then
|
||||
@@ -514,6 +523,10 @@ check_cpu() {
|
||||
if [ $ret = $READ_CPUID_RET_OK ]; then
|
||||
cap_ibpb='IBPB_SUPPORT'
|
||||
pstatus green YES "IBPB_SUPPORT feature bit"
|
||||
elif [ $ret = $READ_CPUID_RET_ERR ] && [ "$opt_live" = 1 ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw ibpb; then
|
||||
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
|
||||
cap_ibpb='IBPB (cpuinfo)'
|
||||
pstatus green YES "ibpb flag in $g_procfs/cpuinfo"
|
||||
elif [ $ret = $READ_CPUID_RET_KO ]; then
|
||||
pstatus yellow NO
|
||||
else
|
||||
@@ -549,7 +562,7 @@ check_cpu() {
|
||||
elif [ "$spec_ctrl_msr" = 0 ]; then
|
||||
pstatus yellow NO
|
||||
else
|
||||
pstatus yellow UNKNOWN "is msr kernel module available?"
|
||||
pstatus yellow UNKNOWN "$ret_read_msr_msg"
|
||||
fi
|
||||
|
||||
pr_info_nol " * CPU indicates STIBP capability: "
|
||||
@@ -581,6 +594,14 @@ check_cpu() {
|
||||
ret=invalid
|
||||
pstatus yellow UNKNOWN "unknown CPU"
|
||||
fi
|
||||
if [ -z "$cap_stibp" ] && [ $ret = $READ_CPUID_RET_ERR ] && [ "$opt_live" = 1 ]; then
|
||||
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
|
||||
if grep ^flags "$g_procfs/cpuinfo" | grep -qw stibp; then
|
||||
cap_stibp='STIBP (cpuinfo)'
|
||||
pstatus green YES "stibp flag in $g_procfs/cpuinfo"
|
||||
ret=$READ_CPUID_RET_OK
|
||||
fi
|
||||
fi
|
||||
if [ $ret = $READ_CPUID_RET_KO ]; then
|
||||
pstatus yellow NO
|
||||
elif [ $ret = $READ_CPUID_RET_ERR ]; then
|
||||
@@ -645,6 +666,15 @@ check_cpu() {
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$cap_ssbd" ] && [ "$ret24" = $READ_CPUID_RET_ERR ] && [ "$ret25" = $READ_CPUID_RET_ERR ] && [ "$opt_live" = 1 ]; then
|
||||
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
|
||||
if grep ^flags "$g_procfs/cpuinfo" | grep -qw ssbd; then
|
||||
cap_ssbd='SSBD (cpuinfo)'
|
||||
elif grep ^flags "$g_procfs/cpuinfo" | grep -qw virt_ssbd; then
|
||||
cap_ssbd='SSBD in VIRT_SPEC_CTRL (cpuinfo)'
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "${cap_ssbd:=}" ]; then
|
||||
pstatus green YES "$cap_ssbd"
|
||||
elif [ "$ret24" = $READ_CPUID_RET_ERR ] && [ "$ret25" = $READ_CPUID_RET_ERR ]; then
|
||||
@@ -700,6 +730,10 @@ check_cpu() {
|
||||
if [ $ret = $READ_CPUID_RET_OK ]; then
|
||||
pstatus green YES "L1D flush feature bit"
|
||||
cap_l1df=1
|
||||
elif [ $ret = $READ_CPUID_RET_ERR ] && [ "$opt_live" = 1 ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw flush_l1d; then
|
||||
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
|
||||
pstatus green YES "flush_l1d flag in $g_procfs/cpuinfo"
|
||||
cap_l1df=1
|
||||
elif [ $ret = $READ_CPUID_RET_KO ]; then
|
||||
pstatus yellow NO
|
||||
cap_l1df=0
|
||||
@@ -716,6 +750,10 @@ check_cpu() {
|
||||
if [ $ret = $READ_CPUID_RET_OK ]; then
|
||||
cap_md_clear=1
|
||||
pstatus green YES "MD_CLEAR feature bit"
|
||||
elif [ $ret = $READ_CPUID_RET_ERR ] && [ "$opt_live" = 1 ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw md_clear; then
|
||||
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
|
||||
cap_md_clear=1
|
||||
pstatus green YES "md_clear flag in $g_procfs/cpuinfo"
|
||||
elif [ $ret = $READ_CPUID_RET_KO ]; then
|
||||
cap_md_clear=0
|
||||
pstatus yellow NO
|
||||
@@ -782,6 +820,10 @@ check_cpu() {
|
||||
if [ $ret = $READ_CPUID_RET_OK ]; then
|
||||
pstatus green YES
|
||||
cap_arch_capabilities=1
|
||||
elif [ $ret = $READ_CPUID_RET_ERR ] && [ "$opt_live" = 1 ] && grep ^flags "$g_procfs/cpuinfo" | grep -qw arch_capabilities; then
|
||||
# CPUID device unavailable (e.g. in a VM): fall back to /proc/cpuinfo
|
||||
pstatus green YES "arch_capabilities flag in $g_procfs/cpuinfo"
|
||||
cap_arch_capabilities=1
|
||||
elif [ $ret = $READ_CPUID_RET_KO ]; then
|
||||
pstatus yellow NO
|
||||
cap_arch_capabilities=0
|
||||
@@ -974,7 +1016,8 @@ check_cpu() {
|
||||
elif [ "$cap_tsx_ctrl_rtm_disable" = 0 ]; then
|
||||
pstatus blue NO
|
||||
else
|
||||
pstatus yellow UNKNOWN "couldn't read MSR"
|
||||
# shellcheck disable=SC2154
|
||||
pstatus yellow UNKNOWN "$ret_read_msr_0x122_msg"
|
||||
fi
|
||||
|
||||
pr_info_nol " * TSX_CTRL MSR indicates TSX CPUID bit is cleared: "
|
||||
@@ -983,7 +1026,8 @@ check_cpu() {
|
||||
elif [ "$cap_tsx_ctrl_cpuid_clear" = 0 ]; then
|
||||
pstatus blue NO
|
||||
else
|
||||
pstatus yellow UNKNOWN "couldn't read MSR"
|
||||
# shellcheck disable=SC2154
|
||||
pstatus yellow UNKNOWN "$ret_read_msr_0x122_msg"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -1008,7 +1052,8 @@ check_cpu() {
|
||||
|
||||
pr_info_nol " * GDS microcode mitigation is disabled (GDS_MITG_DIS): "
|
||||
if [ "$cap_gds_mitg_dis" = -1 ]; then
|
||||
pstatus yellow UNKNOWN "couldn't read MSR"
|
||||
# shellcheck disable=SC2154
|
||||
pstatus yellow UNKNOWN "$ret_read_msr_0x123_msg"
|
||||
elif [ "$cap_gds_mitg_dis" = 1 ]; then
|
||||
pstatus yellow YES
|
||||
else
|
||||
@@ -1017,7 +1062,8 @@ check_cpu() {
|
||||
|
||||
pr_info_nol " * GDS microcode mitigation is locked in enabled state (GDS_MITG_LOCK): "
|
||||
if [ "$cap_gds_mitg_lock" = -1 ]; then
|
||||
pstatus yellow UNKNOWN "couldn't read MSR"
|
||||
# shellcheck disable=SC2154
|
||||
pstatus yellow UNKNOWN "$ret_read_msr_0x123_msg"
|
||||
elif [ "$cap_gds_mitg_lock" = 1 ]; then
|
||||
pstatus blue YES
|
||||
else
|
||||
@@ -1205,7 +1251,8 @@ check_cpu() {
|
||||
elif [ "$cap_tsx_force_abort_rtm_disable" = 0 ]; then
|
||||
pstatus blue NO
|
||||
else
|
||||
pstatus yellow UNKNOWN "couldn't read MSR"
|
||||
# shellcheck disable=SC2154
|
||||
pstatus yellow UNKNOWN "$ret_read_msr_0x10f_msg"
|
||||
fi
|
||||
|
||||
pr_info_nol " * TSX_FORCE_ABORT MSR indicates TSX CPUID bit is cleared: "
|
||||
@@ -1214,7 +1261,8 @@ check_cpu() {
|
||||
elif [ "$cap_tsx_force_abort_cpuid_clear" = 0 ]; then
|
||||
pstatus blue NO
|
||||
else
|
||||
pstatus yellow UNKNOWN "couldn't read MSR"
|
||||
# shellcheck disable=SC2154
|
||||
pstatus yellow UNKNOWN "$ret_read_msr_0x10f_msg"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ if [ -n "$g_mockme" ] && [ "$opt_mock" = 1 ]; then
|
||||
# not a useless use of cat: gzipping cpuinfo directly doesn't work well
|
||||
# shellcheck disable=SC2002
|
||||
if command -v "base64" >/dev/null 2>&1; then
|
||||
g_mock_cpuinfo="$(cat /proc/cpuinfo | gzip -c | base64 -w0)"
|
||||
g_mock_cpuinfo="$(cat /proc/cpuinfo | gzip -c | base64 | tr -d '\n')"
|
||||
elif command -v "uuencode" >/dev/null 2>&1; then
|
||||
g_mock_cpuinfo="$(cat /proc/cpuinfo | gzip -c | uuencode -m - | grep -Fv 'begin-base64' | grep -Fxv -- '====' | tr -d "\n")"
|
||||
fi
|
||||
|
||||
@@ -633,7 +633,15 @@ check_CVE_2017_5715_linux() {
|
||||
fi
|
||||
fi
|
||||
if [ "$rsb_filling" = 0 ]; then
|
||||
if [ -n "$g_kernel_err" ]; then
|
||||
# Red Hat kernels (RHEL 6/7/8) stuff RSB on context switch as part of
|
||||
# their retpoline implementation when retp_enabled=1, but don't use the
|
||||
# upstream X86_FEATURE_RSB_CTXSW flag or "Filling RSB on context switch"
|
||||
# string. Detect this via the RHEL-specific debugfs knob.
|
||||
# See https://bugzilla.redhat.com/show_bug.cgi?id=1616245#c8
|
||||
if [ "$retp_enabled" = 1 ]; then
|
||||
rsb_filling=1
|
||||
pstatus green YES "Red Hat kernel with retpoline enabled includes RSB filling"
|
||||
elif [ -n "$g_kernel_err" ]; then
|
||||
pstatus yellow UNKNOWN "couldn't check ($g_kernel_err)"
|
||||
else
|
||||
if grep -qw -e 'Filling RSB on context switch' "$g_kernel"; then
|
||||
|
||||
Reference in New Issue
Block a user