github.com/andrewsun2898/u-root@v6.0.1-0.20200616011413-4b2895c1b815+incompatible/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  	"io"
    11  	"log"
    12  
    13  	"github.com/u-root/u-root/pkg/boot"
    14  	"github.com/u-root/u-root/pkg/boot/kexec"
    15  	"github.com/u-root/u-root/pkg/mount"
    16  	slaunch "github.com/u-root/u-root/pkg/securelaunch"
    17  	"github.com/u-root/u-root/pkg/securelaunch/measurement"
    18  	"github.com/u-root/u-root/pkg/uio"
    19  )
    20  
    21  /* describes the "launcher" section of policy file */
    22  type Launcher struct {
    23  	Type   string            `json:"type"`
    24  	Params map[string]string `json:"params"`
    25  }
    26  
    27  // MeasureKernel calls file collector in measurement pkg that
    28  // hashes kernel, initrd files and even store these hashes in tpm pcrs.
    29  func (l *Launcher) MeasureKernel(tpmDev io.ReadWriteCloser) error {
    30  
    31  	kernel := l.Params["kernel"]
    32  	initrd := l.Params["initrd"]
    33  
    34  	if e := measurement.HashFile(tpmDev, kernel); e != nil {
    35  		log.Printf("ERR: measure kernel input=%s, err=%v", kernel, e)
    36  		return e
    37  	}
    38  
    39  	if e := measurement.HashFile(tpmDev, initrd); e != nil {
    40  		log.Printf("ERR: measure initrd input=%s, err=%v", initrd, e)
    41  		return e
    42  	}
    43  	return nil
    44  }
    45  
    46  /*
    47   * Boot boots the target kernel based on information provided
    48   * in the "launcher" section of policy file.
    49   *
    50   * Summary of steps:
    51   * - extracts the kernel, initrd and cmdline from the "launcher" section of policy file.
    52   * - measures the kernel and initrd file into the tpmDev (tpm device).
    53   * - mounts the disks where the kernel and initrd file are located.
    54   * - uses kexec to boot into the target kernel.
    55   * returns error
    56   * - if measurement of kernel and initrd fails
    57   * - if mount fails
    58   * - if kexec fails
    59   */
    60  func (l *Launcher) Boot(tpmDev io.ReadWriteCloser) error {
    61  
    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("********Step 7: kexec called  ********")
    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  }