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