Home | History | Annotate | Download | only in fs_mgr
      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