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