Skip to content

Commit

Permalink
status: Warn about firmware quirks
Browse files Browse the repository at this point in the history
  • Loading branch information
dawidpotocki committed Feb 19, 2023
1 parent 57f51d9 commit 37526c9
Show file tree
Hide file tree
Showing 5 changed files with 362 additions and 10 deletions.
31 changes: 21 additions & 10 deletions cmd/sbctl/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/foxboron/sbctl"
"github.com/foxboron/sbctl/fs"
"github.com/foxboron/sbctl/logging"
"github.com/foxboron/sbctl/quirks"
"github.com/spf13/cobra"
)

Expand All @@ -19,20 +20,22 @@ var statusCmd = &cobra.Command{
}

type Status struct {
Installed bool `json:"installed"`
GUID string `json:"guid"`
SetupMode bool `json:"setup_mode"`
SecureBoot bool `json:"secure_boot"`
Vendors []string `json:"vendors"`
Installed bool `json:"installed"`
GUID string `json:"guid"`
SetupMode bool `json:"setup_mode"`
SecureBoot bool `json:"secure_boot"`
Vendors []string `json:"vendors"`
FirmwareQuirks []quirks.Quirk `json:"firmware_quirks"`
}

func NewStatus() *Status {
return &Status{
Installed: false,
GUID: "",
SetupMode: false,
SecureBoot: false,
Vendors: []string{},
Installed: false,
GUID: "",
SetupMode: false,
SecureBoot: false,
Vendors: []string{},
FirmwareQuirks: []quirks.Quirk{},
}
}

Expand Down Expand Up @@ -65,6 +68,13 @@ func PrintStatus(s *Status) {
logging.Print("Vendor Keys:\t")
logging.Println(strings.Join(s.Vendors, " "))
}
if len(s.FirmwareQuirks) > 0 {
logging.Print("Firmware:\t")
logging.Print(logging.Warnf("Your firmware has known quirks"))
for _, quirk := range s.FirmwareQuirks {
logging.Println("\t\t- " + quirk.ID + ": " + quirk.Name + " (" + quirk.Severity + ")\n\t\t " + quirk.Link)
}
}
}

