feat: rework the --batch json output entirely

This commit is contained in:
Stéphane Lesimple
2026-04-08 20:50:54 +02:00
parent 3afbda8430
commit 39dea1245e
8 changed files with 384 additions and 20 deletions

View File

@@ -43,7 +43,8 @@ show_usage() {
so that invoked tools will be prefixed with this (i.e. aarch64-linux-gnu-objdump)
--batch text produce machine readable output, this is the default if --batch is specified alone
--batch short produce only one line with the vulnerabilities separated by spaces
--batch json produce JSON output formatted for Puppet, Ansible, Chef...
--batch json produce comprehensive JSON output with system, CPU, and vulnerability details
--batch json-terse produce a terse JSON array of per-CVE results (legacy format)
--batch nrpe produce machine readable output formatted for NRPE
--batch prometheus produce output for consumption by prometheus-node-exporter

View File

@@ -116,7 +116,7 @@ while [ -n "${1:-}" ]; do
opt_no_color=1
shift
case "$1" in
text | short | nrpe | json | prometheus)
text | short | nrpe | json | json-terse | prometheus)
opt_batch_format="$1"
shift
;;
@@ -124,7 +124,7 @@ while [ -n "${1:-}" ]; do
'') ;; # allow nothing at all
*)
echo "$0: error: unknown batch format '$1'" >&2
echo "$0: error: --batch expects a format from: text, nrpe, json" >&2
echo "$0: error: --batch expects a format from: text, nrpe, json, json-terse" >&2
exit 255
;;
esac

View File

