From ae3259d963e865e2373ac937545c964cf9ea77a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Pedro=20Lima?= Date: Fri, 22 Sep 2023 14:11:32 +0100 Subject: [PATCH] Improve sysfs vulnerability parsing (#568) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The existing sysfs vulnerability parsing routines expected the data provided by the kernel to start with either "Not Affected"/"Vulnerable"/"Mitigation"; however, there are a handful of vulnerabilities that can provide data not matching this expectation: - https://elixir.bootlin.com/linux/v6.1.53/source/arch/x86/kernel/cpu/bugs.c#L2519 - https://elixir.bootlin.com/linux/v6.1.53/source/arch/x86/kernel/cpu/bugs.c#L546 - https://elixir.bootlin.com/linux/v6.1.53/source/arch/x86/kernel/cpu/bugs.c#L2578 Modify the vulnerability parsing to make use of a 4th state ("Unknown"), which is used when the vulnerability information can't be parsed to any of the other vulnerability states, and output the information provided by the kernel, rather than erroring out. Vulnerability parsing tests have been updated to include the aforementioned vulnerability data. Signed-off-by: João Lima Co-authored-by: Ben Kochie --- sysfs/vulnerability.go | 16 +++++++++++++--- sysfs/vulnerability_test.go | 5 +++-- testdata/fixtures.ttar | 7 ++++++- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/sysfs/vulnerability.go b/sysfs/vulnerability.go index 08927a21..5a14a3e7 100644 --- a/sysfs/vulnerability.go +++ b/sysfs/vulnerability.go @@ -17,7 +17,6 @@ package sysfs import ( - "fmt" "os" "path/filepath" "strings" @@ -27,12 +26,14 @@ const ( notAffected = "not affected" // based on: https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-system-cpu vulnerable = "vulnerable" mitigation = "mitigation" + unknown = "unknown" ) const ( VulnerabilityStateNotAffected = iota VulnerabilityStateVulnerable VulnerabilityStateMitigation + VulnerabilityStateUnknown ) var ( @@ -42,6 +43,7 @@ var ( VulnerabilityStateNotAffected: notAffected, VulnerabilityStateVulnerable: vulnerable, VulnerabilityStateMitigation: mitigation, + VulnerabilityStateUnknown: unknown, } ) @@ -98,9 +100,17 @@ func parseVulnerability(name, rawContent string) (*Vulnerability, error) { if len(m) > 1 { v.Mitigation = strings.Join(m[1:], " ") } + case strings.HasPrefix(rawContentLower, unknown): + v.State = VulnerabilityStateUnknown + m := strings.Fields(rawContent) + if len(m) > 1 { + v.Mitigation = strings.Join(m[1:], " ") + } default: - return nil, fmt.Errorf("unknown vulnerability state for %s: %s", name, rawContent) - + // Output the raw data obtained from the vulnerability, with state + // unknown, rather than erroring out + v.State = VulnerabilityStateUnknown + v.Mitigation = rawContent } return v, nil } diff --git a/sysfs/vulnerability_test.go b/sysfs/vulnerability_test.go index 255586d8..ec9cafcb 100644 --- a/sysfs/vulnerability_test.go +++ b/sysfs/vulnerability_test.go @@ -38,14 +38,15 @@ func TestFS_CPUVulnerabilities(t *testing.T) { want *Vulnerability wantErr bool }{ - {"Not affected", "itlb_multihit", &Vulnerability{CodeName: "itlb_multihit", State: VulnerabilityStateNotAffected, Mitigation: ""}, false}, - {"Not affected with underscores", "tsx_async_abort", &Vulnerability{CodeName: "tsx_async_abort", State: VulnerabilityStateNotAffected, Mitigation: ""}, false}, + {"Not affected", "tsx_async_abort", &Vulnerability{CodeName: "tsx_async_abort", State: VulnerabilityStateNotAffected, Mitigation: ""}, false}, {"Mitigation simple string", "spec_store_bypass", &Vulnerability{CodeName: "spec_store_bypass", State: VulnerabilityStateMitigation, Mitigation: "Speculative Store Bypass disabled via prctl"}, false}, {"Mitigation special chars", "retbleed", &Vulnerability{CodeName: "retbleed", State: VulnerabilityStateMitigation, Mitigation: "untrained return thunk; SMT enabled with STIBP protection"}, false}, {"Mitigation more special chars", "spectre_v1", &Vulnerability{CodeName: "spectre_v1", State: VulnerabilityStateMitigation, Mitigation: "usercopy/swapgs barriers and __user pointer sanitization"}, false}, {"Mitigation with multiple subsections", "spectre_v2", &Vulnerability{CodeName: "spectre_v2", State: VulnerabilityStateMitigation, Mitigation: "Retpolines, IBPB: conditional, STIBP: always-on, RSB filling, PBRSB-eIBRS: Not affected"}, false}, {"Vulnerable", "mds", &Vulnerability{CodeName: "mds", State: VulnerabilityStateVulnerable, Mitigation: ""}, false}, {"Vulnerable with mitigation available", "mmio_stale_data", &Vulnerability{CodeName: "mmio_stale_data", State: VulnerabilityStateVulnerable, Mitigation: "Clear CPU buffers attempted, no microcode"}, false}, + {"Unknown", "srbds", &Vulnerability{CodeName: "srbds", State: VulnerabilityStateUnknown, Mitigation: "Dependent on hypervisor status"}, false}, + {"Unknown with unparseable mitigation", "itlb_multihit", &Vulnerability{CodeName: "itlb_multihit", State: VulnerabilityStateUnknown, Mitigation: "KVM: Mitigation: VMX unsupported"}, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/testdata/fixtures.ttar b/testdata/fixtures.ttar index ae2e0f0b..39ec9462 100644 --- a/testdata/fixtures.ttar +++ b/testdata/fixtures.ttar @@ -13239,7 +13239,7 @@ Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/system/cpu/vulnerabilities/itlb_multihit Lines: 1 -Not affected +KVM: Mitigation: VMX unsupported Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/system/cpu/vulnerabilities/mds @@ -13272,6 +13272,11 @@ Lines: 1 Mitigation: Retpolines, IBPB: conditional, STIBP: always-on, RSB filling, PBRSB-eIBRS: Not affected Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/sys/devices/system/cpu/vulnerabilities/srbds +Lines: 1 +Unknown: Dependent on hypervisor status +Mode: 444 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/system/cpu/vulnerabilities/tsx_async_abort Lines: 1 Not affected