github.com/xyproto/u-root@v6.0.1-0.20200302025726-5528e0c77a3c+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  /*
    28   * Boot boots the target kernel based on information provided
    29   * in the "launcher" section of policy file.
    30   *
    31   * Summary of steps:
    32   * - extracts the kernel, initrd and cmdline from the "launcher" section of policy file.
    33   * - measures the kernel and initrd file into the tpmDev (tpm device).
    34   * - mounts the disks where the kernel and initrd file are located.
    35   * - uses kexec to boot into the target kernel.
    36   * returns error
    37   * - if measurement of kernel and initrd fails
    38   * - if mount fails
    39   * - if kexec fails
    40   */
    41  func (l *Launcher) Boot(tpmDev io.ReadWriteCloser) error {
    42  
    43  	if l.Type != "kexec" {
    44  		log.Printf("launcher: Unsupported launcher type. Exiting.")
    45  		return fmt.Errorf("launcher: Unsupported launcher type. Exiting")
    46  	}
    47  
    48  	slaunch.Debug("Identified Launcher Type = Kexec")
    49  
    50  	// TODO: if kernel and initrd are on different devices.
    51  	kernel := l.Params["kernel"]
    52  	initrd := l.Params["initrd"]
    53  	cmdline := l.Params["cmdline"]
    54  
    55  	slaunch.Debug("********Step 6: Measuring kernel, initrd ********")
    56  	if e := measurement.HashFile(tpmDev, kernel); e != nil {
    57  		log.Printf("launcher: ERR: measure kernel input=%s, err=%v", kernel, e)
    58  		return e
    59  	}
    60  
    61  	if e := measurement.HashFile(tpmDev, initrd); e != nil {
    62  		log.Printf("launcher: ERR: measure initrd input=%s, err=%v", initrd, e)
    63  		return e
    64  	}
    65  
    66  	k, _, e := slaunch.GetMountedFilePath(kernel, mount.MS_RDONLY)
    67  	if e != nil {
    68  		log.Printf("launcher: ERR: kernel input %s couldnt be located, err=%v", kernel, e)
    69  		return e
    70  	}
    71  
    72  	i, _, e := slaunch.GetMountedFilePath(initrd, mount.MS_RDONLY)
    73  	if e != nil {
    74  		log.Printf("launcher: ERR: initrd input %s couldnt be located, err=%v", initrd, e)
    75  		return e
    76  	}
    77  
    78  	slaunch.Debug("********Step 7: kexec called  ********")
    79  	image := &boot.LinuxImage{
    80  		Kernel:  uio.NewLazyFile(k),
    81  		Initrd:  uio.NewLazyFile(i),
    82  		Cmdline: cmdline,
    83  	}
    84  	if err := image.Load(false); err != nil {
    85  		log.Printf("kexec -l failed. err: %v", err)
    86  		return err
    87  	}
    88  
    89  	err := kexec.Reboot()
    90  	if err != nil {
    91  		log.Printf("kexec reboot failed. err=%v", err)
    92  	}
    93  	return nil
    94  }