mirror of
https://github.com/speed47/spectre-meltdown-checker.git
synced 2026-04-02 13:17:07 +02:00
enh: CVE-2017-5715: inventory of all sysfs strings, fix --sysfs-only path
This commit is contained in:
@@ -3,20 +3,211 @@
|
|||||||
# SPECTRE 2 SECTION
|
# SPECTRE 2 SECTION
|
||||||
|
|
||||||
# CVE-2017-5715 Spectre Variant 2 (branch target injection) - entry point
|
# CVE-2017-5715 Spectre Variant 2 (branch target injection) - entry point
|
||||||
|
# Sets: vulnstatus
|
||||||
check_CVE_2017_5715() {
|
check_CVE_2017_5715() {
|
||||||
check_cve 'CVE-2017-5715'
|
check_cve 'CVE-2017-5715'
|
||||||
}
|
}
|
||||||
|
|
||||||
# CVE-2017-5715 Spectre Variant 2 (branch target injection) - Linux mitigation check
|
# CVE-2017-5715 Spectre Variant 2 (branch target injection) - Linux mitigation check
|
||||||
|
# Sets: g_ibrs_can_tell, g_ibrs_supported, g_ibrs_enabled, g_ibrs_fw_enabled,
|
||||||
|
# g_ibpb_can_tell, g_ibpb_supported, g_ibpb_enabled, g_specex_knob_dir
|
||||||
check_CVE_2017_5715_linux() {
|
check_CVE_2017_5715_linux() {
|
||||||
local status sys_interface_available msg dir bp_harden_can_tell bp_harden retpoline retpoline_compiler retpoline_compiler_reason retp_enabled rsb_filling explain_hypervisor
|
local status sys_interface_available msg dir bp_harden_can_tell bp_harden retpoline retpoline_compiler retpoline_compiler_reason retp_enabled rsb_filling explain_hypervisor
|
||||||
status=UNK
|
status=UNK
|
||||||
sys_interface_available=0
|
sys_interface_available=0
|
||||||
msg=''
|
msg=''
|
||||||
if sys_interface_check "$VULN_SYSFS_BASE/spectre_v2"; then
|
if sys_interface_check "$VULN_SYSFS_BASE/spectre_v2"; then
|
||||||
# this kernel has the /sys interface, trust it over everything
|
|
||||||
sys_interface_available=1
|
sys_interface_available=1
|
||||||
status=$ret_sys_interface_check_status
|
status=$ret_sys_interface_check_status
|
||||||
|
#
|
||||||
|
# Complete sysfs message inventory for spectre_v2, traced via git blame
|
||||||
|
# on mainline (~/linux) and stable (~/linux-stable):
|
||||||
|
#
|
||||||
|
# all versions:
|
||||||
|
# "Not affected" (cpu_show_common, 61dc0f555b5c)
|
||||||
|
# "Vulnerable" (cpu_show_common fallthrough / spectre_v2_strings[NONE], 61dc0f555b5c)
|
||||||
|
#
|
||||||
|
# The output is a composite string: <base>[<ibpb>][<ibrs_fw>][<stibp>][<rsb>][<pbrsb>][<bhi>][<module>]
|
||||||
|
# where <base> comes from spectre_v2_strings[] (or an early-return override),
|
||||||
|
# and the remaining fields are appended by helper functions.
|
||||||
|
# Before v6.9-rc4 (0cd01ac5dcb1), fields were separated by ", ".
|
||||||
|
# From v6.9-rc4 onward, fields are separated by "; ".
|
||||||
|
#
|
||||||
|
# --- base string (spectre_v2_strings[]) ---
|
||||||
|
#
|
||||||
|
# da285121560e (v4.15, initial spectre_v2 sysfs):
|
||||||
|
# "Vulnerable"
|
||||||
|
# "Mitigation: None" (documented in spectre.rst 5ad3eb113245,
|
||||||
|
# not found in code but listed as a possible value; treat as vulnerable / sysfs override)
|
||||||
|
# "Vulnerable: Minimal generic ASM retpoline"
|
||||||
|
# "Vulnerable: Minimal AMD ASM retpoline"
|
||||||
|
# "Mitigation: Full generic retpoline"
|
||||||
|
# "Mitigation: Full AMD retpoline"
|
||||||
|
# 706d51681d63 (v4.19, added Enhanced IBRS):
|
||||||
|
# + "Mitigation: Enhanced IBRS"
|
||||||
|
# ef014aae8f1c (v4.20-rc5, removed minimal retpoline):
|
||||||
|
# - "Vulnerable: Minimal generic ASM retpoline"
|
||||||
|
# - "Vulnerable: Minimal AMD ASM retpoline"
|
||||||
|
# d45476d98324 (v5.17-rc8, renamed retpoline variants):
|
||||||
|
# "Mitigation: Full generic retpoline" -> "Mitigation: Retpolines"
|
||||||
|
# "Mitigation: Full AMD retpoline" -> "Mitigation: LFENCE" (in array)
|
||||||
|
# NOTE: "Mitigation: LFENCE" was the actual sysfs output for a brief window
|
||||||
|
# (between d45476d98324 and eafd987d4a82, both in v5.17-rc8) before the
|
||||||
|
# show_state override reclassified it as "Vulnerable: LFENCE". LFENCE alone
|
||||||
|
# is now considered an insufficient mitigation for Spectre v2. Any kernel
|
||||||
|
# reporting "Mitigation: LFENCE" is from this narrow window and should be
|
||||||
|
# treated as vulnerable.
|
||||||
|
# 1e19da8522c8 (v5.17-rc8, split Enhanced IBRS into 3 modes):
|
||||||
|
# "Mitigation: Enhanced IBRS" -> "Mitigation: Enhanced IBRS" (EIBRS alone)
|
||||||
|
# + "Mitigation: Enhanced IBRS + LFENCE"
|
||||||
|
# + "Mitigation: Enhanced IBRS + Retpolines"
|
||||||
|
# 7c693f54c873 (v5.19-rc7, added kernel IBRS):
|
||||||
|
# + "Mitigation: IBRS"
|
||||||
|
# e7862eda309e (v6.3-rc1, AMD Automatic IBRS):
|
||||||
|
# "Mitigation: Enhanced IBRS" -> "Mitigation: Enhanced / Automatic IBRS"
|
||||||
|
# "Mitigation: Enhanced IBRS + LFENCE" -> "Mitigation: Enhanced / Automatic IBRS + LFENCE"
|
||||||
|
# "Mitigation: Enhanced IBRS + Retpolines" -> "Mitigation: Enhanced / Automatic IBRS + Retpolines"
|
||||||
|
# d1cc1baef67a (v6.18-rc1, fixed LFENCE in array):
|
||||||
|
# "Mitigation: LFENCE" -> "Vulnerable: LFENCE" (in array, matching the
|
||||||
|
# show_state override that had been correcting the sysfs output since v5.17)
|
||||||
|
#
|
||||||
|
# --- early-return overrides in spectre_v2_show_state() ---
|
||||||
|
#
|
||||||
|
# These bypass the base string + suffix format entirely.
|
||||||
|
#
|
||||||
|
# eafd987d4a82 (v5.17-rc8, LFENCE override):
|
||||||
|
# "Vulnerable: LFENCE"
|
||||||
|
# (overrode the array's "Mitigation: LFENCE"; removed in v6.18-rc1 when the array
|
||||||
|
# was fixed to say "Vulnerable: LFENCE" directly)
|
||||||
|
# 44a3918c8245 (v5.17-rc8, created spectre_v2_show_state, eIBRS+eBPF):
|
||||||
|
# "Vulnerable: Unprivileged eBPF enabled"
|
||||||
|
# (immediately renamed below)
|
||||||
|
# 0de05d056afd (v5.17-rc8, renamed + added eIBRS+LFENCE case):
|
||||||
|
# "Vulnerable: Unprivileged eBPF enabled" -> "Vulnerable: eIBRS with unprivileged eBPF"
|
||||||
|
# + "Vulnerable: eIBRS+LFENCE with unprivileged eBPF and SMT"
|
||||||
|
#
|
||||||
|
# --- <ibpb> suffix (ibpb_state()) ---
|
||||||
|
#
|
||||||
|
# 20ffa1caecca (v4.16-rc1, initial IBPB):
|
||||||
|
# ", IBPB" (present/absent)
|
||||||
|
# a8f76ae41cd6 (v4.20-rc5, extracted ibpb_state()):
|
||||||
|
# ", IBPB: disabled" | ", IBPB: always-on"
|
||||||
|
# 7cc765a67d8e (v4.20-rc5, conditional IBPB):
|
||||||
|
# + ", IBPB: conditional"
|
||||||
|
# 0cd01ac5dcb1 (v6.9-rc4, separator change):
|
||||||
|
# ", IBPB: ..." -> "; IBPB: ..."
|
||||||
|
#
|
||||||
|
# --- <ibrs_fw> suffix ---
|
||||||
|
#
|
||||||
|
# dd84441a7971 (v4.16-rc4):
|
||||||
|
# ", IBRS_FW" (present/absent)
|
||||||
|
# 0cd01ac5dcb1 (v6.9-rc4, separator change):
|
||||||
|
# ", IBRS_FW" -> "; IBRS_FW"
|
||||||
|
#
|
||||||
|
# --- <stibp> suffix (stibp_state()) ---
|
||||||
|
#
|
||||||
|
# 53c613fe6349 (v4.20-rc1, initial STIBP):
|
||||||
|
# ", STIBP" (present/absent)
|
||||||
|
# a8f76ae41cd6 (v4.20-rc5, extracted stibp_state()):
|
||||||
|
# ", STIBP: disabled" | ", STIBP: forced"
|
||||||
|
# 9137bb27e60e (v4.20-rc5, added prctl):
|
||||||
|
# + ", STIBP: conditional" (when prctl/seccomp + switch_to_cond_stibp)
|
||||||
|
# 20c3a2c33e9f (v5.0-rc1, added always-on preferred):
|
||||||
|
# + ", STIBP: always-on"
|
||||||
|
# 34bce7c9690b (v4.20-rc5, eIBRS suppresses STIBP):
|
||||||
|
# returns "" when eIBRS is in use
|
||||||
|
# fd470a8beed8 (v6.5-rc4, AutoIBRS exception):
|
||||||
|
# returns "" only when eIBRS AND not AutoIBRS (AutoIBRS shows STIBP)
|
||||||
|
# 0cd01ac5dcb1 (v6.9-rc4, separator change):
|
||||||
|
# ", STIBP: ..." -> "; STIBP: ..."
|
||||||
|
#
|
||||||
|
# --- <rsb> suffix ---
|
||||||
|
#
|
||||||
|
# bb4b3b776273 (v4.20-rc1):
|
||||||
|
# ", RSB filling" (present/absent)
|
||||||
|
# 53c613fe6349 (v4.20-rc1, temporarily removed, re-added in a8f76ae41cd6)
|
||||||
|
# 0cd01ac5dcb1 (v6.9-rc4, separator change):
|
||||||
|
# ", RSB filling" -> "; RSB filling"
|
||||||
|
#
|
||||||
|
# --- <pbrsb> suffix (pbrsb_eibrs_state()) ---
|
||||||
|
#
|
||||||
|
# 2b1299322016 (v6.0-rc1):
|
||||||
|
# ", PBRSB-eIBRS: Not affected" | ", PBRSB-eIBRS: SW sequence" | ", PBRSB-eIBRS: Vulnerable"
|
||||||
|
# 0cd01ac5dcb1 (v6.9-rc4, separator change):
|
||||||
|
# ", PBRSB-eIBRS: ..." -> "; PBRSB-eIBRS: ..."
|
||||||
|
#
|
||||||
|
# --- <bhi> suffix (spectre_bhi_state()) ---
|
||||||
|
#
|
||||||
|
# ec9404e40e8f (v6.9-rc4):
|
||||||
|
# "; BHI: Not affected" | "; BHI: BHI_DIS_S" | "; BHI: SW loop, KVM: SW loop"
|
||||||
|
# | "; BHI: Retpoline" | "; BHI: Vulnerable"
|
||||||
|
# 95a6ccbdc719 (v6.9-rc4, KVM default):
|
||||||
|
# + "; BHI: Vulnerable, KVM: SW loop"
|
||||||
|
# 5f882f3b0a8b (v6.9-rc4, clarified syscall hardening):
|
||||||
|
# removed "; BHI: Vulnerable (Syscall hardening enabled)"
|
||||||
|
# removed "; BHI: Syscall hardening, KVM: SW loop"
|
||||||
|
# (both replaced by "; BHI: Vulnerable" / "; BHI: Vulnerable, KVM: SW loop")
|
||||||
|
#
|
||||||
|
# --- <module> suffix (spectre_v2_module_string()) ---
|
||||||
|
#
|
||||||
|
# caf7501a1b4e (v4.16-rc1):
|
||||||
|
# " - vulnerable module loaded" (present/absent)
|
||||||
|
#
|
||||||
|
# --- stable backports ---
|
||||||
|
#
|
||||||
|
# 3.2.y: old-style base strings ("Full generic/AMD retpoline", "Minimal generic/AMD
|
||||||
|
# ASM retpoline"). Suffixes: ", IBPB" only (no STIBP/IBRS_FW/RSB). Format: %s%s\n.
|
||||||
|
# Has "Mitigation: Enhanced IBRS" (no "/ Automatic") in later releases.
|
||||||
|
# 3.16.y, 4.4.y: old-style base strings. ibpb_state()/stibp_state()/IBRS_FW/RSB filling.
|
||||||
|
# 3.16.y lacks STIBP "always-on". Comma separators.
|
||||||
|
# Both have "Mitigation: Enhanced IBRS" (no "/ Automatic"). No LFENCE/EIBRS modes.
|
||||||
|
# 4.9.y: has spectre_v2_show_state() with LFENCE override ("Vulnerable: LFENCE"),
|
||||||
|
# eIBRS+eBPF overrides. "Mitigation: Enhanced IBRS" (no "/ Automatic").
|
||||||
|
# No SPECTRE_V2_IBRS. No pbrsb or BHI. Comma separators.
|
||||||
|
# 4.14.y: like 4.9.y but also has SPECTRE_V2_IBRS and pbrsb_eibrs_state().
|
||||||
|
# "Mitigation: Enhanced IBRS" (no "/ Automatic"). No BHI. Comma separators.
|
||||||
|
# 4.19.y: like 4.14.y but has "Enhanced / Automatic IBRS". No BHI. Comma separators.
|
||||||
|
# 5.4.y, 5.10.y: like 4.19.y. No BHI. Comma separators.
|
||||||
|
# 5.15.y, 6.1.y, 6.6.y, 6.12.y: match mainline (semicolons, BHI, all fields).
|
||||||
|
#
|
||||||
|
# --- Red Hat / CentOS / Rocky kernels ---
|
||||||
|
#
|
||||||
|
# Red Hat kernels carry their own spectre_v2 mitigation implementation that differs
|
||||||
|
# significantly from mainline. The following strings are unique to Red Hat kernels:
|
||||||
|
#
|
||||||
|
# centos6 (RHEL 6, kernel 2.6.32): base strings are a superset of mainline v4.15:
|
||||||
|
# "Vulnerable: Minimal ASM retpoline" (no "generic" qualifier)
|
||||||
|
# "Vulnerable: Minimal AMD ASM retpoline"
|
||||||
|
# "Vulnerable: Retpoline without IBPB"
|
||||||
|
# "Vulnerable: Retpoline on Skylake+" (removed in later centos6 releases)
|
||||||
|
# "Vulnerable: Retpoline with unsafe module(s)"
|
||||||
|
# "Mitigation: Full AMD retpoline"
|
||||||
|
# "Mitigation: Full retpoline" (no "generic" qualifier)
|
||||||
|
# "Mitigation: Full retpoline and IBRS (user space)"
|
||||||
|
# "Mitigation: IBRS (kernel)"
|
||||||
|
# "Mitigation: IBRS (kernel and user space)"
|
||||||
|
# "Mitigation: IBP disabled"
|
||||||
|
# Suffixes: ", IBPB" only. Format: %s%s\n.
|
||||||
|
#
|
||||||
|
# centos7 (RHEL 7, kernel 3.10): early releases have all centos6 strings plus
|
||||||
|
# "Vulnerable: Retpoline on Skylake+". Later releases removed Skylake+ and
|
||||||
|
# Minimal AMD, and changed AMD retpoline to:
|
||||||
|
# "Vulnerable: AMD retpoline (LFENCE/JMP)"
|
||||||
|
# Added "Mitigation: Enhanced IBRS". Suffixes: ibpb_state() + stibp_state()
|
||||||
|
# with simple ", IBPB" / ", STIBP" strings. No IBRS_FW/RSB/pbrsb/BHI.
|
||||||
|
#
|
||||||
|
# centos8 (RHEL 8, kernel 4.18): uses mainline v5.17+ style enum names
|
||||||
|
# (RETPOLINE/LFENCE/EIBRS) but retains RHEL-specific entries:
|
||||||
|
# "Mitigation: IBRS (kernel)" (SPECTRE_V2_IBRS)
|
||||||
|
# "Mitigation: Full retpoline and IBRS (user space)" (SPECTRE_V2_RETPOLINE_IBRS_USER)
|
||||||
|
# "Mitigation: IBRS (kernel and user space)" (SPECTRE_V2_IBRS_ALWAYS)
|
||||||
|
# "Mitigation: Enhanced IBRS" (no "/ Automatic"). spectre_v2_show_state() with
|
||||||
|
# LFENCE/eIBRS+eBPF overrides. Comma separators. No pbrsb/BHI.
|
||||||
|
#
|
||||||
|
# rocky9 (RHEL 9, kernel 5.14): matches mainline. Semicolons, BHI, all fields.
|
||||||
|
# rocky10 (RHEL 10, kernel 6.12): matches mainline.
|
||||||
|
#
|
||||||
|
# all messages start with either "Not affected", "Mitigation", or "Vulnerable"
|
||||||
fi
|
fi
|
||||||
if [ "$opt_sysfs_only" != 1 ]; then
|
if [ "$opt_sysfs_only" != 1 ]; then
|
||||||
pr_info "* Mitigation 1"
|
pr_info "* Mitigation 1"
|
||||||
@@ -406,7 +597,9 @@ check_CVE_2017_5715_linux() {
|
|||||||
if ! is_cpu_affected "$cve"; then
|
if ! is_cpu_affected "$cve"; then
|
||||||
# override status & msg in case CPU is not vulnerable after all
|
# override status & msg in case CPU is not vulnerable after all
|
||||||
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"
|
||||||
else
|
elif [ -z "$msg" ]; then
|
||||||
|
if [ "$opt_sysfs_only" != 1 ]; then
|
||||||
|
# --- own logic using Phase 2 variables ---
|
||||||
if [ "$retpoline" = 1 ] && [ "$retpoline_compiler" = 1 ] && [ "$retp_enabled" != 0 ] && [ -n "$g_ibpb_enabled" ] && [ "$g_ibpb_enabled" -ge 1 ] && (! is_vulnerable_to_empty_rsb || [ "$rsb_filling" = 1 ]); then
|
if [ "$retpoline" = 1 ] && [ "$retpoline_compiler" = 1 ] && [ "$retp_enabled" != 0 ] && [ -n "$g_ibpb_enabled" ] && [ "$g_ibpb_enabled" -ge 1 ] && (! is_vulnerable_to_empty_rsb || [ "$rsb_filling" = 1 ]); then
|
||||||
pvulnstatus "$cve" OK "Full retpoline + IBPB are mitigating the vulnerability"
|
pvulnstatus "$cve" OK "Full retpoline + IBPB are mitigating the vulnerability"
|
||||||
elif [ "$retpoline" = 1 ] && [ "$retpoline_compiler" = 1 ] && [ "$retp_enabled" != 0 ] && [ "$opt_paranoid" = 0 ] && (! is_vulnerable_to_empty_rsb || [ "$rsb_filling" = 1 ]); then
|
elif [ "$retpoline" = 1 ] && [ "$retpoline_compiler" = 1 ] && [ "$retp_enabled" != 0 ] && [ "$opt_paranoid" = 0 ] && (! is_vulnerable_to_empty_rsb || [ "$rsb_filling" = 1 ]); then
|
||||||
@@ -454,9 +647,8 @@ check_CVE_2017_5715_linux() {
|
|||||||
explain "To mitigate this vulnerability, you need either IBRS + IBPB, both requiring hardware support from your CPU microcode in addition to kernel support, or a kernel compiled with retpoline and IBPB, with retpoline requiring a retpoline-aware compiler (re-run this script with -v to know if your version of gcc is retpoline-aware) and IBPB requiring hardware support from your CPU microcode. The retpoline + IBPB approach is generally preferred as the performance impact is lower. More information about how to enable the missing bits for those two possible mitigations on your system follow. You only need to take one of the two approaches."
|
explain "To mitigate this vulnerability, you need either IBRS + IBPB, both requiring hardware support from your CPU microcode in addition to kernel support, or a kernel compiled with retpoline and IBPB, with retpoline requiring a retpoline-aware compiler (re-run this script with -v to know if your version of gcc is retpoline-aware) and IBPB requiring hardware support from your CPU microcode. The retpoline + IBPB approach is generally preferred as the performance impact is lower. More information about how to enable the missing bits for those two possible mitigations on your system follow. You only need to take one of the two approaches."
|
||||||
else
|
else
|
||||||
# in that case, we might want to trust sysfs if it's there
|
# in that case, we might want to trust sysfs if it's there
|
||||||
if [ -n "$msg" ]; then
|
if [ "$sys_interface_available" = 1 ]; then
|
||||||
[ "$msg" = Vulnerable ] && msg="no known mitigation exists for your CPU vendor ($cpu_vendor)"
|
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
|
||||||
pvulnstatus "$cve" "$status" "$msg"
|
|
||||||
else
|
else
|
||||||
pvulnstatus "$cve" VULN "no known mitigation exists for your CPU vendor ($cpu_vendor)"
|
pvulnstatus "$cve" VULN "no known mitigation exists for your CPU vendor ($cpu_vendor)"
|
||||||
fi
|
fi
|
||||||
@@ -522,29 +714,19 @@ check_CVE_2017_5715_linux() {
|
|||||||
fi
|
fi
|
||||||
# /RETPOLINE
|
# /RETPOLINE
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
# --sysfs-only: Phase 2 variables are unset, fall back to the
|
||||||
|
# raw sysfs result (status + fullmsg were set in Phase 1).
|
||||||
|
pvulnstatus "$cve" "$status" "$ret_sys_interface_check_fullmsg"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# msg was explicitly set by the "sysfs not available" elif above.
|
||||||
|
pvulnstatus "$cve" "$status" "$msg"
|
||||||
fi
|
fi
|
||||||
# sysfs msgs:
|
|
||||||
#1 "Vulnerable"
|
|
||||||
#2 "Vulnerable: Minimal generic ASM retpoline"
|
|
||||||
#2 "Vulnerable: Minimal AMD ASM retpoline"
|
|
||||||
# "Mitigation: Full generic retpoline"
|
|
||||||
# "Mitigation: Full AMD retpoline"
|
|
||||||
# $MITIGATION + ", IBPB"
|
|
||||||
# $MITIGATION + ", IBRS_FW"
|
|
||||||
#5 $MITIGATION + " - vulnerable module loaded"
|
|
||||||
# Red Hat only:
|
|
||||||
#2 "Vulnerable: Minimal ASM retpoline",
|
|
||||||
#3 "Vulnerable: Retpoline without IBPB",
|
|
||||||
#4 "Vulnerable: Retpoline on Skylake+",
|
|
||||||
#5 "Vulnerable: Retpoline with unsafe module(s)",
|
|
||||||
# "Mitigation: Full retpoline",
|
|
||||||
# "Mitigation: Full retpoline and IBRS (user space)",
|
|
||||||
# "Mitigation: IBRS (kernel)",
|
|
||||||
# "Mitigation: IBRS (kernel and user space)",
|
|
||||||
# "Mitigation: IBP disabled",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# CVE-2017-5715 Spectre Variant 2 (branch target injection) - BSD mitigation check
|
# CVE-2017-5715 Spectre Variant 2 (branch target injection) - BSD mitigation check
|
||||||
|
# Sets: vulnstatus
|
||||||
check_CVE_2017_5715_bsd() {
|
check_CVE_2017_5715_bsd() {
|
||||||
local ibrs_disabled ibrs_active retpoline nb_thunks
|
local ibrs_disabled ibrs_active retpoline nb_thunks
|
||||||
pr_info "* Mitigation 1"
|
pr_info "* Mitigation 1"
|
||||||
|
|||||||
Reference in New Issue
Block a user