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 43static 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 49static 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 58static 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 72static 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 81static 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 92void FsManagerAvbOps::InitializeAvbOps() { 93 // We only need to provide the implementation of read_from_partition() 94 // operation since that's all what is being used by the avb_slot_verify(). 95 // Other I/O operations are only required in bootloader but not in 96 // user-space so we set them as dummy operations. 97 avb_ops_.read_from_partition = read_from_partition; 98 avb_ops_.read_rollback_index = dummy_read_rollback_index; 99 avb_ops_.validate_vbmeta_public_key = dummy_validate_vbmeta_public_key; 100 avb_ops_.read_is_device_unlocked = dummy_read_is_device_unlocked; 101 avb_ops_.get_unique_guid_for_partition = dummy_get_unique_guid_for_partition; 102 103 // Sets user_data for GetInstanceFromAvbOps() to convert it back to FsManagerAvbOps. 104 avb_ops_.user_data = this; 105} 106 107FsManagerAvbOps::FsManagerAvbOps(std::map<std::string, std::string>&& by_name_symlink_map) 108 : by_name_symlink_map_(std::move(by_name_symlink_map)) { 109 InitializeAvbOps(); 110} 111 112FsManagerAvbOps::FsManagerAvbOps(const fstab& fstab) { 113 // Constructs the by-name symlink map for each fstab record. 114 // /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a => 115 // by_name_symlink_map_["system_a"] = "/dev/block/platform/soc.0/7824900.sdhci/by-name/system_a" 116 for (int i = 0; i < fstab.num_entries; i++) { 117 std::string partition_name = basename(fstab.recs[i].blk_device); 118 by_name_symlink_map_[partition_name] = fstab.recs[i].blk_device; 119 } 120 InitializeAvbOps(); 121} 122 123AvbIOResult FsManagerAvbOps::ReadFromPartition(const char* partition, int64_t offset, 124 size_t num_bytes, void* buffer, 125 size_t* out_num_read) { 126 const auto iter = by_name_symlink_map_.find(partition); 127 if (iter == by_name_symlink_map_.end()) { 128 LERROR << "by-name symlink not found for partition: '" << partition << "'"; 129 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 130 } 131 std::string path = iter->second; 132 133 // Ensures the device path (a symlink created by init) is ready to 134 // access. fs_mgr_test_access() will test a few iterations if the 135 // path doesn't exist yet. 136 if (fs_mgr_test_access(path.c_str()) < 0) { 137 return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; 138 } 139 140 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC))); 141 if (fd < 0) { 142 PERROR << "Failed to open " << path; 143 return AVB_IO_RESULT_ERROR_IO; 144 } 145 146 // If offset is negative, interprets its absolute value as the 147 // number of bytes from the end of the partition. 148 if (offset < 0) { 149 off64_t total_size = lseek64(fd, 0, SEEK_END); 150 if (total_size == -1) { 151 LERROR << "Failed to lseek64 to end of the partition"; 152 return AVB_IO_RESULT_ERROR_IO; 153 } 154 offset = total_size + offset; 155 // Repositions the offset to the beginning. 156 if (lseek64(fd, 0, SEEK_SET) == -1) { 157 LERROR << "Failed to lseek64 to the beginning of the partition"; 158 return AVB_IO_RESULT_ERROR_IO; 159 } 160 } 161 162 // On Linux, we never get partial reads from block devices (except 163 // for EOF). 164 ssize_t num_read = TEMP_FAILURE_RETRY(pread64(fd, buffer, num_bytes, offset)); 165 if (num_read < 0 || (size_t)num_read != num_bytes) { 166 PERROR << "Failed to read " << num_bytes << " bytes from " << path << " offset " << offset; 167 return AVB_IO_RESULT_ERROR_IO; 168 } 169 170 if (out_num_read != nullptr) { 171 *out_num_read = num_read; 172 } 173 174 return AVB_IO_RESULT_OK; 175} 176 177AvbSlotVerifyResult FsManagerAvbOps::AvbSlotVerify(const std::string& ab_suffix, 178 bool allow_verification_error, 179 AvbSlotVerifyData** out_data) { 180 // Invokes avb_slot_verify() to load and verify all vbmeta images. 181 // Sets requested_partitions to nullptr as it's to copy the contents 182 // of HASH partitions into handle>avb_slot_data_, which is not required as 183 // fs_mgr only deals with HASHTREE partitions. 184 const char* requested_partitions[] = {nullptr}; 185 return avb_slot_verify(&avb_ops_, requested_partitions, ab_suffix.c_str(), 186 allow_verification_error, out_data); 187} 188