diff --git a/vmaas/cache.go b/vmaas/cache.go index 9e061e1..d30a713 100644 --- a/vmaas/cache.go +++ b/vmaas/cache.go @@ -25,9 +25,8 @@ type Cache struct { ArchCompat map[ArchID]map[ArchID]bool - PackageDetails map[PkgID]PackageDetail - Nevra2PkgID map[Nevra]PkgID - NameID2SrcNameIDs map[NameID]map[NameID]struct{} + PackageDetails map[PkgID]PackageDetail + Nevra2PkgID map[Nevra]PkgID RepoIDs []RepoID RepoDetails map[RepoID]RepoDetail diff --git a/vmaas/load.go b/vmaas/load.go index 762de33..9c102b2 100644 --- a/vmaas/load.go +++ b/vmaas/load.go @@ -325,7 +325,6 @@ func loadPkgDetails(c *Cache) { id2pkdDetail := make(map[PkgID]PackageDetail, cnt) nevra2id := make(map[Nevra]PkgID, cnt) srcPkgID2PkgID := make(map[PkgID][]PkgID, cntSrc) - nameID2SrcNameIDs := make(map[NameID]map[NameID]struct{}) var pkgID PkgID for rows.Next() { var det PackageDetail @@ -343,16 +342,6 @@ func loadPkgDetails(c *Cache) { continue } - var srcNameID NameID - row := sqlDB.QueryRow("SELECT name_id FROM package_detail WHERE id = ?", *det.SrcPkgID) - if err := row.Scan(&srcNameID); err != nil { - panic(err) - } - if _, ok := nameID2SrcNameIDs[det.NameID]; !ok { - nameID2SrcNameIDs[det.NameID] = make(map[NameID]struct{}) - } - nameID2SrcNameIDs[det.NameID][srcNameID] = struct{}{} - _, ok := srcPkgID2PkgID[*det.SrcPkgID] if !ok { srcPkgID2PkgID[*det.SrcPkgID] = []PkgID{} @@ -365,7 +354,6 @@ func loadPkgDetails(c *Cache) { c.PackageDetails = id2pkdDetail c.Nevra2PkgID = nevra2id c.SrcPkgID2PkgID = srcPkgID2PkgID - c.NameID2SrcNameIDs = nameID2SrcNameIDs } func loadRepoDetails(c *Cache) { //nolint: funlen diff --git a/vmaas/vulnerabilities.go b/vmaas/vulnerabilities.go index 68550e9..2bddf5c 100644 --- a/vmaas/vulnerabilities.go +++ b/vmaas/vulnerabilities.go @@ -219,17 +219,20 @@ func (r *ProcessedRequest) processProducts(c *Cache, opts *options) []ProductsPa productsPackages := make([]ProductsPackage, 0) for _, pkg := range r.Packages { nameID := c.Packagename2ID[pkg.Nevra.Name] - products := cpes2products(c, r.Cpes, nameID, r.Updates.ModuleList, pkg, opts) + evrID := c.Evr2ID[utils.Evr{Epoch: pkg.Nevra.Epoch, Release: pkg.Nevra.Release, Version: pkg.Nevra.Version}] + archID := c.Arch2ID[pkg.Nevra.Arch] + pkgID := c.Nevra2PkgID[Nevra{NameID: nameID, EvrID: evrID, ArchID: archID}] + products := cpes2products(c, r.Cpes, nameID, pkgID, r.Updates.ModuleList, pkg, opts) if opts.newerReleaseverCsaf && len(r.Cpes) > 0 { // look at newer releasever cpes only when there is a CPE hit for EUS repo - newerReleaseverProducts := cpes2products(c, r.NewerReleaseverCpes, nameID, r.Updates.ModuleList, pkg, opts) + newerReleaseverProducts := cpes2products(c, r.NewerReleaseverCpes, nameID, pkgID, r.Updates.ModuleList, pkg, opts) products.ProductsFixed = append(products.ProductsFixed, newerReleaseverProducts.ProductsFixed...) products.ProductsUnfixed = append(products.ProductsUnfixed, newerReleaseverProducts.ProductsUnfixed...) } if len(r.Cpes) == 0 { // use CPEs from Content Sets if we haven't found any Cpes from repos - products = cpes2products(c, r.ContentSetsCpes, nameID, r.Updates.ModuleList, pkg, opts) + products = cpes2products(c, r.ContentSetsCpes, nameID, pkgID, r.Updates.ModuleList, pkg, opts) } productsPackages = append(productsPackages, products) } @@ -362,7 +365,7 @@ func productWithFixedCVEs(c *Cache, cpe CpeID, nameID NameID, modules []ModuleSt return products, ok } -func cpes2products(c *Cache, cpes []CpeID, nameID NameID, modules []ModuleStream, pkg NevraString, +func cpes2products(c *Cache, cpes []CpeID, nameID NameID, pkgID PkgID, modules []ModuleStream, pkg NevraString, opts *options, ) ProductsPackage { productsUnfixed := make([]CSAFProduct, 0, len(cpes)*(len(modules)+1)) @@ -370,18 +373,37 @@ func cpes2products(c *Cache, cpes []CpeID, nameID NameID, modules []ModuleStream // add empty module to module list to find affected products without modules modules = append(modules, ModuleStream{}) for _, cpe := range cpes { + seenNameIDs := make(map[NameID]bool) // create unfixed products for every CPE, unfixed product has PackageID=0 - for srcNameID := range c.NameID2SrcNameIDs[nameID] { - srcName := c.ID2Packagename[srcNameID] - if opts.excludedPackages[srcName] { - continue - } - productsUnfixed = append(productsUnfixed, productsWithUnfixedCVEs(c, cpe, srcNameID, modules)...) + pkgDetail := c.PackageDetails[pkgID] + srcNameID := pkgDetail.NameID + if pkgDetail.SrcPkgID != nil { + srcPkgDetail := c.PackageDetails[*pkgDetail.SrcPkgID] + srcNameID = srcPkgDetail.NameID + } + + if seenNameIDs[nameID] || seenNameIDs[srcNameID] { + continue } + + srcName := c.ID2Packagename[srcNameID] + if opts.excludedPackages[srcName] { + seenNameIDs[srcNameID] = true + continue + } + productsUnfixed = append(productsUnfixed, productsWithUnfixedCVEs(c, cpe, srcNameID, modules)...) + if srcNameID != nameID { + // find unfixed products for installed package name not name of source package in case CSAF + // shows vulnerability for package name and not source package name + productsUnfixed = append(productsUnfixed, productsWithUnfixedCVEs(c, cpe, nameID, modules)...) + } + // create fixed products for every CPE if products, ok := productWithFixedCVEs(c, cpe, nameID, modules); ok { productsFixed = append(productsFixed, products...) } + seenNameIDs[srcNameID] = true + seenNameIDs[nameID] = true } pp := ProductsPackage{ ProductsFixed: productsFixed, diff --git a/vmaas/vulnerabilities_test.go b/vmaas/vulnerabilities_test.go index 7e6fd12..f44013f 100644 --- a/vmaas/vulnerabilities_test.go +++ b/vmaas/vulnerabilities_test.go @@ -16,6 +16,7 @@ func TestCSAF(t *testing.T) { unfixed := CSAFProduct{CpeID: 1, PackageNameID: 1} fixed1 := CSAFProduct{CpeID: 1, PackageNameID: 1, PackageID: 1} fixed2 := CSAFProduct{CpeID: 2, PackageNameID: 1, PackageID: 2} + var one PkgID = 1 c := Cache{ Arch2ID: map[string]ArchID{"x86_64": 1}, @@ -35,13 +36,9 @@ func TestCSAF(t *testing.T) { {NameID: 2, EvrID: 1, ArchID: 1}: 3, }, PackageDetails: map[PkgID]PackageDetail{ - 1: {NameID: 1, EvrID: 1, ArchID: 1}, // kernel-0:1-1 - 2: {NameID: 1, EvrID: 2, ArchID: 1}, // kernel-0:2-2 - 3: {NameID: 2, EvrID: 1, ArchID: 1}, // kernel-devel-0:1-1 - }, - NameID2SrcNameIDs: map[NameID]map[NameID]struct{}{ - 1: {1: struct{}{}}, - 2: {1: struct{}{}}, + 1: {NameID: 1, EvrID: 1, ArchID: 1, SrcPkgID: nil}, // kernel-0:1-1 + 2: {NameID: 1, EvrID: 2, ArchID: 1, SrcPkgID: nil}, // kernel-0:2-2 + 3: {NameID: 2, EvrID: 1, ArchID: 1, SrcPkgID: &one}, // kernel-devel-0:1-1 }, CSAFCVEs: map[CpeIDNameID]map[CSAFProduct]CSAFCVEs{ {CpeID: 1, NameID: 1}: { @@ -58,6 +55,7 @@ func TestCSAF(t *testing.T) { type expected struct { pkg NevraString nameID NameID + pkgID PkgID fixed []CSAFProduct unfixed []CSAFProduct } @@ -68,18 +66,21 @@ func TestCSAF(t *testing.T) { { pkg: NevraString{Nevra: pkg1, Pkg: pkg1.String()}, nameID: 1, + pkgID: 1, unfixed: []CSAFProduct{unfixed}, fixed: []CSAFProduct{fixed1, fixed2}, }, { pkg: NevraString{Nevra: pkg2, Pkg: pkg2.String()}, nameID: 1, + pkgID: 2, unfixed: []CSAFProduct{unfixed}, fixed: []CSAFProduct{fixed1, fixed2}, }, { pkg: NevraString{Nevra: pkg3, Pkg: pkg3.String()}, nameID: 2, + pkgID: 3, unfixed: []CSAFProduct{unfixed}, fixed: []CSAFProduct{}, }, // match source package @@ -87,7 +88,7 @@ func TestCSAF(t *testing.T) { products := make([]ProductsPackage, 0, len(matrix)) for _, m := range matrix { - pp := cpes2products(&c, []CpeID{1, 2}, m.nameID, []ModuleStream{ms}, m.pkg, &defaultOpts) + pp := cpes2products(&c, []CpeID{1, 2}, m.nameID, m.pkgID, []ModuleStream{ms}, m.pkg, &defaultOpts) assert.Equal(t, m.fixed, pp.ProductsFixed) assert.Equal(t, m.unfixed, pp.ProductsUnfixed) products = append(products, pp)