Skip to content

Commit

Permalink
Infer the package type from ELF package notes (#3008)
Browse files Browse the repository at this point in the history
* fix ELF package types to be honored

Signed-off-by: Alex Goodman <[email protected]>

* prefer OS packages over binary packages when there are duplicates

Signed-off-by: Alex Goodman <[email protected]>

---------

Signed-off-by: Alex Goodman <[email protected]>
  • Loading branch information
wagoodman authored Jul 2, 2024
1 parent c816039 commit 573440b
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import (
func TestMarinerDistroless(t *testing.T) {
sbom, _ := catalogFixtureImage(t, "image-mariner-distroless", source.SquashedScope)

expectedPkgs := 12
// 12 RPMs + 2 binaries with ELF package notes claiming to be RPMs
expectedPkgs := 14
actualPkgs := 0
for range sbom.Artifacts.Packages.Enumerate(pkg.RpmPkg) {
actualPkgs += 1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package relationship

import (
"reflect"
"slices"

"github.com/anchore/syft/internal/sbomsync"
Expand All @@ -21,6 +22,10 @@ var (
binaryCatalogerTypes = []pkg.Type{
pkg.BinaryPkg,
}
binaryMetadataTypes = []string{
reflect.TypeOf(pkg.ELFBinaryPackageNoteJSONPayload{}).Name(),
reflect.TypeOf(pkg.BinarySignature{}).Name(),
}
)

func ExcludeBinariesByFileOwnershipOverlap(accessor sbomsync.Accessor) {
Expand Down Expand Up @@ -60,5 +65,15 @@ func excludeBinaryByFileOwnershipOverlap(r artifact.Relationship, c *pkg.Collect
return false
}

return slices.Contains(binaryCatalogerTypes, child.Type)
if slices.Contains(binaryCatalogerTypes, child.Type) {
return true
}

if child.Metadata == nil {
return false
}

childMetadataType := reflect.TypeOf(child.Metadata)

return slices.Contains(binaryMetadataTypes, childMetadataType.Name())
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ func TestExclude(t *testing.T) {
packageB := pkg.Package{Name: "package-a", Type: pkg.PythonPkg}
packageC := pkg.Package{Name: "package-a", Type: pkg.BinaryPkg}
packageD := pkg.Package{Name: "package-d", Type: pkg.BinaryPkg}
for _, p := range []*pkg.Package{&packageA, &packageB, &packageC, &packageD} {
packageE := pkg.Package{Name: "package-e", Type: pkg.RpmPkg, Metadata: pkg.ELFBinaryPackageNoteJSONPayload{Type: "rpm"}}
packageF := pkg.Package{Name: "package-f", Type: pkg.RpmPkg, Metadata: pkg.BinarySignature{}}
for _, p := range []*pkg.Package{&packageA, &packageB, &packageC, &packageD, &packageE, &packageF} {
p := p
p.SetID()
}
Expand Down Expand Up @@ -43,6 +45,26 @@ func TestExclude(t *testing.T) {
packages: pkg.NewCollection(packageA, packageC),
shouldExclude: true,
},
{
name: "exclusions from os -> elf binary (as RPM)",
relationship: artifact.Relationship{
Type: artifact.OwnershipByFileOverlapRelationship,
From: packageA,
To: packageE,
},
packages: pkg.NewCollection(packageA, packageE),
shouldExclude: true,
},
{
name: "exclusions from os -> binary (masquerading as RPM)",
relationship: artifact.Relationship{
Type: artifact.OwnershipByFileOverlapRelationship,
From: packageA,
To: packageF,
},
packages: pkg.NewCollection(packageA, packageF),
shouldExclude: true,
},
{
name: "no exclusions from python -> binary",
relationship: artifact.Relationship{
Expand Down
22 changes: 19 additions & 3 deletions syft/pkg/cataloger/binary/elf_package.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func newELFPackage(metadata elfBinaryPackageNotes, locations file.LocationSet) p
Version: metadata.Version,
Licenses: pkg.NewLicenseSet(pkg.NewLicense(metadata.License)),
PURL: packageURL(metadata),
Type: pkg.BinaryPkg,
Type: pkgType(metadata.Type),
Locations: locations,
Metadata: metadata.ELFBinaryPackageNoteJSONPayload,
}
Expand Down Expand Up @@ -67,6 +67,8 @@ func packageURL(metadata elfBinaryPackageNotes) string {
).ToString()
}

const alpmType = "alpm"

func purlDistroType(ty string) string {
switch ty {
case "rpm":
Expand All @@ -75,8 +77,22 @@ func purlDistroType(ty string) string {
return packageurl.TypeDebian
case "apk":
return packageurl.TypeAlpine
case "alpm":
return "alpm"
case alpmType:
return alpmType
}
return packageurl.TypeGeneric
}

func pkgType(ty string) pkg.Type {
switch ty {
case "rpm":
return pkg.RpmPkg
case "deb":
return pkg.DebPkg
case "apk":
return pkg.ApkPkg
case alpmType:
return pkg.AlpmPkg
}
return pkg.BinaryPkg
}
4 changes: 2 additions & 2 deletions syft/pkg/cataloger/binary/elf_package_cataloger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func Test_ELF_Package_Cataloger(t *testing.T) {
file.NewLocation("/sha1sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Licenses: pkg.NewLicenseSet(),
Type: pkg.BinaryPkg,
Type: pkg.RpmPkg,
Metadata: pkg.ELFBinaryPackageNoteJSONPayload{
Type: "rpm",
Architecture: "x86_64",
Expand All @@ -99,7 +99,7 @@ func Test_ELF_Package_Cataloger(t *testing.T) {
file.NewLocation("/sha1sum").WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
),
Licenses: pkg.NewLicenseSet(),
Type: pkg.BinaryPkg,
Type: pkg.RpmPkg,
Metadata: pkg.ELFBinaryPackageNoteJSONPayload{
Type: "rpm",
Architecture: "arm",
Expand Down

0 comments on commit 573440b

Please sign in to comment.