1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Permission is hereby granted, free of charge, to any person 5 * obtaining a copy of this software and associated documentation 6 * files (the "Software"), to deal in the Software without 7 * restriction, including without limitation the rights to use, copy, 8 * modify, merge, publish, distribute, sublicense, and/or sell copies 9 * of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 25 #include "fs_mgr_priv_avb_ops.h" 26 27 #include <errno.h> 28 #include <fcntl.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <sys/stat.h> 32 #include <string> 33 34 #include <android-base/macros.h> 35 #include <android-base/strings.h> 36 #include <android-base/unique_fd.h> 37 #include <libavb/libavb.h> 38 #include <utils/Compat.h> 39 40 #include "fs_mgr.h" 41 #include "fs_mgr_priv.h" 42 43 static AvbIOResult read_from_partition(AvbOps* ops, const char* partition, int64_t offset, 44 size_t num_bytes, void* buffer, size_t* out_num_read) { 45 return FsManagerAvbOps::GetInstanceFromAvbOps(ops)->ReadFromPartition( 46 partition, offset, num_bytes, buffer, out_num_read); 47 } 48 49 static AvbIOResult dummy_read_rollback_index(AvbOps* ops ATTRIBUTE_UNUSED, 50 size_t rollback_index_location ATTRIBUTE_UNUSED, 51 uint64_t* out_rollback_index) { 52 // rollback_index has been checked in bootloader phase. 53 // In user-space, returns the smallest value 0 to pass the check. 54 *out_rollback_index = 0; 55 return AVB_IO_RESULT_OK; 56 } 57 58 static AvbIOResult dummy_validate_vbmeta_public_key( 59 AvbOps* ops ATTRIBUTE_UNUSED, const uint8_t* public_key_data ATTRIBUTE_UNUSED, 60 size_t public_key_length ATTRIBUTE_UNUSED, const uint8_t* public_key_metadata ATTRIBUTE_UNUSED, 61 size_t public_key_metadata_length ATTRIBUTE_UNUSED, bool* out_is_trusted) { 62 // vbmeta public key has been checked in bootloader phase. 63 // In user-space, returns true to pass the check. 64 // 65 // Addtionally, user-space should check 66 // androidboot.vbmeta.{hash_alg, size, digest} against the digest 67 // of all vbmeta images after invoking avb_slot_verify(). 68 *out_is_trusted = true; 69 return AVB_IO_RESULT_OK; 70 } 71 72 static AvbIOResult dummy_read_is_device_unlocked(AvbOps* ops ATTRIBUTE_UNUSED, 73 bool* out_is_unlocked) { 74 // The function is for bootloader to update the value into 75 // androidboot.vbmeta.device_state in kernel cmdline. 76 // In user-space, returns true as we don't need to update it anymore. 77 *out_is_unlocked = true; 78 return AVB_IO_RESULT_OK; 79 } 80 81 static AvbIOResult dummy_get_unique_guid_for_partition(AvbOps* ops ATTRIBUTE_UNUSED, 82 const char* partition ATTRIBUTE_UNUSED, 83 char* guid_buf, size_t guid_buf_size) { 84 // The function is for bootloader to set the correct UUID 85 // for a given partition in kernel cmdline. 86 // In user-space, returns a faking one as we don't need to update 87 // it anymore. 88 snprintf(guid_buf, guid_buf_size, "1234-fake-guid-for:%s", partition); 89 return AVB_IO_RESULT_OK; 90 } 91 92 static AvbIOResult dummy_get_size_of_partition(AvbOps* ops ATTRIBUTE_UNUSED, 93 const char* partition ATTRIBUTE_UNUSED, 94 uint64_t* out_size_num_byte) { 95 // The function is for bootloader to load entire content of AVB HASH partitions. 96 // In user-space, returns 0 as we only need to set up AVB HASHTHREE partitions. 97 *out_size_num_byte = 0; 98 return AVB_IO_RESULT_OK; 99 } 100 101 void FsManagerAvbOps::InitializeAvbOps() { 102 // We only need to provide the implementation of read_from_partition() 103 // operation since that's all what is being used by the avb_slot_verify(). 104 // Other I/O operations are only required in bootloader but not in 105 // user-space so we set them as dummy operations. Also zero the entire 106 // struct so operations added in the future will be set to NULL. 107 memset(&avb_ops_, 0, sizeof(AvbOps)); 108 avb_ops_.read_from_partition = read_from_partition; 109 avb_ops_.read_rollback_index = dummy_read_rollback_index; 110 avb_ops_.validate_vbmeta_public_key = dummy_validate_vbmeta_public_key; 111 avb_ops_.read_is_device_unlocked = dummy_read_is_device_unlocked; 112 avb_ops_.get_unique_guid_for_partition = dummy_get_unique_guid_for_partition; 113 avb_ops_.get_size_of_partition = dummy_get_size_of_partition; 114 115 // Sets user_data for GetInstanceFromAvbOps() to convert it back to FsManagerAvbOps. 116 avb_ops_.user_data = this; 117 } 118 119 FsManagerAvbOps::FsManagerAvbOps(std::map<std::string, std::string>&& by_name_symlink_map) 120 : by_name_symlink_map_(std::move(by_name_symlink_map)) { 121 InitializeAvbOps(); 122 } 123 124 FsManagerAvbOps::FsManagerAvbOps(const fstab& fstab) { 125 // Constructs the by-name symlink map for each fstab record. 126 // /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a => 127 // by_name_symlink_map_["system_a"] = "/dev/block/platform/soc.0/7824900.sdhci/by-name/system_a" 128 for (int i = 0; i < fstab.num_entries; i++) { 129 std::string partition_name = basename(fstab.recs[i].blk_device); 130 by_name_symlink_map_[partition_name] = fstab.recs[i].blk_device; 131 } 132 InitializeAvbOps(); 133 } 134 135 AvbIOResult FsManagerAvbOps::ReadFromPartition(const char* partition, int64_t offset, 136 size_t num_bytes, void* buffer, 137 size_t* out_num_read) { 138 const auto iter = by_name_symlink_map_.find(partition); 139 if (iter == by_name_symlink_map_.end()) { 140 LERROR << "by-name symlink not found for partition: '" << partition << "'"; 141 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 142 } 143 std::string path = iter->second; 144 145 // Ensures the device path (a symlink created by init) is ready to access. 146 if (!fs_mgr_wait_for_file(path, 1s)) { 147 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 148 } 149 150 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC))); 151 if (fd < 0) { 152 PERROR << "Failed to open " << path; 153 return AVB_IO_RESULT_ERROR_IO; 154 } 155 156 // If offset is negative, interprets its absolute value as the 157 // number of bytes from the end of the partition. 158 if (offset < 0) { 159 off64_t total_size = lseek64(fd, 0, SEEK_END); 160 if (total_size == -1) { 161 PERROR << "Failed to lseek64 to end of the partition"; 162 return AVB_IO_RESULT_ERROR_IO; 163 } 164 offset = total_size + offset; 165 // Repositions the offset to the beginning. 166 if (lseek64(fd, 0, SEEK_SET) == -1) { 167 PERROR << "Failed to lseek64 to the beginning of the partition"; 168 return AVB_IO_RESULT_ERROR_IO; 169 } 170 } 171 172 // On Linux, we never get partial reads from block devices (except 173 // for EOF). 174 ssize_t num_read = TEMP_FAILURE_RETRY(pread64(fd, buffer, num_bytes, offset)); 175 if (num_read < 0 || (size_t)num_read != num_bytes) { 176 PERROR << "Failed to read " << num_bytes << " bytes from " << path << " offset " << offset; 177 return AVB_IO_RESULT_ERROR_IO; 178 } 179 180 if (out_num_read != nullptr) { 181 *out_num_read = num_read; 182 } 183 184 return AVB_IO_RESULT_OK; 185 } 186 187 AvbSlotVerifyResult FsManagerAvbOps::AvbSlotVerify(const std::string& ab_suffix, 188 AvbSlotVerifyFlags flags, 189 AvbSlotVerifyData** out_data) { 190 // Invokes avb_slot_verify() to load and verify all vbmeta images. 191 // Sets requested_partitions to nullptr as it's to copy the contents 192 // of HASH partitions into handle>avb_slot_data_, which is not required as 193 // fs_mgr only deals with HASHTREE partitions. 194 const char* requested_partitions[] = {nullptr}; 195 // The |hashtree_error_mode| field doesn't matter as it only 196 // influences the generated kernel cmdline parameters. 197 return avb_slot_verify(&avb_ops_, requested_partitions, ab_suffix.c_str(), flags, 198 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, out_data); 199 } 200