blob: 43879fe5604a7efc9c50aae26f6d60c3cf926a26 [file] [log] [blame]
bowgotsaib51722b2017-01-11 22:21:38 +08001/*
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
Bowgo Tsai20651f62017-05-08 20:45:50 +080025#include "fs_mgr_priv_avb_ops.h"
26
bowgotsaib51722b2017-01-11 22:21:38 +080027#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"
bowgotsaib51722b2017-01-11 22:21:38 +080041#include "fs_mgr_priv.h"
42
Bowgo Tsai95c966a2017-03-30 18:42:54 +080043static 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);
bowgotsaib51722b2017-01-11 22:21:38 +080047}
48
Bowgo Tsai4caf4c02017-02-16 21:35:09 +080049static AvbIOResult dummy_read_rollback_index(AvbOps* ops ATTRIBUTE_UNUSED,
50 size_t rollback_index_location ATTRIBUTE_UNUSED,
51 uint64_t* out_rollback_index) {
bowgotsaib51722b2017-01-11 22:21:38 +080052 // 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(
Bowgo Tsai4caf4c02017-02-16 21:35:09 +080059 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) {
bowgotsaib51722b2017-01-11 22:21:38 +080062 // 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().
bowgotsaib51722b2017-01-11 22:21:38 +080068 *out_is_trusted = true;
69 return AVB_IO_RESULT_OK;
70}
71
Bowgo Tsai4caf4c02017-02-16 21:35:09 +080072static AvbIOResult dummy_read_is_device_unlocked(AvbOps* ops ATTRIBUTE_UNUSED,
73 bool* out_is_unlocked) {
bowgotsaib51722b2017-01-11 22:21:38 +080074 // 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
Bowgo Tsai4caf4c02017-02-16 21:35:09 +080081static 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) {
bowgotsaib51722b2017-01-11 22:21:38 +080084 // 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
Bowgo Tsai60f19a02017-06-22 22:23:08 +080092static 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
Bowgo Tsai20651f62017-05-08 20:45:50 +0800101void FsManagerAvbOps::InitializeAvbOps() {
Bowgo Tsai95c966a2017-03-30 18:42:54 +0800102 // 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
David Zeuthen16c6fd12017-05-01 12:43:34 -0400105 // 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));
Bowgo Tsai95c966a2017-03-30 18:42:54 +0800108 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;
Bowgo Tsai60f19a02017-06-22 22:23:08 +0800113 avb_ops_.get_size_of_partition = dummy_get_size_of_partition;
bowgotsaib51722b2017-01-11 22:21:38 +0800114
Bowgo Tsai95c966a2017-03-30 18:42:54 +0800115 // Sets user_data for GetInstanceFromAvbOps() to convert it back to FsManagerAvbOps.
116 avb_ops_.user_data = this;
bowgotsaib51722b2017-01-11 22:21:38 +0800117}
118
Bowgo Tsai20651f62017-05-08 20:45:50 +0800119FsManagerAvbOps::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
124FsManagerAvbOps::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
Bowgo Tsai95c966a2017-03-30 18:42:54 +0800135AvbIOResult FsManagerAvbOps::ReadFromPartition(const char* partition, int64_t offset,
136 size_t num_bytes, void* buffer,
137 size_t* out_num_read) {
Bowgo Tsai20651f62017-05-08 20:45:50 +0800138 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;
Bowgo Tsai95c966a2017-03-30 18:42:54 +0800144
Jinguang Dong9d344962017-06-13 10:20:34 +0800145 // Ensures the device path (a symlink created by init) is ready to access.
146 if (!fs_mgr_wait_for_file(path, 1s)) {
Bowgo Tsai95c966a2017-03-30 18:42:54 +0800147 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) {
Bowgo Tsai20651f62017-05-08 20:45:50 +0800152 PERROR << "Failed to open " << path;
Bowgo Tsai95c966a2017-03-30 18:42:54 +0800153 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) {
Bowgo Tsai359bed32017-04-27 15:44:39 +0800161 PERROR << "Failed to lseek64 to end of the partition";
Bowgo Tsai95c966a2017-03-30 18:42:54 +0800162 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) {
Bowgo Tsai359bed32017-04-27 15:44:39 +0800167 PERROR << "Failed to lseek64 to the beginning of the partition";
Bowgo Tsai95c966a2017-03-30 18:42:54 +0800168 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) {
Bowgo Tsai20651f62017-05-08 20:45:50 +0800176 PERROR << "Failed to read " << num_bytes << " bytes from " << path << " offset " << offset;
Bowgo Tsai95c966a2017-03-30 18:42:54 +0800177 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
187AvbSlotVerifyResult FsManagerAvbOps::AvbSlotVerify(const std::string& ab_suffix,
David Zeuthen7ea2c282017-05-10 15:43:37 -0400188 AvbSlotVerifyFlags flags,
Bowgo Tsai95c966a2017-03-30 18:42:54 +0800189 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};
David Zeuthen7ea2c282017-05-10 15:43:37 -0400195 // 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);
Bowgo Tsai95c966a2017-03-30 18:42:54 +0800199}