@@ -1,4 +1,245 @@
# vim: set ts=4 sw=4 sts=4 et:
# --- JSON helper functions ---
# Escape a string for use in a JSON value (handles backslashes, double quotes, newlines, tabs)
# Args: $1=string
# Prints: escaped string (without surrounding quotes)
_json_escape() {
printf '%s' "$1" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/ /\\t/g' | tr '\n' ' '
}
# Convert a shell capability value to a JSON token
# Args: $1=value (1=true, 0=false, -1/empty=null, other string=quoted string)
# Prints: JSON token
_json_cap() {
case "${1:-}" in
1) printf 'true' ;;
0) printf 'false' ;;
-1|'') printf 'null' ;;
*) printf '"%s"' "$(_json_escape "$1")" ;;
esac
}
# Emit a JSON string value or null
# Args: $1=string (empty=null)
# Prints: JSON token ("escaped string" or null)
_json_str() {
if [ -n "${1:-}" ]; then
printf '"%s"' "$(_json_escape "$1")"
else
printf 'null'
fi
}
# Emit a JSON number value or null
# Args: $1=number (empty=null)
# Prints: JSON token
_json_num() {
if [ -n "${1:-}" ]; then
printf '%s' "$1"
else
printf 'null'
fi
}
# Emit a JSON boolean value or null
# Args: $1=value (1/0/empty)
# Prints: JSON token
_json_bool() {
case "${1:-}" in
1) printf 'true' ;;
0) printf 'false' ;;
*) printf 'null' ;;
esac
}
# --- JSON section builders (comprehensive format) ---
# Build the "meta" section of the comprehensive JSON output
# Sets: g_json_meta
# shellcheck disable=SC2034
_build_json_meta() {
local timestamp mode
timestamp=$(date -u '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || echo "unknown")
if [ "$opt_live" = 1 ]; then
mode="live"
else
mode="offline"
fi
local run_as_root
if [ "$(id -u)" -eq 0 ]; then
run_as_root='true'
else
run_as_root='false'
fi
g_json_meta=$(printf '{"script_version":%s,"format_version":1,"timestamp":%s,"os":%s,"mode":"%s","run_as_root":%s,"reduced_accuracy":%s,"paranoid":%s,"sysfs_only":%s,"no_hw":%s,"extra":%s}' \
"$(_json_str "$VERSION")" \
"$(_json_str "$timestamp")" \
"$(_json_str "$g_os")" \
"$mode" \
"$run_as_root" \
"$(_json_bool "${g_bad_accuracy:-0}")" \
"$(_json_bool "$opt_paranoid")" \
"$(_json_bool "$opt_sysfs_only")" \
"$(_json_bool "$opt_no_hw")" \
"$(_json_bool "$opt_extra")")
}
# Build the "system" section of the comprehensive JSON output
# Sets: g_json_system
# shellcheck disable=SC2034
_build_json_system() {
local kernel_release kernel_version kernel_arch smt_val
if [ "$opt_live" = 1 ]; then
kernel_release=$(uname -r)
kernel_version=$(uname -v)
kernel_arch=$(uname -m)
else
kernel_release=''
kernel_version=''
kernel_arch=''
fi
# SMT detection
is_cpu_smt_enabled
smt_val=$?
case $smt_val in
0) smt_val='true' ;;
1) smt_val='false' ;;
*) smt_val='null' ;;
esac
g_json_system=$(printf '{"kernel_release":%s,"kernel_version":%s,"kernel_arch":%s,"kernel_image":%s,"kernel_config":%s,"kernel_version_string":%s,"kernel_cmdline":%s,"cpu_count":%s,"smt_enabled":%s,"hypervisor_host":%s,"hypervisor_host_reason":%s}' \
"$(_json_str "$kernel_release")" \
"$(_json_str "$kernel_version")" \
"$(_json_str "$kernel_arch")" \
"$(_json_str "${opt_kernel:-}")" \
"$(_json_str "${opt_config:-}")" \
"$(_json_str "${g_kernel_version:-}")" \
"$(_json_str "${g_kernel_cmdline:-}")" \
"$(_json_num "${g_max_core_id:+$((g_max_core_id + 1))}")" \
"$smt_val" \
"$(_json_bool "${g_has_vmm:-}")" \
"$(_json_str "${g_has_vmm_reason:-}")")
}
# Build the "cpu" section of the comprehensive JSON output
# Sets: g_json_cpu
# shellcheck disable=SC2034
_build_json_cpu() {
local cpuid_hex ucode_hex codename caps
if [ -n "${cpu_cpuid:-}" ]; then
cpuid_hex=$(printf '0x%08x' "$cpu_cpuid")
else
cpuid_hex=''
fi
if [ -n "${cpu_ucode:-}" ]; then
ucode_hex=$(printf '0x%x' "$cpu_ucode")
else
ucode_hex=''
fi
codename=''
if is_intel; then
codename=$(get_intel_codename 2>/dev/null || true)
fi
# Build capabilities sub-object
caps=$(printf '{"spec_ctrl":%s,"ibrs":%s,"ibpb":%s,"ibpb_ret":%s,"stibp":%s,"ssbd":%s,"l1d_flush":%s,"md_clear":%s,"arch_capabilities":%s,"rdcl_no":%s,"ibrs_all":%s,"rsba":%s,"l1dflush_no":%s,"ssb_no":%s,"mds_no":%s,"taa_no":%s,"pschange_msc_no":%s,"tsx_ctrl_msr":%s,"tsx_ctrl_rtm_disable":%s,"tsx_ctrl_cpuid_clear":%s,"gds_ctrl":%s,"gds_no":%s,"gds_mitg_dis":%s,"gds_mitg_lock":%s,"rfds_no":%s,"rfds_clear":%s,"its_no":%s,"sbdr_ssdp_no":%s,"fbsdp_no":%s,"psdp_no":%s,"fb_clear":%s,"rtm":%s,"tsx_force_abort":%s,"tsx_force_abort_rtm_disable":%s,"tsx_force_abort_cpuid_clear":%s,"sgx":%s,"srbds":%s,"srbds_on":%s,"amd_ssb_no":%s,"hygon_ssb_no":%s,"ipred":%s,"rrsba":%s,"bhi":%s,"tsa_sq_no":%s,"tsa_l1_no":%s,"verw_clear":%s,"autoibrs":%s,"sbpb":%s,"avx2":%s,"avx512":%s}' \
"$(_json_cap "${cap_spec_ctrl:-}")" \
"$(_json_cap "${cap_ibrs:-}")" \
"$(_json_cap "${cap_ibpb:-}")" \
"$(_json_cap "${cap_ibpb_ret:-}")" \
"$(_json_cap "${cap_stibp:-}")" \
"$(_json_cap "${cap_ssbd:-}")" \
"$(_json_cap "${cap_l1df:-}")" \
"$(_json_cap "${cap_md_clear:-}")" \
"$(_json_cap "${cap_arch_capabilities:-}")" \
"$(_json_cap "${cap_rdcl_no:-}")" \
"$(_json_cap "${cap_ibrs_all:-}")" \
"$(_json_cap "${cap_rsba:-}")" \
"$(_json_cap "${cap_l1dflush_no:-}")" \
"$(_json_cap "${cap_ssb_no:-}")" \
"$(_json_cap "${cap_mds_no:-}")" \
"$(_json_cap "${cap_taa_no:-}")" \
"$(_json_cap "${cap_pschange_msc_no:-}")" \
"$(_json_cap "${cap_tsx_ctrl_msr:-}")" \
"$(_json_cap "${cap_tsx_ctrl_rtm_disable:-}")" \
"$(_json_cap "${cap_tsx_ctrl_cpuid_clear:-}")" \
"$(_json_cap "${cap_gds_ctrl:-}")" \
"$(_json_cap "${cap_gds_no:-}")" \
"$(_json_cap "${cap_gds_mitg_dis:-}")" \
"$(_json_cap "${cap_gds_mitg_lock:-}")" \
"$(_json_cap "${cap_rfds_no:-}")" \
"$(_json_cap "${cap_rfds_clear:-}")" \
"$(_json_cap "${cap_its_no:-}")" \
"$(_json_cap "${cap_sbdr_ssdp_no:-}")" \
"$(_json_cap "${cap_fbsdp_no:-}")" \
"$(_json_cap "${cap_psdp_no:-}")" \
"$(_json_cap "${cap_fb_clear:-}")" \
"$(_json_cap "${cap_rtm:-}")" \
"$(_json_cap "${cap_tsx_force_abort:-}")" \
"$(_json_cap "${cap_tsx_force_abort_rtm_disable:-}")" \
"$(_json_cap "${cap_tsx_force_abort_cpuid_clear:-}")" \
"$(_json_cap "${cap_sgx:-}")" \
"$(_json_cap "${cap_srbds:-}")" \
"$(_json_cap "${cap_srbds_on:-}")" \
"$(_json_cap "${cap_amd_ssb_no:-}")" \
"$(_json_cap "${cap_hygon_ssb_no:-}")" \
"$(_json_cap "${cap_ipred:-}")" \
"$(_json_cap "${cap_rrsba:-}")" \
"$(_json_cap "${cap_bhi:-}")" \
"$(_json_cap "${cap_tsa_sq_no:-}")" \
"$(_json_cap "${cap_tsa_l1_no:-}")" \
"$(_json_cap "${cap_verw_clear:-}")" \
"$(_json_cap "${cap_autoibrs:-}")" \
"$(_json_cap "${cap_sbpb:-}")" \
"$(_json_cap "${cap_avx2:-}")" \
"$(_json_cap "${cap_avx512:-}")")
g_json_cpu=$(printf '{"vendor":%s,"friendly_name":%s,"family":%s,"model":%s,"stepping":%s,"cpuid":%s,"platform_id":%s,"hybrid":%s,"codename":%s,"arm_part_list":%s,"arm_arch_list":%s,"capabilities":%s}' \
"$(_json_str "${cpu_vendor:-}")" \
"$(_json_str "${cpu_friendly_name:-}")" \
"$(_json_num "${cpu_family:-}")" \
"$(_json_num "${cpu_model:-}")" \
"$(_json_num "${cpu_stepping:-}")" \
"$(_json_str "$cpuid_hex")" \
"$(_json_num "${cpu_platformid:-}")" \
"$(_json_bool "${cpu_hybrid:-}")" \
"$(_json_str "$codename")" \
"$(_json_str "${cpu_part_list:-}")" \
"$(_json_str "${cpu_arch_list:-}")" \
"$caps")
}
# Build the "cpu_microcode" section of the comprehensive JSON output
# Sets: g_json_cpu_microcode
# shellcheck disable=SC2034
_build_json_cpu_microcode() {
local ucode_uptodate ucode_hex latest_hex blacklisted
if [ -n "${cpu_ucode:-}" ]; then
ucode_hex=$(printf '0x%x' "$cpu_ucode")
else
ucode_hex=''
fi
is_latest_known_ucode
case $? in
0) ucode_uptodate='true' ;;
1) ucode_uptodate='false' ;;
*) ucode_uptodate='null' ;;
esac
if is_ucode_blacklisted; then
blacklisted='true'
else
blacklisted='false'
fi
latest_hex="${ret_is_latest_known_ucode_version:-}"
g_json_cpu_microcode=$(printf '{"installed_version":%s,"latest_version":%s,"microcode_up_to_date":%s,"is_blacklisted":%s,"message":%s,"db_source":%s,"db_info":%s}' \
"$(_json_str "$ucode_hex")" \
"$(_json_str "$latest_hex")" \
"$ucode_uptodate" \
"$blacklisted" \
"$(_json_str "${ret_is_latest_known_ucode_latest:-}")" \
"$(_json_str "${g_mcedb_source:-}")" \
"$(_json_str "${g_mcedb_info:-}")")
}
# --- Format-specific batch emitters ---
# Emit a single CVE result as plain text
@@ -16,28 +257,62 @@ _emit_short() {
g_short_output="${g_short_output}$1 "
}
# Append a CVE result as a JSON object to the batch output buffer
# Append a CVE result as a terse JSON object to the batch output buffer
# Args: $1=cve $2=aka $3=status(UNK|VULN|OK) $4=description
# Sets: g_json_output
# Callers: pvulnstatus
_emit_json() {
_emit_json_terse() {
local is_vuln esc_name esc_infos
case "$3" in
UNK) is_vuln="null" ;;
VULN) is_vuln="true" ;;
OK) is_vuln="false" ;;
*)
echo "$0: error: unknown status '$3' passed to _emit_json()" >&2
echo "$0: error: unknown status '$3' passed to _emit_json_terse()" >&2
exit 255
;;
esac
# escape backslashes and double quotes for valid JSON strings
esc_name=$(printf '%s' "$2" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g')
esc_infos=$(printf '%s' "$4" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g')
esc_name=$(_json_escape "$2")
esc_infos=$(_json_escape "$4")
[ -z "$g_json_output" ] && g_json_output='['
g_json_output="${g_json_output}{\"NAME\":\"$esc_name\",\"CVE\":\"$1\",\"VULNERABLE\":$is_vuln,\"INFOS\":\"$esc_infos\"},"
}
# Append a CVE result as a comprehensive JSON object to the batch output buffer
# Args: $1=cve $2=aka $3=status(UNK|VULN|OK) $4=description
# Sets: g_json_vulns
# Callers: pvulnstatus
_emit_json_full() {
local is_vuln esc_name esc_infos aliases cpu_affected sysfs_status sysfs_msg
case "$3" in
UNK) is_vuln="null" ;;
VULN) is_vuln="true" ;;
OK) is_vuln="false" ;;
*)
echo "$0: error: unknown status '$3' passed to _emit_json_full()" >&2
exit 255
;;
esac
esc_name=$(_json_escape "$2")
esc_infos=$(_json_escape "$4")
aliases=$(_cve_registry_field "$1" 4)
# CPU affection status (cached, cheap)
if is_cpu_affected "$1" 2>/dev/null; then
cpu_affected='true'
else
cpu_affected='false'
fi
# sysfs status: use the value captured by this CVE's check function, then clear it
# so it doesn't leak into the next CVE that might not call sys_interface_check
sysfs_status="${g_json_cve_sysfs_status:-}"
sysfs_msg="${g_json_cve_sysfs_msg:-}"
: "${g_json_vulns:=}"
g_json_vulns="${g_json_vulns}{\"cve\":\"$1\",\"name\":\"$esc_name\",\"aliases\":$(_json_str "$aliases"),\"cpu_affected\":$cpu_affected,\"status\":\"$3\",\"vulnerable\":$is_vuln,\"info\":\"$esc_infos\",\"sysfs_status\":$(_json_str "$sysfs_status"),\"sysfs_message\":$(_json_str "$sysfs_msg")},"
}
# Append vulnerable CVE IDs to the NRPE output buffer
# Args: $1=cve $2=aka $3=status $4=description
# Sets: g_nrpe_vuln
@@ -85,7 +360,8 @@ pvulnstatus() {
case "$opt_batch_format" in
text) _emit_text "$1" "$aka" "$2" "$3" ;;
short) _emit_short "$1" "$aka" "$2" "$3" ;;
json) _emit_json "$1" "$aka" "$2" "$3" ;;
json) _emit_json_full "$1" "$aka" "$2" "$3" ;;
json-terse) _emit_json_terse "$1" "$aka" "$2" "$3" ;;
nrpe) _emit_nrpe "$1" "$aka" "$2" "$3" ;;
prometheus) _emit_prometheus "$1" "$aka" "$2" "$3" ;;
*)
@@ -93,6 +369,9 @@ pvulnstatus() {
exit 255
;;
esac
# reset per-CVE sysfs globals so they don't leak into the next CVE
g_json_cve_sysfs_status=''
g_json_cve_sysfs_msg=''
fi
_record_result "$1" "$2"

View File

@@ -33,11 +33,12 @@ read_inteldb() {
}
# Check whether the CPU is running the latest known microcode version
# Sets: ret_is_latest_known_ucode_latest
# Sets: ret_is_latest_known_ucode_latest, ret_is_latest_known_ucode_version
# Returns: 0=latest, 1=outdated, 2=unknown
is_latest_known_ucode() {
local brand_prefix tuple pfmask ucode ucode_date
parse_cpu_details
ret_is_latest_known_ucode_version=''
if [ "$cpu_cpuid" = 0 ]; then
ret_is_latest_known_ucode_latest="couldn't get your cpuid"
return 2
@@ -64,6 +65,8 @@ is_latest_known_ucode() {
ucode_date=$(echo "$tuple" | cut -d, -f5 | sed -E 's=(....)(..)(..)=\1/\2/\3=')
pr_debug "is_latest_known_ucode: with cpuid $cpu_cpuid has ucode $cpu_ucode, last known is $ucode from $ucode_date"
ret_is_latest_known_ucode_latest=$(printf "latest version is 0x%x dated $ucode_date according to $g_mcedb_info" "$ucode")
# shellcheck disable=SC2034
ret_is_latest_known_ucode_version=$(printf "0x%x" "$ucode")
if [ "$cpu_ucode" -ge "$ucode" ]; then
return 0
else

View File

@@ -312,9 +312,14 @@ sys_interface_check() {
g_mockme=$(printf "%b\n%b" "$g_mockme" "SMC_MOCK_SYSFS_$(basename "$file")='$ret_sys_interface_check_fullmsg'")
fi
if [ "$mode" = silent ]; then
# capture sysfs message for JSON even in silent mode
# shellcheck disable=SC2034
g_json_cve_sysfs_msg="$ret_sys_interface_check_fullmsg"
return 0
elif [ "$mode" = quiet ]; then
pr_info "* Information from the /sys interface: $ret_sys_interface_check_fullmsg"
# shellcheck disable=SC2034
g_json_cve_sysfs_msg="$ret_sys_interface_check_fullmsg"
return 0
fi
pr_info_nol "* Mitigated according to the /sys interface: "
@@ -334,6 +339,11 @@ sys_interface_check() {
ret_sys_interface_check_status=UNK
pstatus yellow UNKNOWN "$ret_sys_interface_check_fullmsg"
fi
# capture for JSON full output (read by _emit_json_full via pvulnstatus)
# shellcheck disable=SC2034
g_json_cve_sysfs_status="$ret_sys_interface_check_status"
# shellcheck disable=SC2034
g_json_cve_sysfs_msg="$ret_sys_interface_check_fullmsg"
pr_debug "sys_interface_check: $file=$msg (re=$regex)"
return 0
}

View File

@@ -1,6 +1,12 @@
# vim: set ts=4 sw=4 sts=4 et:
check_kernel_info
# Build JSON meta and system sections early (after kernel info is resolved)
if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "json" ]; then
_build_json_meta
fi
pr_info
if [ "$opt_no_hw" = 0 ] && [ -z "$opt_arch_prefix" ]; then
@@ -10,6 +16,15 @@ if [ "$opt_no_hw" = 0 ] && [ -z "$opt_arch_prefix" ]; then
pr_info
fi
# Build JSON system/cpu/microcode sections (after check_cpu has populated cap_* vars and VMM detection)
if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "json" ]; then
_build_json_system
if [ "$opt_no_hw" = 0 ] && [ -z "$opt_arch_prefix" ]; then
_build_json_cpu
_build_json_cpu_microcode
fi
fi
# now run the checks the user asked for
for cve in $g_supported_cve_list; do
if [ "$opt_cve_all" = 1 ] || echo "$opt_cve_list" | grep -qw "$cve"; then
@@ -80,10 +95,28 @@ if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "short" ]; then
_pr_echo 0 "${g_short_output% }"
fi
if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "json" ]; then
if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "json-terse" ]; then
_pr_echo 0 "${g_json_output%?}]"
fi
if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "json" ]; then
# Assemble the comprehensive JSON output from pre-built sections
# Inject mocked flag into meta (g_mocked can be set at any point during the run)
g_json_meta="${g_json_meta%\}},\"mocked\":$(_json_bool "${g_mocked:-0}")}"
_json_final='{'
_json_final="${_json_final}\"meta\":${g_json_meta:-null}"
_json_final="${_json_final},\"system\":${g_json_system:-null}"
_json_final="${_json_final},\"cpu\":${g_json_cpu:-null}"
_json_final="${_json_final},\"cpu_microcode\":${g_json_cpu_microcode:-null}"
if [ -n "${g_json_vulns:-}" ]; then
_json_final="${_json_final},\"vulnerabilities\":[${g_json_vulns%,}]"
else
_json_final="${_json_final},\"vulnerabilities\":[]"
fi
_json_final="${_json_final}}"
_pr_echo 0 "$_json_final"
fi
if [ "$opt_batch" = 1 ] && [ "$opt_batch_format" = "prometheus" ]; then
echo "# TYPE specex_vuln_status untyped"
echo "# HELP specex_vuln_status Exposure of system to speculative execution vulnerabilities"

