From 5f49bd31481da0d37a01ac493620e4115a76cec4 Mon Sep 17 00:00:00 2001 From: MaineK00n Date: Mon, 13 Feb 2023 18:27:22 +0900 Subject: [PATCH] feat(gost/ubuntu): check kernel source package more strictly --- gost/debian.go | 2 +- gost/debian_test.go | 35 +++++++++++++ gost/ubuntu.go | 124 +++++++++++++++++++++++++++++++++++++++++--- gost/ubuntu_test.go | 51 ++++++++++++++++++ 4 files changed, 203 insertions(+), 9 deletions(-) diff --git a/gost/debian.go b/gost/debian.go index ea6b18b9be..574745fd7d 100644 --- a/gost/debian.go +++ b/gost/debian.go @@ -181,7 +181,7 @@ func (deb Debian) isKernelSourcePackage(pkgname string) bool { case 1: return pkgname == "linux" case 2: - if ss[0] != "liunx" { + if ss[0] != "linux" { return false } switch ss[1] { diff --git a/gost/debian_test.go b/gost/debian_test.go index f663b85add..25f0118cd3 100644 --- a/gost/debian_test.go +++ b/gost/debian_test.go @@ -309,3 +309,38 @@ func TestDebian_detect(t *testing.T) { }) } } + +func TestDebian_isKernelSourcePackage(t *testing.T) { + tests := []struct { + pkgname string + want bool + }{ + { + pkgname: "linux", + want: true, + }, + { + pkgname: "apt", + want: false, + }, + { + pkgname: "linux-5.10", + want: true, + }, + { + pkgname: "linux-grsec", + want: true, + }, + { + pkgname: "linux-base", + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.pkgname, func(t *testing.T) { + if got := (Debian{}).isKernelSourcePackage(tt.pkgname); got != tt.want { + t.Errorf("Debian.isKernelSourcePackage() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/gost/ubuntu.go b/gost/ubuntu.go index 47cde38965..449ba51e96 100644 --- a/gost/ubuntu.go +++ b/gost/ubuntu.go @@ -6,7 +6,7 @@ package gost import ( "encoding/json" "fmt" - "regexp" + "strconv" "strings" debver "github.com/knqyf263/go-deb-version" @@ -70,8 +70,6 @@ type cveContent struct { fixStatuses models.PackageFixStatuses } -var kernelSourceNamePattern = regexp.MustCompile(`^linux((-(ti-omap4|armadaxp|mako|manta|flo|goldfish|joule|raspi2?|snapdragon|aws|azure|bluefield|dell300x|gcp|gke(op)?|ibm|intel|lowlatency|kvm|oem|oracle|euclid|lts-xenial|hwe|riscv))?(-(edge|fde|iotg|hwe|osp1))?(-[\d\.]+)?)?$`) - // DetectCVEs fills cve information that has in Gost func (ubu Ubuntu) DetectCVEs(r *models.ScanResult, _ bool) (nCVEs int, err error) { if !ubu.supported(strings.Replace(r.Release, ".", "", 1)) { @@ -121,7 +119,7 @@ func (ubu Ubuntu) detectCVEsWithFixState(r *models.ScanResult, fixed bool) ([]st n := strings.NewReplacer("linux-signed", "linux", "linux-meta", "linux").Replace(res.request.packName) - if kernelSourceNamePattern.MatchString(n) { + if ubu.isKernelSourcePackage(n) { isRunning := false for _, bn := range r.SrcPackages[res.request.packName].BinaryNames { if bn == fmt.Sprintf("linux-image-%s", r.RunningKernel.Release) { @@ -151,7 +149,7 @@ func (ubu Ubuntu) detectCVEsWithFixState(r *models.ScanResult, fixed bool) ([]st for _, p := range r.SrcPackages { n := strings.NewReplacer("linux-signed", "linux", "linux-meta", "linux").Replace(p.Name) - if kernelSourceNamePattern.MatchString(n) { + if ubu.isKernelSourcePackage(n) { isRunning := false for _, bn := range p.BinaryNames { if bn == fmt.Sprintf("linux-image-%s", r.RunningKernel.Release) { @@ -225,7 +223,7 @@ func (ubu Ubuntu) detect(cves map[string]gostmodels.UbuntuCVE, fixed bool, srcPk patchedVersion := rp.Note // https://git.launchpad.net/ubuntu-cve-tracker/tree/scripts/generate-oval#n384 - if kernelSourceNamePattern.MatchString(n) && strings.HasPrefix(srcPkg.Name, "linux-meta") { + if ubu.isKernelSourcePackage(n) && strings.HasPrefix(srcPkg.Name, "linux-meta") { // 5.15.0.1026.30~20.04.16 -> 5.15.0.1026 ss := strings.Split(installedVersion, ".") if len(ss) >= 4 { @@ -247,7 +245,7 @@ func (ubu Ubuntu) detect(cves map[string]gostmodels.UbuntuCVE, fixed bool, srcPk if affected { for _, bn := range srcPkg.BinaryNames { - if kernelSourceNamePattern.MatchString(n) && bn != runningKernelBinaryPkgName { + if ubu.isKernelSourcePackage(n) && bn != runningKernelBinaryPkgName { continue } c.fixStatuses = append(c.fixStatuses, models.PackageFixStatus{ @@ -260,7 +258,7 @@ func (ubu Ubuntu) detect(cves map[string]gostmodels.UbuntuCVE, fixed bool, srcPk } } else { for _, bn := range srcPkg.BinaryNames { - if kernelSourceNamePattern.MatchString(n) && bn != runningKernelBinaryPkgName { + if ubu.isKernelSourcePackage(n) && bn != runningKernelBinaryPkgName { continue } c.fixStatuses = append(c.fixStatuses, models.PackageFixStatus{ @@ -322,3 +320,113 @@ func (ubu Ubuntu) ConvertToModel(cve *gostmodels.UbuntuCVE) *models.CveContent { Published: cve.PublicDate, } } + +// https://git.launchpad.net/ubuntu-cve-tracker/tree/scripts/cve_lib.py#n931 +func (ubu Ubuntu) isKernelSourcePackage(pkgname string) bool { + switch ss := strings.Split(pkgname, "-"); len(ss) { + case 1: + return pkgname == "linux" + case 2: + if ss[0] != "linux" { + return false + } + switch ss[1] { + case "armadaxp", "mako", "manta", "flo", "goldfish", "joule", "raspi", "raspi2", "snapdragon", "aws", "azure", "bluefield", "dell300x", "gcp", "gke", "gkeop", "ibm", "lowlatency", "kvm", "oem", "oracle", "euclid", "hwe", "riscv": + return true + default: + _, err := strconv.ParseFloat(ss[1], 64) + return err == nil + } + case 3: + if ss[0] != "linux" { + return false + } + switch ss[1] { + case "ti": + return ss[2] == "omap4" + case "raspi", "raspi2", "gke", "gkeop", "ibm", "oracle", "riscv": + _, err := strconv.ParseFloat(ss[2], 64) + return err == nil + case "aws": + switch ss[2] { + case "hwe", "edge": + return true + default: + _, err := strconv.ParseFloat(ss[2], 64) + return err == nil + } + case "azure": + switch ss[2] { + case "fde", "edge": + return true + default: + _, err := strconv.ParseFloat(ss[2], 64) + return err == nil + } + case "gcp": + switch ss[2] { + case "edge": + return true + default: + _, err := strconv.ParseFloat(ss[2], 64) + return err == nil + } + case "intel": + switch ss[2] { + case "iotg": + return true + default: + _, err := strconv.ParseFloat(ss[2], 64) + return err == nil + } + case "oem": + switch ss[2] { + case "osp1": + return true + default: + _, err := strconv.ParseFloat(ss[2], 64) + return err == nil + } + case "lts": + return ss[2] == "xenial" + case "hwe": + switch ss[2] { + case "edge": + return true + default: + _, err := strconv.ParseFloat(ss[2], 64) + return err == nil + } + default: + return false + } + case 4: + if ss[0] != "linux" { + return false + } + switch ss[1] { + case "azure": + if ss[2] != "fde" { + return false + } + _, err := strconv.ParseFloat(ss[3], 64) + return err == nil + case "intel": + if ss[2] != "iotg" { + return false + } + _, err := strconv.ParseFloat(ss[3], 64) + return err == nil + case "lowlatency": + if ss[2] != "hwe" { + return false + } + _, err := strconv.ParseFloat(ss[3], 64) + return err == nil + default: + return false + } + default: + return false + } +} diff --git a/gost/ubuntu_test.go b/gost/ubuntu_test.go index 03acbb63eb..a4522c56c9 100644 --- a/gost/ubuntu_test.go +++ b/gost/ubuntu_test.go @@ -278,3 +278,54 @@ func Test_detect(t *testing.T) { }) } } + +func TestUbuntu_isKernelSourcePackage(t *testing.T) { + tests := []struct { + pkgname string + want bool + }{ + { + pkgname: "linux", + want: true, + }, + { + pkgname: "apt", + want: false, + }, + { + pkgname: "linux-aws", + want: true, + }, + { + pkgname: "linux-5.9", + want: true, + }, + { + pkgname: "linux-base", + want: false, + }, + { + pkgname: "apt-utils", + want: false, + }, + { + pkgname: "linux-aws-edge", + want: true, + }, + { + pkgname: "linux-aws-5.15", + want: true, + }, + { + pkgname: "linux-lowlatency-hwe-5.15", + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.pkgname, func(t *testing.T) { + if got := (Ubuntu{}).isKernelSourcePackage(tt.pkgname); got != tt.want { + t.Errorf("Ubuntu.isKernelSourcePackage() = %v, want %v", got, tt.want) + } + }) + } +}