github.com/anchore/syft@v1.4.2-0.20240516191711-1bec1fc5d397/syft/pkg/cataloger/kernel/parse_linux_kernel_file.go (about)

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