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