github.com/noqcks/syft@v0.0.0-20230920222752-a9e2c4e288e5/syft/pkg/cataloger/kernel/cataloger.go (about) 1 /* 2 Package kernel provides a concrete Cataloger implementation for linux kernel and module files. 3 */ 4 package kernel 5 6 import ( 7 "github.com/hashicorp/go-multierror" 8 9 "github.com/anchore/syft/internal/log" 10 "github.com/anchore/syft/syft/artifact" 11 "github.com/anchore/syft/syft/file" 12 "github.com/anchore/syft/syft/pkg" 13 "github.com/anchore/syft/syft/pkg/cataloger/generic" 14 ) 15 16 var _ pkg.Cataloger = (*LinuxKernelCataloger)(nil) 17 18 type LinuxCatalogerConfig struct { 19 CatalogModules bool 20 } 21 22 type LinuxKernelCataloger struct { 23 cfg LinuxCatalogerConfig 24 } 25 26 func DefaultLinuxCatalogerConfig() LinuxCatalogerConfig { 27 return LinuxCatalogerConfig{ 28 CatalogModules: true, 29 } 30 } 31 32 var kernelArchiveGlobs = []string{ 33 "**/kernel", 34 "**/kernel-*", 35 "**/vmlinux", 36 "**/vmlinux-*", 37 "**/vmlinuz", 38 "**/vmlinuz-*", 39 } 40 41 var kernelModuleGlobs = []string{ 42 "**/lib/modules/**/*.ko", 43 } 44 45 // NewLinuxKernelCataloger returns a new kernel files cataloger object. 46 func NewLinuxKernelCataloger(cfg LinuxCatalogerConfig) *LinuxKernelCataloger { 47 return &LinuxKernelCataloger{ 48 cfg: cfg, 49 } 50 } 51 52 func (l LinuxKernelCataloger) Name() string { 53 return "linux-kernel-cataloger" 54 } 55 56 func (l LinuxKernelCataloger) Catalog(resolver file.Resolver) ([]pkg.Package, []artifact.Relationship, error) { 57 var allPackages []pkg.Package 58 var allRelationships []artifact.Relationship 59 var errs error 60 61 kernelPackages, kernelRelationships, err := generic.NewCataloger(l.Name()).WithParserByGlobs(parseLinuxKernelFile, kernelArchiveGlobs...).Catalog(resolver) 62 if err != nil { 63 errs = multierror.Append(errs, err) 64 } 65 66 allRelationships = append(allRelationships, kernelRelationships...) 67 allPackages = append(allPackages, kernelPackages...) 68 69 if l.cfg.CatalogModules { 70 modulePackages, moduleRelationships, err := generic.NewCataloger(l.Name()).WithParserByGlobs(parseLinuxKernelModuleFile, kernelModuleGlobs...).Catalog(resolver) 71 if err != nil { 72 errs = multierror.Append(errs, err) 73 } 74 75 allPackages = append(allPackages, modulePackages...) 76 77 moduleToKernelRelationships := createKernelToModuleRelationships(kernelPackages, modulePackages) 78 allRelationships = append(allRelationships, moduleRelationships...) 79 allRelationships = append(allRelationships, moduleToKernelRelationships...) 80 } 81 82 return allPackages, allRelationships, errs 83 } 84 85 func createKernelToModuleRelationships(kernelPackages, modulePackages []pkg.Package) []artifact.Relationship { 86 // organize kernel and module packages by kernel version 87 kernelPackagesByVersion := make(map[string][]*pkg.Package) 88 for idx, p := range kernelPackages { 89 kernelPackagesByVersion[p.Version] = append(kernelPackagesByVersion[p.Version], &kernelPackages[idx]) 90 } 91 92 modulesByKernelVersion := make(map[string][]*pkg.Package) 93 for idx, p := range modulePackages { 94 m, ok := p.Metadata.(pkg.LinuxKernelModuleMetadata) 95 if !ok { 96 log.Debug("linux-kernel-module package found without metadata: %s@%s", p.Name, p.Version) 97 continue 98 } 99 modulesByKernelVersion[m.KernelVersion] = append(modulesByKernelVersion[m.KernelVersion], &modulePackages[idx]) 100 } 101 102 // create relationships between kernel and modules: [module] --(depends on)--> [kernel] 103 // since we try to use singular directions for relationships, we'll use "dependency of" here instead: 104 // [kernel] --(dependency of)--> [module] 105 var moduleToKernelRelationships []artifact.Relationship 106 for kernelVersion, modules := range modulesByKernelVersion { 107 kps, ok := kernelPackagesByVersion[kernelVersion] 108 if !ok { 109 // it's ok if there is a module that has no installed kernel... 110 continue 111 } 112 113 // we don't know which kernel is the "right" one, so we'll create a relationship for each one 114 for _, kp := range kps { 115 for _, mp := range modules { 116 moduleToKernelRelationships = append(moduleToKernelRelationships, artifact.Relationship{ 117 // note: relationships should have Package objects, not pointers 118 From: *kp, 119 To: *mp, 120 Type: artifact.DependencyOfRelationship, 121 }) 122 } 123 } 124 } 125 126 return moduleToKernelRelationships 127 }