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