View File

@@ -121,11 +121,21 @@ check_CVE_2018_3639_linux() {
fi
else
if [ -n "$kernel_ssb" ]; then
pvulnstatus "$cve" VULN "Your CPU doesn't support SSBD"
explain "Your kernel is recent enough to use the CPU microcode features for mitigation, but your CPU microcode doesn't actually provide the necessary features for the kernel to use. The microcode of your CPU hence needs to be upgraded. This is usually done at boot time by your kernel (the upgrade is not persistent across reboots which is why it's done at each boot). If you're using a distro, make sure you are up to date, as microcode updates are usually shipped alongside with the distro kernel. Availability of a microcode update for you CPU model depends on your CPU vendor. You can usually find out online if a microcode update is available for your CPU by searching for your CPUID (indicated in the Hardware Check section)."
if [ "$cpu_vendor" = ARM ] || [ "$cpu_vendor" = CAVIUM ] || [ "$cpu_vendor" = PHYTIUM ]; then
pvulnstatus "$cve" VULN "no SSB mitigation is active on your system"
explain "ARM CPUs mitigate SSB either through a hardware SSBS bit (ARMv8.5+ CPUs) or through firmware support for SMCCC ARCH_WORKAROUND_2. Your kernel reports SSB status but neither mechanism appears to be active. For CPUs predating ARMv8.5 (such as Cortex-A57 or Cortex-A72), check with your board or SoC vendor for a firmware update that provides SMCCC ARCH_WORKAROUND_2 support."
else
pvulnstatus "$cve" VULN "Your CPU doesn't support SSBD"
explain "Your kernel is recent enough to use the CPU microcode features for mitigation, but your CPU microcode doesn't actually provide the necessary features for the kernel to use. The microcode of your CPU hence needs to be upgraded. This is usually done at boot time by your kernel (the upgrade is not persistent across reboots which is why it's done at each boot). If you're using a distro, make sure you are up to date, as microcode updates are usually shipped alongside with the distro kernel. Availability of a microcode update for you CPU model depends on your CPU vendor. You can usually find out online if a microcode update is available for your CPU by searching for your CPUID (indicated in the Hardware Check section)."
fi
else
pvulnstatus "$cve" VULN "Neither your CPU nor your kernel support SSBD"
explain "Both your CPU microcode and your kernel are lacking support for mitigation. If you're using a distro kernel, upgrade your distro to get the latest kernel available. Otherwise, recompile the kernel from recent-enough sources. The microcode of your CPU also needs to be upgraded. This is usually done at boot time by your kernel (the upgrade is not persistent across reboots which is why it's done at each boot). If you're using a distro, make sure you are up to date, as microcode updates are usually shipped alongside with the distro kernel. Availability of a microcode update for you CPU model depends on your CPU vendor. You can usually find out online if a microcode update is available for your CPU by searching for your CPUID (indicated in the Hardware Check section)."
if [ "$cpu_vendor" = ARM ] || [ "$cpu_vendor" = CAVIUM ] || [ "$cpu_vendor" = PHYTIUM ]; then
pvulnstatus "$cve" VULN "your kernel and firmware do not support SSB mitigation"
explain "ARM SSB mitigation requires kernel support (CONFIG_ARM64_SSBD) combined with either a hardware SSBS bit (ARMv8.5+ CPUs) or firmware support for SMCCC ARCH_WORKAROUND_2. Ensure you are running a recent kernel compiled with CONFIG_ARM64_SSBD. For CPUs predating ARMv8.5, also check with your board or SoC vendor for a firmware update providing SMCCC ARCH_WORKAROUND_2 support."
else
pvulnstatus "$cve" VULN "Neither your CPU nor your kernel support SSBD"
explain "Both your CPU microcode and your kernel are lacking support for mitigation. If you're using a distro kernel, upgrade your distro to get the latest kernel available. Otherwise, recompile the kernel from recent-enough sources. The microcode of your CPU also needs to be upgraded. This is usually done at boot time by your kernel (the upgrade is not persistent across reboots which is why it's done at each boot). If you're using a distro, make sure you are up to date, as microcode updates are usually shipped alongside with the distro kernel. Availability of a microcode update for you CPU model depends on your CPU vendor. You can usually find out online if a microcode update is available for your CPU by searching for your CPUID (indicated in the Hardware Check section)."
fi
fi
fi
else