github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/cmds/core/sluinit/uinit.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 main
     6  
     7  import (
     8  	"errors"
     9  	"flag"
    10  	"fmt"
    11  	"log"
    12  	"os"
    13  	"time"
    14  
    15  	"github.com/u-root/iscsinl"
    16  	"github.com/u-root/u-root/pkg/cmdline"
    17  	"github.com/u-root/u-root/pkg/dhclient"
    18  	slaunch "github.com/u-root/u-root/pkg/securelaunch"
    19  	"github.com/u-root/u-root/pkg/securelaunch/policy"
    20  	"github.com/u-root/u-root/pkg/securelaunch/tpm"
    21  )
    22  
    23  var (
    24  	slDebug = flag.Bool("d", false, "enable debug logs")
    25  )
    26  
    27  func checkDebugFlag() {
    28  	/*
    29  	 * check if uroot.uinitargs=-d is set in kernel cmdline.
    30  	 * if set, slaunch.Debug is set to log.Printf.
    31  	 */
    32  	flag.Parse()
    33  
    34  	if flag.NArg() > 1 {
    35  		log.Fatal("Incorrect number of arguments")
    36  	}
    37  
    38  	if *slDebug {
    39  		slaunch.Debug = log.Printf
    40  		slaunch.Debug("debug flag is set. Logging Enabled.")
    41  	}
    42  }
    43  
    44  /*
    45   * main parses platform policy file, and based on the inputs,
    46   * performs measurements and then launches a target kernel.
    47   *
    48   * steps followed by sluinit:
    49   * 1. if debug flag is set, enable logging.
    50   * 2. gets the TPM handle
    51   * 3. Gets secure launch policy file entered by user.
    52   * 4. calls collectors to collect measurements(hashes) a.k.a evidence.
    53   */
    54  func main() {
    55  	checkDebugFlag()
    56  
    57  	err := scanIscsiDrives()
    58  	if err != nil {
    59  		log.Printf("NO ISCSI DRIVES found, err=[%v]", err)
    60  	}
    61  
    62  	defer unmountAndExit() // called only on error, on success we kexec
    63  	slaunch.Debug("********Step 1: init completed. starting main ********")
    64  	if err := tpm.New(); err != nil {
    65  		log.Printf("tpm.New() failed. err=%v", err)
    66  		return
    67  	}
    68  	defer tpm.Close()
    69  
    70  	slaunch.Debug("********Step 2: locate and parse SL Policy ********")
    71  	p, err := policy.Get()
    72  	if err != nil {
    73  		log.Printf("failed to get policy err=%v", err)
    74  		return
    75  	}
    76  	slaunch.Debug("policy file successfully parsed")
    77  
    78  	slaunch.Debug("********Step 3: Collecting Evidence ********")
    79  	for _, c := range p.Collectors {
    80  		slaunch.Debug("Input Collector: %v", c)
    81  		if e := c.Collect(); e != nil {
    82  			log.Printf("Collector %v failed, err = %v", c, e)
    83  		}
    84  	}
    85  	slaunch.Debug("Collectors completed")
    86  
    87  	slaunch.Debug("********Step 4: Measuring target kernel, initrd ********")
    88  	if err := p.Launcher.MeasureKernel(); err != nil {
    89  		log.Printf("Launcher.MeasureKernel failed err=%v", err)
    90  		return
    91  	}
    92  
    93  	slaunch.Debug("********Step 5: Parse eventlogs *********")
    94  	if err := p.EventLog.Parse(); err != nil {
    95  		log.Printf("EventLog.Parse() failed err=%v", err)
    96  		return
    97  	}
    98  
    99  	slaunch.Debug("*****Step 6: Dump logs to disk *******")
   100  	if err := slaunch.ClearPersistQueue(); err != nil {
   101  		log.Printf("ClearPersistQueue failed err=%v", err)
   102  		return
   103  	}
   104  
   105  	slaunch.Debug("********Step *: Unmount all ********")
   106  	slaunch.UnmountAll()
   107  
   108  	slaunch.Debug("********Step 7: Launcher called to Boot ********")
   109  	if err := p.Launcher.Boot(); err != nil {
   110  		log.Printf("Boot failed. err=%s", err)
   111  		return
   112  	}
   113  }
   114  
   115  // unmountAndExit is called on error and unmounts all devices.
   116  // sluinit ends here.
   117  func unmountAndExit() {
   118  	slaunch.UnmountAll()
   119  	time.Sleep(5 * time.Second) // let queued up debug statements get printed
   120  	os.Exit(1)
   121  }
   122  
   123  // scanIscsiDrives calls dhcleint to parse cmdline and
   124  // iscsinl to mount iscsi drives.
   125  func scanIscsiDrives() error {
   126  	val, ok := cmdline.Flag("netroot")
   127  	if !ok {
   128  		return errors.New("netroot flag is not set")
   129  	}
   130  	slaunch.Debug("netroot flag is set with val=%s", val)
   131  
   132  	target, volume, err := dhclient.ParseISCSIURI(val)
   133  	if err != nil {
   134  		return fmt.Errorf("dhclient ISCSI parser failed err=%v", err)
   135  	}
   136  
   137  	slaunch.Debug("resolved ip:port=%s", target)
   138  	slaunch.Debug("resolved vol=%v", volume)
   139  
   140  	slaunch.Debug("Scanning kernel cmd line for *rd.iscsi.initiator* flag")
   141  	initiatorName, ok := cmdline.Flag("rd.iscsi.initiator")
   142  	if !ok {
   143  		return errors.New("rd.iscsi.initiator flag is not set")
   144  	}
   145  
   146  	devices, err := iscsinl.MountIscsi(
   147  		iscsinl.WithInitiator(initiatorName),
   148  		iscsinl.WithTarget(target.String(), volume),
   149  		iscsinl.WithCmdsMax(128),
   150  		iscsinl.WithQueueDepth(16),
   151  		iscsinl.WithScheduler("noop"),
   152  	)
   153  	if err != nil {
   154  		return err
   155  	}
   156  
   157  	for i := range devices {
   158  		slaunch.Debug("Mounted at dev %v", devices[i])
   159  	}
   160  	return nil
   161  }