func RunStatus(cmd *cobra.Command, args []string) error {
Expand All @@ -88,6 +98,7 @@ func RunStatus(cmd *cobra.Command, args []string) error {
if keys := sbctl.GetEnrolledVendorCerts(); len(keys) > 0 {
stat.Vendors = keys
}
stat.FirmwareQuirks = quirks.CheckFirmwareQuirks()
if cmdOptions.JsonOutput {
if err := JsonOut(stat); err != nil {
return err
Expand Down
152 changes: 152 additions & 0 deletions cmd/sbctl/status_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package main

import (
"reflect"
"testing"
"testing/fstest"

"github.com/foxboron/go-uefi/efi/efitest"
"github.com/foxboron/sbctl/quirks"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -38,3 +41,152 @@ func TestStatusOn(t *testing.T) {
t.Fatal("secure boot is not enabled")
}
}

func TestFQ0001DateMethod(t *testing.T) {
SetFS(
fstest.MapFS{"/sys/devices/virtual/dmi/id/bios_date": {Data: []byte("01/06/2023\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/bios_version": {Data: []byte("A.30\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/board_name": {Data: []byte("PRO Z790-A WIFI (MS-7E07)\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/board_vendor": {Data: []byte("Micro-Star International Co., Ltd.\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/chassis_type": {Data: []byte("3\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/product_name": {Data: []byte("MS-7E07\n")}},
efitest.SecureBootOn(),
)

if err := captureJsonOutput(&out, func() error {
return RunStatus(&cobra.Command{}, []string{})
}); err != nil {
t.Fatal(err)
}

fq0001 := quirks.Quirk{}
for _, quirk := range out.FirmwareQuirks {
if quirk.ID == "FQ0001" {
fq0001 = quirk
}
}

if reflect.ValueOf(fq0001).IsZero() {
t.Fatal("quirk not detected")
} else if fq0001.Method != "date" {
t.Fatal("expected 'date' method, got '" + fq0001.Method + "'")
}
}

func TestFQ0001DeviceMethod(t *testing.T) {
SetFS(
fstest.MapFS{"/sys/devices/virtual/dmi/id/bios_date": {Data: []byte("12/29/2021\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/bios_version": {Data: []byte("1.80\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/board_name": {Data: []byte("MAG X570 TOMAHAWK WIFI (MS-7C84)\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/board_vendor": {Data: []byte("Micro-Star International Co., Ltd.\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/chassis_type": {Data: []byte("3\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/product_name": {Data: []byte("MS-7C84\n")}},
efitest.SecureBootOn(),
)

if err := captureJsonOutput(&out, func() error {
return RunStatus(&cobra.Command{}, []string{})
}); err != nil {
t.Fatal(err)
}

fq0001 := quirks.Quirk{}
for _, quirk := range out.FirmwareQuirks {
if quirk.ID == "FQ0001" {
fq0001 = quirk
}
}

if reflect.ValueOf(fq0001).IsZero() {
t.Fatal("quirk not detected")
} else if fq0001.Method != "device_name" {
t.Fatal("expected 'device_name' method, got '" + fq0001.Method + "'")
}
}

func TestFQ0001ExplicitlyUnaffected(t *testing.T) {
SetFS(
fstest.MapFS{"/sys/devices/virtual/dmi/id/bios_date": {Data: []byte("03/31/2022\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/bios_version": {Data: []byte("1.B0\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/board_name": {Data: []byte("MAG Z490 TOMAHAWK (MS-7C80)\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/board_vendor": {Data: []byte("Micro-Star International Co., Ltd.\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/chassis_type": {Data: []byte("3\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/product_name": {Data: []byte("MS-7C80\n")}},
efitest.SecureBootOn(),
)

if err := captureJsonOutput(&out, func() error {
return RunStatus(&cobra.Command{}, []string{})
}); err != nil {
t.Fatal(err)
}

fq0001 := quirks.Quirk{}
for _, quirk := range out.FirmwareQuirks {
if quirk.ID == "FQ0001" {
fq0001 = quirk
}
}

if !reflect.ValueOf(fq0001).IsZero() {
t.Fatal("quirk got detected, with method '" + fq0001.Method + "'")
}
}

func TestFQ0001WrongChassis(t *testing.T) {
SetFS(
fstest.MapFS{"/sys/devices/virtual/dmi/id/bios_date": {Data: []byte("01/06/2023\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/bios_version": {Data: []byte("A.30\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/board_name": {Data: []byte("PRO Z790-A WIFI (MS-7E07)\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/board_vendor": {Data: []byte("Micro-Star International Co., Ltd.\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/chassis_type": {Data: []byte("5\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/product_name": {Data: []byte("MS-7E07\n")}},
efitest.SecureBootOn(),
)

if err := captureJsonOutput(&out, func() error {
return RunStatus(&cobra.Command{}, []string{})
}); err != nil {
t.Fatal(err)
}

fq0001 := quirks.Quirk{}
for _, quirk := range out.FirmwareQuirks {
if quirk.ID == "FQ0001" {
fq0001 = quirk
}
}

if !reflect.ValueOf(fq0001).IsZero() {
t.Fatal("quirk got detected using '" + fq0001.Method + "' method")
}
}

func TestFQ0001WrongVendor(t *testing.T) {
SetFS(
fstest.MapFS{"/sys/devices/virtual/dmi/id/bios_date": {Data: []byte("01/06/2023\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/bios_version": {Data: []byte("A.30\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/board_name": {Data: []byte("PRO Z790-A WIFI (MS-7E07)\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/board_vendor": {Data: []byte("Micro-Security International Co., Ltd.\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/chassis_type": {Data: []byte("3\n")}},
fstest.MapFS{"/sys/devices/virtual/dmi/id/product_name": {Data: []byte("MS-7E07\n")}},
efitest.SecureBootOn(),
)

if err := captureJsonOutput(&out, func() error {
return RunStatus(&cobra.Command{}, []string{})
}); err != nil {
t.Fatal(err)
}

fq0001 := quirks.Quirk{}
for _, quirk := range out.FirmwareQuirks {
if quirk.ID == "FQ0001" {
fq0001 = quirk
}
}

if !reflect.ValueOf(fq0001).IsZero() {
t.Fatal("quirk got detected using '" + fq0001.Method + "' method")
}
}
51 changes: 51 additions & 0 deletions dmi/dmi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package dmi

import (
"strings"
"time"

"github.com/foxboron/sbctl/fs"
)

var Table = DMI{}

type DMI struct {
BoardName string `json:"board_name"`
BoardVendor string `json:"board_vendor"`
BoardVersion string `json:"board_version"`
ChassisType string `json:"chassis_type"`
FirmwareDate time.Time `json:"firmware_date"`
FirmwareRelease string `json:"firmware_release"`
FirmwareVendor string `json:"firmware_vendor"`
FirmwareVersion string `json:"firmware_version"`
ProductFamily string `json:"product_family"`
ProductName string `json:"product_name"`
ProductSKU string `json:"product_sku"`
ProductVersion string `json:"product_version"`
SystemVendor string `json:"system_vendor"`
}

func readValue(filename string) string {
f, _ := fs.ReadFile("/sys/devices/virtual/dmi/id/" + filename)
return strings.TrimSpace(string(f))
}

func ParseDMI() DMI {
dmi := DMI{}

dmi.BoardName = readValue("board_name")
dmi.BoardVendor = readValue("board_vendor")
dmi.BoardVersion = readValue("board_version")
dmi.ChassisType = readValue("chassis_type")
dmi.FirmwareDate, _ = time.Parse("01/02/2006", readValue("bios_date"))
dmi.FirmwareRelease = readValue("bios_release")
dmi.FirmwareVendor = readValue("bios_vendor")
dmi.FirmwareVersion = readValue("bios_version")
dmi.ProductFamily = readValue("product_family")
dmi.ProductName = readValue("product_name")
dmi.ProductSKU = readValue("product_sku")
dmi.ProductVersion = readValue("product_version")
dmi.SystemVendor = readValue("sys_vendor")

return dmi
}
57 changes: 57 additions & 0 deletions quirks/fq0001.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package quirks

import (
"time"

"github.com/foxboron/sbctl/dmi"
)

var FQ0001 = Quirk {
ID: "FQ0001",
Name: "Defaults to executing on Secure Boot policy violation",
Severity: "CRITICAL",
}

func HasFQ0001() bool {
unaffectedVersions := []unaffectedVersion{
// MSI MAG Z490 TOMAHAWK
{Name: "MS-7C80", NameSrc: &dmi.Table.ProductName, NameStrict: true, Version: "1.B0", VersionSrc: &dmi.Table.FirmwareVersion},
// MSI H310M PRO-C
{Name: "MS-7D02", NameSrc: &dmi.Table.ProductName, NameStrict: true, Version: "1.20", VersionSrc: &dmi.Table.FirmwareVersion},
}

affectedDateRanges := []affectedDateRange{
{From: time.Date(2022, 5, 10, 0, 0, 0, 0, time.UTC)},
}

affectedDevices := []affectedDevice{
// MSI AMD boards
{Name: "X570", NameSrc: &dmi.Table.BoardName, NameStrict: false, DateFrom: time.Date(2021, 12, 16, 0, 0, 0, 0, time.UTC)},
{Name: "X470", NameSrc: &dmi.Table.BoardName, NameStrict: false, DateFrom: time.Date(2021, 9, 28, 0, 0, 0, 0, time.UTC)},
{Name: "B550", NameSrc: &dmi.Table.BoardName, NameStrict: false, DateFrom: time.Date(2021, 12, 13, 0, 0, 0, 0, time.UTC)},
{Name: "B450", NameSrc: &dmi.Table.BoardName, NameStrict: false, DateFrom: time.Date(2021, 12, 13, 0, 0, 0, 0, time.UTC)},
{Name: "B350", NameSrc: &dmi.Table.BoardName, NameStrict: false, DateFrom: time.Date(2021, 11, 1, 0, 0, 0, 0, time.UTC)},
{Name: "A520", NameSrc: &dmi.Table.BoardName, NameStrict: false, DateFrom: time.Date(2021, 9, 11, 0, 0, 0, 0, time.UTC)},
// MSI Intel boards
{Name: "Z590", NameSrc: &dmi.Table.BoardName, NameStrict: false, DateFrom: time.Date(2021, 9, 6, 0, 0, 0, 0, time.UTC)},
{Name: "Z490", NameSrc: &dmi.Table.BoardName, NameStrict: false, DateFrom: time.Date(2021, 9, 30, 0, 0, 0, 0, time.UTC)},
{Name: "B560", NameSrc: &dmi.Table.BoardName, NameStrict: false, DateFrom: time.Date(2021, 9, 9, 0, 0, 0, 0, time.UTC)},
{Name: "B460", NameSrc: &dmi.Table.BoardName, NameStrict: false, DateFrom: time.Date(2021, 10, 22, 0, 0, 0, 0, time.UTC)},
{Name: "H510", NameSrc: &dmi.Table.BoardName, NameStrict: false, DateFrom: time.Date(2021, 9, 10, 0, 0, 0, 0, time.UTC)},
{Name: "H410", NameSrc: &dmi.Table.BoardName, NameStrict: false, DateFrom: time.Date(2021, 10, 22, 0, 0, 0, 0, time.UTC)},
}

if dmi.Table.BoardVendor == "Micro-Star International Co., Ltd." && dmi.Table.ChassisType == "3" {
if isUnaffectedVersion(unaffectedVersions) {
return false
} else if isAffectedDate(affectedDateRanges) {
FQ0001.Method = "date"
return true
} else if isAffectedDevice(affectedDevices) {
FQ0001.Method = "device_name"
return true
}
}

return false
}
Loading

0 comments on commit 37526c9

Please sign in to comment.