1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "init_first_stage.h"
18
19 #include <stdlib.h>
20 #include <unistd.h>
21
22 #include <memory>
23 #include <set>
24 #include <string>
25 #include <vector>
26
27 #include <android-base/file.h>
28 #include <android-base/logging.h>
29 #include <android-base/strings.h>
30
31 #include "devices.h"
32 #include "fs_mgr.h"
33 #include "fs_mgr_avb.h"
34 #include "util.h"
35
36 // Class Declarations
37 // ------------------
38 class FirstStageMount {
39 public:
40 FirstStageMount();
41 virtual ~FirstStageMount() = default;
42
43 // The factory method to create either FirstStageMountVBootV1 or FirstStageMountVBootV2
44 // based on device tree configurations.
45 static std::unique_ptr<FirstStageMount> Create();
46 bool DoFirstStageMount(); // Mounts fstab entries read from device tree.
47 bool InitDevices();
48
49 protected:
50 void InitRequiredDevices();
51 void InitVerityDevice(const std::string& verity_device);
52 bool MountPartitions();
53
54 virtual coldboot_action_t ColdbootCallback(uevent* uevent);
55
56 // Pure virtual functions.
57 virtual bool GetRequiredDevices() = 0;
58 virtual bool SetUpDmVerity(fstab_rec* fstab_rec) = 0;
59
60 bool need_dm_verity_;
61 // Device tree fstab entries.
62 std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> device_tree_fstab_;
63 // Eligible first stage mount candidates, only allow /system, /vendor and/or /odm.
64 std::vector<fstab_rec*> mount_fstab_recs_;
65 std::set<std::string> required_devices_partition_names_;
66 };
67
68 class FirstStageMountVBootV1 : public FirstStageMount {
69 public:
70 FirstStageMountVBootV1() = default;
71 ~FirstStageMountVBootV1() override = default;
72
73 protected:
74 bool GetRequiredDevices() override;
75 bool SetUpDmVerity(fstab_rec* fstab_rec) override;
76 };
77
78 class FirstStageMountVBootV2 : public FirstStageMount {
79 public:
80 friend void SetInitAvbVersionInRecovery();
81
82 FirstStageMountVBootV2();
83 ~FirstStageMountVBootV2() override = default;
84
85 protected:
86 coldboot_action_t ColdbootCallback(uevent* uevent) override;
87 bool GetRequiredDevices() override;
88 bool SetUpDmVerity(fstab_rec* fstab_rec) override;
89 bool InitAvbHandle();
90
91 std::string device_tree_vbmeta_parts_;
92 FsManagerAvbUniquePtr avb_handle_;
93 ByNameSymlinkMap by_name_symlink_map_;
94 };
95
96 // Static Functions
97 // ----------------
IsDtVbmetaCompatible()98 static inline bool IsDtVbmetaCompatible() {
99 return is_android_dt_value_expected("vbmeta/compatible", "android,vbmeta");
100 }
101
IsRecoveryMode()102 static bool inline IsRecoveryMode() {
103 return access("/sbin/recovery", F_OK) == 0;
104 }
105
106 // Class Definitions
107 // -----------------
FirstStageMount()108 FirstStageMount::FirstStageMount()
109 : need_dm_verity_(false), device_tree_fstab_(fs_mgr_read_fstab_dt(), fs_mgr_free_fstab) {
110 if (!device_tree_fstab_) {
111 LOG(ERROR) << "Failed to read fstab from device tree";
112 return;
113 }
114 for (auto mount_point : {"/system", "/vendor", "/odm"}) {
115 fstab_rec* fstab_rec =
116 fs_mgr_get_entry_for_mount_point(device_tree_fstab_.get(), mount_point);
117 if (fstab_rec != nullptr) {
118 mount_fstab_recs_.push_back(fstab_rec);
119 }
120 }
121 }
122
Create()123 std::unique_ptr<FirstStageMount> FirstStageMount::Create() {
124 if (IsDtVbmetaCompatible()) {
125 return std::make_unique<FirstStageMountVBootV2>();
126 } else {
127 return std::make_unique<FirstStageMountVBootV1>();
128 }
129 }
130
DoFirstStageMount()131 bool FirstStageMount::DoFirstStageMount() {
132 // Nothing to mount.
133 if (mount_fstab_recs_.empty()) return true;
134
135 if (!InitDevices()) return false;
136
137 if (!MountPartitions()) return false;
138
139 return true;
140 }
141
InitDevices()142 bool FirstStageMount::InitDevices() {
143 if (!GetRequiredDevices()) return false;
144
145 InitRequiredDevices();
146
147 // InitRequiredDevices() will remove found partitions from required_devices_partition_names_.
148 // So if it isn't empty here, it means some partitions are not found.
149 if (!required_devices_partition_names_.empty()) {
150 LOG(ERROR) << __FUNCTION__ << "(): partition(s) not found: "
151 << android::base::Join(required_devices_partition_names_, ", ");
152 return false;
153 } else {
154 return true;
155 }
156 }
157
158 // Creates devices with uevent->partition_name matching one in the member variable
159 // required_devices_partition_names_. Found partitions will then be removed from it
160 // for the subsequent member function to check which devices are NOT created.
InitRequiredDevices()161 void FirstStageMount::InitRequiredDevices() {
162 if (required_devices_partition_names_.empty()) {
163 return;
164 }
165
166 if (need_dm_verity_) {
167 const std::string dm_path = "/devices/virtual/misc/device-mapper";
168 device_init(("/sys" + dm_path).c_str(), [&dm_path](uevent* uevent) -> coldboot_action_t {
169 if (uevent->path && uevent->path == dm_path) return COLDBOOT_STOP;
170 return COLDBOOT_CONTINUE; // dm_path not found, continue to find it.
171 });
172 }
173
174 device_init(nullptr,
175 [this](uevent* uevent) -> coldboot_action_t { return ColdbootCallback(uevent); });
176
177 device_close();
178 }
179
ColdbootCallback(uevent * uevent)180 coldboot_action_t FirstStageMount::ColdbootCallback(uevent* uevent) {
181 // We need platform devices to create symlinks.
182 if (!strncmp(uevent->subsystem, "platform", 8)) {
183 return COLDBOOT_CREATE;
184 }
185
186 // Ignores everything that is not a block device.
187 if (strncmp(uevent->subsystem, "block", 5)) {
188 return COLDBOOT_CONTINUE;
189 }
190
191 if (uevent->partition_name) {
192 // Matches partition name to create device nodes.
193 // Both required_devices_partition_names_ and uevent->partition_name have A/B
194 // suffix when A/B is used.
195 auto iter = required_devices_partition_names_.find(uevent->partition_name);
196 if (iter != required_devices_partition_names_.end()) {
197 LOG(VERBOSE) << __FUNCTION__ << "(): found partition: " << *iter;
198 required_devices_partition_names_.erase(iter);
199 if (required_devices_partition_names_.empty()) {
200 return COLDBOOT_STOP; // Found all partitions, stop coldboot.
201 } else {
202 return COLDBOOT_CREATE; // Creates this device and continue to find others.
203 }
204 }
205 }
206 // Not found a partition or find an unneeded partition, continue to find others.
207 return COLDBOOT_CONTINUE;
208 }
209
210 // Creates "/dev/block/dm-XX" for dm-verity by running coldboot on /sys/block/dm-XX.
InitVerityDevice(const std::string & verity_device)211 void FirstStageMount::InitVerityDevice(const std::string& verity_device) {
212 const std::string device_name(basename(verity_device.c_str()));
213 const std::string syspath = "/sys/block/" + device_name;
214
215 device_init(syspath.c_str(), [&](uevent* uevent) -> coldboot_action_t {
216 if (uevent->device_name && uevent->device_name == device_name) {
217 LOG(VERBOSE) << "Creating dm-verity device : " << verity_device;
218 return COLDBOOT_STOP;
219 }
220 return COLDBOOT_CONTINUE;
221 });
222 device_close();
223 }
224
MountPartitions()225 bool FirstStageMount::MountPartitions() {
226 for (auto fstab_rec : mount_fstab_recs_) {
227 if (!SetUpDmVerity(fstab_rec)) {
228 PLOG(ERROR) << "Failed to setup verity for '" << fstab_rec->mount_point << "'";
229 return false;
230 }
231 if (fs_mgr_do_mount_one(fstab_rec)) {
232 PLOG(ERROR) << "Failed to mount '" << fstab_rec->mount_point << "'";
233 return false;
234 }
235 }
236 return true;
237 }
238
GetRequiredDevices()239 bool FirstStageMountVBootV1::GetRequiredDevices() {
240 std::string verity_loc_device;
241 need_dm_verity_ = false;
242
243 for (auto fstab_rec : mount_fstab_recs_) {
244 // Don't allow verifyatboot in the first stage.
245 if (fs_mgr_is_verifyatboot(fstab_rec)) {
246 LOG(ERROR) << "Partitions can't be verified at boot";
247 return false;
248 }
249 // Checks for verified partitions.
250 if (fs_mgr_is_verified(fstab_rec)) {
251 need_dm_verity_ = true;
252 }
253 // Checks if verity metadata is on a separate partition. Note that it is
254 // not partition specific, so there must be only one additional partition
255 // that carries verity state.
256 if (fstab_rec->verity_loc) {
257 if (verity_loc_device.empty()) {
258 verity_loc_device = fstab_rec->verity_loc;
259 } else if (verity_loc_device != fstab_rec->verity_loc) {
260 LOG(ERROR) << "More than one verity_loc found: " << verity_loc_device << ", "
261 << fstab_rec->verity_loc;
262 return false;
263 }
264 }
265 }
266
267 // Includes the partition names of fstab records and verity_loc_device (if any).
268 // Notes that fstab_rec->blk_device has A/B suffix updated by fs_mgr when A/B is used.
269 for (auto fstab_rec : mount_fstab_recs_) {
270 required_devices_partition_names_.emplace(basename(fstab_rec->blk_device));
271 }
272
273 if (!verity_loc_device.empty()) {
274 required_devices_partition_names_.emplace(basename(verity_loc_device.c_str()));
275 }
276
277 return true;
278 }
279
SetUpDmVerity(fstab_rec * fstab_rec)280 bool FirstStageMountVBootV1::SetUpDmVerity(fstab_rec* fstab_rec) {
281 if (fs_mgr_is_verified(fstab_rec)) {
282 int ret = fs_mgr_setup_verity(fstab_rec, false /* wait_for_verity_dev */);
283 if (ret == FS_MGR_SETUP_VERITY_DISABLED) {
284 LOG(INFO) << "Verity disabled for '" << fstab_rec->mount_point << "'";
285 } else if (ret == FS_MGR_SETUP_VERITY_SUCCESS) {
286 // The exact block device name (fstab_rec->blk_device) is changed to "/dev/block/dm-XX".
287 // Needs to create it because ueventd isn't started in init first stage.
288 InitVerityDevice(fstab_rec->blk_device);
289 } else {
290 return false;
291 }
292 }
293 return true; // Returns true to mount the partition.
294 }
295
296 // FirstStageMountVBootV2 constructor.
297 // Gets the vbmeta partitions from device tree.
298 // /{
299 // firmware {
300 // android {
301 // vbmeta {
302 // compatible = "android,vbmeta";
303 // parts = "vbmeta,boot,system,vendor"
304 // };
305 // };
306 // };
307 // }
FirstStageMountVBootV2()308 FirstStageMountVBootV2::FirstStageMountVBootV2() : avb_handle_(nullptr) {
309 if (!read_android_dt_file("vbmeta/parts", &device_tree_vbmeta_parts_)) {
310 PLOG(ERROR) << "Failed to read vbmeta/parts from device tree";
311 return;
312 }
313 }
314
GetRequiredDevices()315 bool FirstStageMountVBootV2::GetRequiredDevices() {
316 need_dm_verity_ = false;
317
318 // fstab_rec->blk_device has A/B suffix.
319 for (auto fstab_rec : mount_fstab_recs_) {
320 if (fs_mgr_is_avb(fstab_rec)) {
321 need_dm_verity_ = true;
322 }
323 required_devices_partition_names_.emplace(basename(fstab_rec->blk_device));
324 }
325
326 // libavb verifies AVB metadata on all verified partitions at once.
327 // e.g., The device_tree_vbmeta_parts_ will be "vbmeta,boot,system,vendor"
328 // for libavb to verify metadata, even if there is only /vendor in the
329 // above mount_fstab_recs_.
330 if (need_dm_verity_) {
331 if (device_tree_vbmeta_parts_.empty()) {
332 LOG(ERROR) << "Missing vbmeta parts in device tree";
333 return false;
334 }
335 std::vector<std::string> partitions = android::base::Split(device_tree_vbmeta_parts_, ",");
336 std::string ab_suffix = fs_mgr_get_slot_suffix();
337 for (const auto& partition : partitions) {
338 // required_devices_partition_names_ is of type std::set so it's not an issue
339 // to emplace a partition twice. e.g., /vendor might be in both places:
340 // - device_tree_vbmeta_parts_ = "vbmeta,boot,system,vendor"
341 // - mount_fstab_recs_: /vendor_a
342 required_devices_partition_names_.emplace(partition + ab_suffix);
343 }
344 }
345 return true;
346 }
347
ColdbootCallback(uevent * uevent)348 coldboot_action_t FirstStageMountVBootV2::ColdbootCallback(uevent* uevent) {
349 // Invokes the parent function to see if any desired partition has been found.
350 // If yes, record the by-name symlink for creating FsManagerAvbHandle later.
351 coldboot_action_t parent_callback_ret = FirstStageMount::ColdbootCallback(uevent);
352
353 // Skips the uevent if the parent function returns COLDBOOT_CONTINUE (meaning
354 // that the uevent was skipped) or there is no uevent->partition_name to
355 // create the by-name symlink.
356 if (parent_callback_ret != COLDBOOT_CONTINUE && uevent->partition_name) {
357 // get_block_device_symlinks() will return three symlinks at most, depending on
358 // the content of uevent. by-name symlink will be at [0] if uevent->partition_name
359 // is not empty. e.g.,
360 // - /dev/block/platform/soc.0/f9824900.sdhci/by-name/modem
361 // - /dev/block/platform/soc.0/f9824900.sdhci/by-num/p1
362 // - /dev/block/platform/soc.0/f9824900.sdhci/mmcblk0p1
363 char** links = get_block_device_symlinks(uevent);
364 if (links && links[0]) {
365 auto[it, inserted] = by_name_symlink_map_.emplace(uevent->partition_name, links[0]);
366 if (!inserted) {
367 LOG(ERROR) << "Partition '" << uevent->partition_name
368 << "' already existed in the by-name symlink map with a value of '"
369 << it->second << "', new value '" << links[0] << "' will be ignored.";
370 }
371 }
372 }
373
374 return parent_callback_ret;
375 }
376
SetUpDmVerity(fstab_rec * fstab_rec)377 bool FirstStageMountVBootV2::SetUpDmVerity(fstab_rec* fstab_rec) {
378 if (fs_mgr_is_avb(fstab_rec)) {
379 if (!InitAvbHandle()) return false;
380 if (avb_handle_->hashtree_disabled()) {
381 LOG(INFO) << "avb hashtree disabled for '" << fstab_rec->mount_point << "'";
382 } else if (avb_handle_->SetUpAvb(fstab_rec, false /* wait_for_verity_dev */)) {
383 // The exact block device name (fstab_rec->blk_device) is changed to "/dev/block/dm-XX".
384 // Needs to create it because ueventd isn't started in init first stage.
385 InitVerityDevice(fstab_rec->blk_device);
386 } else {
387 return false;
388 }
389 }
390 return true; // Returns true to mount the partition.
391 }
392
InitAvbHandle()393 bool FirstStageMountVBootV2::InitAvbHandle() {
394 if (avb_handle_) return true; // Returns true if the handle is already initialized.
395
396 if (by_name_symlink_map_.empty()) {
397 LOG(ERROR) << "by_name_symlink_map_ is empty";
398 return false;
399 }
400
401 avb_handle_ = FsManagerAvbHandle::Open(std::move(by_name_symlink_map_));
402 by_name_symlink_map_.clear(); // Removes all elements after the above std::move().
403
404 if (!avb_handle_) {
405 PLOG(ERROR) << "Failed to open FsManagerAvbHandle";
406 return false;
407 }
408 // Sets INIT_AVB_VERSION here for init to set ro.boot.avb_version in the second stage.
409 setenv("INIT_AVB_VERSION", avb_handle_->avb_version().c_str(), 1);
410 return true;
411 }
412
413 // Public functions
414 // ----------------
415 // Mounts /system, /vendor, and/or /odm if they are present in the fstab provided by device tree.
DoFirstStageMount()416 bool DoFirstStageMount() {
417 // Skips first stage mount if we're in recovery mode.
418 if (IsRecoveryMode()) {
419 LOG(INFO) << "First stage mount skipped (recovery mode)";
420 return true;
421 }
422
423 // Firstly checks if device tree fstab entries are compatible.
424 if (!is_android_dt_value_expected("fstab/compatible", "android,fstab")) {
425 LOG(INFO) << "First stage mount skipped (missing/incompatible fstab in device tree)";
426 return true;
427 }
428
429 std::unique_ptr<FirstStageMount> handle = FirstStageMount::Create();
430 if (!handle) {
431 LOG(ERROR) << "Failed to create FirstStageMount";
432 return false;
433 }
434 return handle->DoFirstStageMount();
435 }
436
SetInitAvbVersionInRecovery()437 void SetInitAvbVersionInRecovery() {
438 if (!IsRecoveryMode()) {
439 LOG(INFO) << "Skipped setting INIT_AVB_VERSION (not in recovery mode)";
440 return;
441 }
442
443 if (!IsDtVbmetaCompatible()) {
444 LOG(INFO) << "Skipped setting INIT_AVB_VERSION (not vbmeta compatible)";
445 return;
446 }
447
448 // Initializes required devices for the subsequent FsManagerAvbHandle::Open()
449 // to verify AVB metadata on all partitions in the verified chain.
450 // We only set INIT_AVB_VERSION when the AVB verification succeeds, i.e., the
451 // Open() function returns a valid handle.
452 // We don't need to mount partitions here in recovery mode.
453 FirstStageMountVBootV2 avb_first_mount;
454 if (!avb_first_mount.InitDevices()) {
455 LOG(ERROR) << "Failed to init devices for INIT_AVB_VERSION";
456 return;
457 }
458
459 FsManagerAvbUniquePtr avb_handle =
460 FsManagerAvbHandle::Open(std::move(avb_first_mount.by_name_symlink_map_));
461 if (!avb_handle) {
462 PLOG(ERROR) << "Failed to open FsManagerAvbHandle for INIT_AVB_VERSION";
463 return;
464 }
465 setenv("INIT_AVB_VERSION", avb_handle->avb_version().c_str(), 1);
466 }
467