github.com/xyproto/u-root@v6.0.1-0.20200302025726-5528e0c77a3c+incompatible/pkg/securelaunch/helpers.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 securelaunch takes integrity measurements before launching the target system. 6 package securelaunch 7 8 import ( 9 "fmt" 10 "io/ioutil" 11 "log" 12 "os" 13 "path/filepath" 14 "strings" 15 16 "github.com/u-root/u-root/pkg/boot/diskboot" 17 "github.com/u-root/u-root/pkg/storage" 18 ) 19 20 /* used to store all block devices returned from a call to storage.GetBlockStats */ 21 var storageBlkDevices []storage.BlockDev 22 23 /* 24 * if kernel cmd line has uroot.uinitargs=-d, debug fn is enabled. 25 * kernel cmdline is checked in sluinit. 26 */ 27 var Debug = func(string, ...interface{}) {} 28 29 /* 30 * WriteToFile writes a byte slice to a target file on an 31 * already mounted disk and returns the target file path. 32 * 33 * defFileName is default dst file name, only used if user doesn't provide one. 34 */ 35 func WriteToFile(data []byte, dst, defFileName string) (string, error) { 36 37 // make sure dst is an absolute file path 38 if !filepath.IsAbs(dst) { 39 return "", fmt.Errorf("dst =%s Not an absolute path ", dst) 40 } 41 42 // target is the full absolute path where []byte will be written to 43 target := dst 44 dstInfo, err := os.Stat(dst) 45 if err == nil && dstInfo.IsDir() { 46 Debug("No file name provided. Adding it now. old target=%s", target) 47 target = filepath.Join(dst, defFileName) 48 Debug("New target=%s", target) 49 } 50 51 Debug("target=%s", target) 52 err = ioutil.WriteFile(target, data, 0644) 53 if err != nil { 54 return "", fmt.Errorf("failed to write date to file =%s, err=%v", target, err) 55 } 56 Debug("WriteToFile exit w success data written to target=%s", target) 57 return target, nil 58 } 59 60 /* 61 * GetMountedFilePath returns a file path corresponding to a <device_identifier>:<path> user input format. 62 * <device_identifier> may be a Linux block device identifier like sda or a FS UUID. 63 * 64 * NOTE: Caller's responsbility to unmount this..use return var mountPath to unmount in caller. 65 */ 66 func GetMountedFilePath(inputVal string, flags uintptr) (string, string, error) { 67 s := strings.Split(inputVal, ":") 68 if len(s) != 2 { 69 return "", "", fmt.Errorf("%s: Usage: <block device identifier>:<path>", inputVal) 70 } 71 72 // s[0] can be sda or UUID. if UUID, then we need to find its name 73 deviceId := s[0] 74 if !strings.HasPrefix(deviceId, "sd") { 75 if e := getBlkInfo(); e != nil { 76 return "", "", fmt.Errorf("getBlkInfo err=%s", e) 77 } 78 devices := storage.PartitionsByFsUUID(storageBlkDevices, s[0]) // []BlockDev 79 for _, device := range devices { 80 Debug("device =%s with fsuuid=%s", device.Name, s[0]) 81 deviceId = device.Name 82 } 83 } 84 85 devicePath := filepath.Join("/dev", deviceId) // assumes deviceId is sda, devicePath=/dev/sda 86 Debug("Attempting to mount %s", devicePath) 87 dev, err := diskboot.FindDevice(devicePath, flags) // FindDevice fn mounts devicePath=/dev/sda. 88 if err != nil { 89 return "", "", fmt.Errorf("failed to mount %v , flags=%v, err=%v", devicePath, flags, err) 90 } 91 92 Debug("Mounted %s", devicePath) 93 fPath := filepath.Join(dev.MountPoint.Path, s[1]) // mountPath=/tmp/path/to/target/file if /dev/sda mounted on /tmp 94 return fPath, dev.MountPoint.Path, nil 95 } 96 97 /* 98 * getBlkInfo calls storage package to get information on all block devices. 99 * The information is stored in a global variable 'storageBlkDevices' 100 * If the global variable is already non-zero, we skip the call to storage package. 101 * 102 * In debug mode, it also prints names and UUIDs for all devices. 103 */ 104 func getBlkInfo() error { 105 if len(storageBlkDevices) == 0 { 106 var err error 107 storageBlkDevices, err = storage.GetBlockStats() 108 if err != nil { 109 log.Printf("getBlkInfo: storage.GetBlockStats err=%v. Exiting", err) 110 return err 111 } 112 } 113 114 for k, d := range storageBlkDevices { 115 Debug("block device #%d, Name=%s, FsUUID=%s", k, d.Name, d.FsUUID) 116 } 117 return nil 118 }