github.com/nextlinux/gosbom@v0.81.1-0.20230627115839-1ff50c281391/gosbom/pkg/cataloger/kernel/parse_linux_kernel_file.go (about) 1 package kernel 2 3 import ( 4 "fmt" 5 "strconv" 6 "strings" 7 8 "github.com/deitch/magic/pkg/magic" 9 "github.com/nextlinux/gosbom/gosbom/artifact" 10 "github.com/nextlinux/gosbom/gosbom/file" 11 "github.com/nextlinux/gosbom/gosbom/pkg" 12 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/generic" 13 "github.com/nextlinux/gosbom/gosbom/pkg/cataloger/internal/unionreader" 14 "github.com/nextlinux/gosbom/internal/log" 15 ) 16 17 const linuxKernelMagicName = "Linux kernel" 18 19 func parseLinuxKernelFile(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) { 20 unionReader, err := unionreader.GetUnionReader(reader) 21 if err != nil { 22 return nil, nil, fmt.Errorf("unable to get union reader for file: %w", err) 23 } 24 magicType, err := magic.GetType(unionReader) 25 if err != nil { 26 return nil, nil, fmt.Errorf("unable to get magic type for file: %w", err) 27 } 28 if len(magicType) < 1 || magicType[0] != linuxKernelMagicName { 29 return nil, nil, nil 30 } 31 metadata := parseLinuxKernelMetadata(magicType) 32 if metadata.Version == "" { 33 return nil, nil, nil 34 } 35 36 return []pkg.Package{ 37 newLinuxKernelPackage( 38 metadata, 39 reader.Location, 40 ), 41 }, nil, nil 42 } 43 44 func parseLinuxKernelMetadata(magicType []string) (p pkg.LinuxKernelMetadata) { 45 // Linux kernel x86 boot executable bzImage, 46 // version 5.10.121-linuxkit (root@buildkitsandbox) #1 SMP Fri Dec 2 10:35:42 UTC 2022, 47 // RO-rootFS, 48 // swap_dev 0XA, 49 // Normal VGA 50 for _, t := range magicType { 51 switch { 52 case strings.HasPrefix(t, "x86 "): 53 p.Architecture = "x86" 54 case strings.Contains(t, "ARM64 "): 55 p.Architecture = "arm64" 56 case strings.Contains(t, "ARM "): 57 p.Architecture = "arm" 58 case t == "bzImage": 59 p.Format = "bzImage" 60 case t == "zImage": 61 p.Format = "zImage" 62 case strings.HasPrefix(t, "version "): 63 p.ExtendedVersion = strings.TrimPrefix(t, "version ") 64 fields := strings.Fields(p.ExtendedVersion) 65 if len(fields) > 0 { 66 p.Version = fields[0] 67 } 68 case strings.Contains(t, "rootFS") && strings.HasPrefix(t, "RW-"): 69 p.RWRootFS = true 70 case strings.HasPrefix(t, "swap_dev "): 71 swapDevStr := strings.TrimPrefix(t, "swap_dev ") 72 swapDev, err := strconv.ParseInt(swapDevStr, 16, 32) 73 if err != nil { 74 log.Warnf("unable to parse swap device: %s", err) 75 continue 76 } 77 p.SwapDevice = int(swapDev) 78 case strings.HasPrefix(t, "root_dev "): 79 rootDevStr := strings.TrimPrefix(t, "root_dev ") 80 rootDev, err := strconv.ParseInt(rootDevStr, 16, 32) 81 if err != nil { 82 log.Warnf("unable to parse root device: %s", err) 83 continue 84 } 85 p.SwapDevice = int(rootDev) 86 case strings.Contains(t, "VGA") || strings.Contains(t, "Video"): 87 p.VideoMode = t 88 } 89 } 90 return p 91 }