github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/securelaunch/launcher/launcher.go (about)

     1  // Copyright 2019 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package launcher boots the target kernel.
     6  package launcher
     7  
     8  import (
     9  	"fmt"
    10  	"log"
    11  
    12  	"github.com/mvdan/u-root-coreutils/pkg/boot"
    13  	"github.com/mvdan/u-root-coreutils/pkg/boot/kexec"
    14  	"github.com/mvdan/u-root-coreutils/pkg/mount"
    15  	slaunch "github.com/mvdan/u-root-coreutils/pkg/securelaunch"
    16  	"github.com/mvdan/u-root-coreutils/pkg/securelaunch/measurement"
    17  	"github.com/mvdan/u-root-coreutils/pkg/uio"
    18  )
    19  
    20  // Launcher describes the "launcher" section of policy file.
    21  type Launcher struct {
    22  	Type   string            `json:"type"`
    23  	Params map[string]string `json:"params"`
    24  }
    25  
    26  // MeasureKernel hashes the kernel and extends the measurement into a TPM PCR.
    27  func (l *Launcher) MeasureKernel() error {
    28  	kernel := l.Params["kernel"]
    29  
    30  	if err := measurement.HashFile(kernel); err != nil {
    31  		return err
    32  	}
    33  
    34  	return nil
    35  }
    36  
    37  // MeasureInitrd hashes the initrd and extends the measurement into a TPM PCR.
    38  func (l *Launcher) MeasureInitrd() error {
    39  	initrd := l.Params["initrd"]
    40  
    41  	if err := measurement.HashFile(initrd); err != nil {
    42  		return err
    43  	}
    44  
    45  	return nil
    46  }
    47  
    48  // Boot boots the target kernel based on information provided in the "launcher"
    49  // section of the policy file.
    50  //
    51  // Summary of steps:
    52  // - extract the kernel, initrd and cmdline from the "launcher" section of policy file.
    53  // - measure the kernel and initrd file into the tpmDev (tpm device).
    54  // - mount the disks where the kernel and initrd file are located.
    55  // - kexec to boot into the target kernel.
    56  //
    57  // returns error
    58  // - if measurement of kernel and initrd fails
    59  // - if mount fails
    60  // - if kexec fails
    61  func (l *Launcher) Boot() error {
    62  	if l.Type != "kexec" {
    63  		log.Printf("launcher: Unsupported launcher type. Exiting.")
    64  		return fmt.Errorf("launcher: Unsupported launcher type. Exiting")
    65  	}
    66  
    67  	slaunch.Debug("Identified Launcher Type = Kexec")
    68  
    69  	// TODO: if kernel and initrd are on different devices.
    70  	kernel := l.Params["kernel"]
    71  	initrd := l.Params["initrd"]
    72  	cmdline := l.Params["cmdline"]
    73  
    74  	k, e := slaunch.GetMountedFilePath(kernel, mount.MS_RDONLY)
    75  	if e != nil {
    76  		log.Printf("launcher: ERR: kernel input %s couldnt be located, err=%v", kernel, e)
    77  		return e
    78  	}
    79  
    80  	i, e := slaunch.GetMountedFilePath(initrd, mount.MS_RDONLY)
    81  	if e != nil {
    82  		log.Printf("launcher: ERR: initrd input %s couldnt be located, err=%v", initrd, e)
    83  		return e
    84  	}
    85  
    86  	slaunch.Debug("Calling kexec")
    87  	image := &boot.LinuxImage{
    88  		Kernel:  uio.NewLazyFile(k),
    89  		Initrd:  uio.NewLazyFile(i),
    90  		Cmdline: cmdline,
    91  	}
    92  	err := image.Load(false)
    93  	if err != nil {
    94  		log.Printf("kexec -l failed. err: %v", err)
    95  		return err
    96  	}
    97  
    98  	err = kexec.Reboot()
    99  	if err != nil {
   100  		log.Printf("kexec reboot failed. err=%v", err)
   101  		return err
   102  	}
   103  	return nil
   104  }