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 <chrono> 23#include <memory> 24#include <set> 25#include <string> 26#include <vector> 27 28#include <android-base/chrono_utils.h> 29#include <android-base/file.h> 30#include <android-base/logging.h> 31#include <android-base/strings.h> 32 33#include "devices.h" 34#include "fs_mgr.h" 35#include "fs_mgr_avb.h" 36#include "uevent.h" 37#include "uevent_listener.h" 38#include "util.h" 39 40using android::base::Timer; 41 42namespace android { 43namespace init { 44 45// Class Declarations 46// ------------------ 47class FirstStageMount { 48 public: 49 FirstStageMount(); 50 virtual ~FirstStageMount() = default; 51 52 // The factory method to create either FirstStageMountVBootV1 or FirstStageMountVBootV2 53 // based on device tree configurations. 54 static std::unique_ptr<FirstStageMount> Create(); 55 bool DoFirstStageMount(); // Mounts fstab entries read from device tree. 56 bool InitDevices(); 57 58 protected: 59 bool InitRequiredDevices(); 60 bool InitVerityDevice(const std::string& verity_device); 61 bool MountPartitions(); 62 63 virtual ListenerAction UeventCallback(const Uevent& uevent); 64 65 // Pure virtual functions. 66 virtual bool GetRequiredDevices() = 0; 67 virtual bool SetUpDmVerity(fstab_rec* fstab_rec) = 0; 68 69 bool need_dm_verity_; 70 71 std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> device_tree_fstab_; 72 std::vector<fstab_rec*> mount_fstab_recs_; 73 std::set<std::string> required_devices_partition_names_; 74 DeviceHandler device_handler_; 75 UeventListener uevent_listener_; 76}; 77 78class FirstStageMountVBootV1 : public FirstStageMount { 79 public: 80 FirstStageMountVBootV1() = default; 81 ~FirstStageMountVBootV1() override = default; 82 83 protected: 84 bool GetRequiredDevices() override; 85 bool SetUpDmVerity(fstab_rec* fstab_rec) override; 86}; 87 88class FirstStageMountVBootV2 : public FirstStageMount { 89 public: 90 friend void SetInitAvbVersionInRecovery(); 91 92 FirstStageMountVBootV2(); 93 ~FirstStageMountVBootV2() override = default; 94 95 protected: 96 ListenerAction UeventCallback(const Uevent& uevent) override; 97 bool GetRequiredDevices() override; 98 bool SetUpDmVerity(fstab_rec* fstab_rec) override; 99 bool InitAvbHandle(); 100 101 std::string device_tree_vbmeta_parts_; 102 FsManagerAvbUniquePtr avb_handle_; 103 ByNameSymlinkMap by_name_symlink_map_; 104}; 105 106// Static Functions 107// ---------------- 108static inline bool IsDtVbmetaCompatible() { 109 return is_android_dt_value_expected("vbmeta/compatible", "android,vbmeta"); 110} 111 112static bool inline IsRecoveryMode() { 113 return access("/sbin/recovery", F_OK) == 0; 114} 115 116// Class Definitions 117// ----------------- 118FirstStageMount::FirstStageMount() 119 : need_dm_verity_(false), device_tree_fstab_(fs_mgr_read_fstab_dt(), fs_mgr_free_fstab) { 120 if (!device_tree_fstab_) { 121 LOG(ERROR) << "Failed to read fstab from device tree"; 122 return; 123 } 124 // Stores device_tree_fstab_->recs[] into mount_fstab_recs_ (vector<fstab_rec*>) 125 // for easier manipulation later, e.g., range-base for loop. 126 for (int i = 0; i < device_tree_fstab_->num_entries; i++) { 127 mount_fstab_recs_.push_back(&device_tree_fstab_->recs[i]); 128 } 129} 130 131std::unique_ptr<FirstStageMount> FirstStageMount::Create() { 132 if (IsDtVbmetaCompatible()) { 133 return std::make_unique<FirstStageMountVBootV2>(); 134 } else { 135 return std::make_unique<FirstStageMountVBootV1>(); 136 } 137} 138 139bool FirstStageMount::DoFirstStageMount() { 140 // Nothing to mount. 141 if (mount_fstab_recs_.empty()) return true; 142 143 if (!InitDevices()) return false; 144 145 if (!MountPartitions()) return false; 146 147 return true; 148} 149 150bool FirstStageMount::InitDevices() { 151 return GetRequiredDevices() && InitRequiredDevices(); 152} 153 154// Creates devices with uevent->partition_name matching one in the member variable 155// required_devices_partition_names_. Found partitions will then be removed from it 156// for the subsequent member function to check which devices are NOT created. 157bool FirstStageMount::InitRequiredDevices() { 158 if (required_devices_partition_names_.empty()) { 159 return true; 160 } 161 162 if (need_dm_verity_) { 163 const std::string dm_path = "/devices/virtual/misc/device-mapper"; 164 bool found = false; 165 auto dm_callback = [this, &dm_path, &found](const Uevent& uevent) { 166 if (uevent.path == dm_path) { 167 device_handler_.HandleDeviceEvent(uevent); 168 found = true; 169 return ListenerAction::kStop; 170 } 171 return ListenerAction::kContinue; 172 }; 173 uevent_listener_.RegenerateUeventsForPath("/sys" + dm_path, dm_callback); 174 if (!found) { 175 LOG(INFO) << "device-mapper device not found in /sys, waiting for its uevent"; 176 Timer t; 177 uevent_listener_.Poll(dm_callback, 10s); 178 LOG(INFO) << "Wait for device-mapper returned after " << t; 179 } 180 if (!found) { 181 LOG(ERROR) << "device-mapper device not found after polling timeout"; 182 return false; 183 } 184 } 185 186 auto uevent_callback = [this](const Uevent& uevent) { return UeventCallback(uevent); }; 187 uevent_listener_.RegenerateUevents(uevent_callback); 188 189 // UeventCallback() will remove found partitions from required_devices_partition_names_. 190 // So if it isn't empty here, it means some partitions are not found. 191 if (!required_devices_partition_names_.empty()) { 192 LOG(INFO) << __PRETTY_FUNCTION__ 193 << ": partition(s) not found in /sys, waiting for their uevent(s): " 194 << android::base::Join(required_devices_partition_names_, ", "); 195 Timer t; 196 uevent_listener_.Poll(uevent_callback, 10s); 197 LOG(INFO) << "Wait for partitions returned after " << t; 198 } 199 200 if (!required_devices_partition_names_.empty()) { 201 LOG(ERROR) << __PRETTY_FUNCTION__ << ": partition(s) not found after polling timeout: " 202 << android::base::Join(required_devices_partition_names_, ", "); 203 return false; 204 } 205 206 return true; 207} 208 209ListenerAction FirstStageMount::UeventCallback(const Uevent& uevent) { 210 // Ignores everything that is not a block device. 211 if (uevent.subsystem != "block") { 212 return ListenerAction::kContinue; 213 } 214 215 if (!uevent.partition_name.empty()) { 216 // Matches partition name to create device nodes. 217 // Both required_devices_partition_names_ and uevent->partition_name have A/B 218 // suffix when A/B is used. 219 auto iter = required_devices_partition_names_.find(uevent.partition_name); 220 if (iter != required_devices_partition_names_.end()) { 221 LOG(VERBOSE) << __PRETTY_FUNCTION__ << ": found partition: " << *iter; 222 required_devices_partition_names_.erase(iter); 223 device_handler_.HandleDeviceEvent(uevent); 224 if (required_devices_partition_names_.empty()) { 225 return ListenerAction::kStop; 226 } else { 227 return ListenerAction::kContinue; 228 } 229 } 230 } 231 // Not found a partition or find an unneeded partition, continue to find others. 232 return ListenerAction::kContinue; 233} 234 235// Creates "/dev/block/dm-XX" for dm-verity by running coldboot on /sys/block/dm-XX. 236bool FirstStageMount::InitVerityDevice(const std::string& verity_device) { 237 const std::string device_name(basename(verity_device.c_str())); 238 const std::string syspath = "/sys/block/" + device_name; 239 bool found = false; 240 241 auto verity_callback = [&device_name, &verity_device, this, &found](const Uevent& uevent) { 242 if (uevent.device_name == device_name) { 243 LOG(VERBOSE) << "Creating dm-verity device : " << verity_device; 244 device_handler_.HandleDeviceEvent(uevent); 245 found = true; 246 return ListenerAction::kStop; 247 } 248 return ListenerAction::kContinue; 249 }; 250 251 uevent_listener_.RegenerateUeventsForPath(syspath, verity_callback); 252 if (!found) { 253 LOG(INFO) << "dm-verity device not found in /sys, waiting for its uevent"; 254 Timer t; 255 uevent_listener_.Poll(verity_callback, 10s); 256 LOG(INFO) << "wait for dm-verity device returned after " << t; 257 } 258 if (!found) { 259 LOG(ERROR) << "dm-verity device not found after polling timeout"; 260 return false; 261 } 262 263 return true; 264} 265 266bool FirstStageMount::MountPartitions() { 267 for (auto fstab_rec : mount_fstab_recs_) { 268 if (!SetUpDmVerity(fstab_rec)) { 269 PLOG(ERROR) << "Failed to setup verity for '" << fstab_rec->mount_point << "'"; 270 return false; 271 } 272 if (fs_mgr_do_mount_one(fstab_rec)) { 273 PLOG(ERROR) << "Failed to mount '" << fstab_rec->mount_point << "'"; 274 return false; 275 } 276 } 277 return true; 278} 279 280bool FirstStageMountVBootV1::GetRequiredDevices() { 281 std::string verity_loc_device; 282 need_dm_verity_ = false; 283 284 for (auto fstab_rec : mount_fstab_recs_) { 285 // Don't allow verifyatboot in the first stage. 286 if (fs_mgr_is_verifyatboot(fstab_rec)) { 287 LOG(ERROR) << "Partitions can't be verified at boot"; 288 return false; 289 } 290 // Checks for verified partitions. 291 if (fs_mgr_is_verified(fstab_rec)) { 292 need_dm_verity_ = true; 293 } 294 // Checks if verity metadata is on a separate partition. Note that it is 295 // not partition specific, so there must be only one additional partition 296 // that carries verity state. 297 if (fstab_rec->verity_loc) { 298 if (verity_loc_device.empty()) { 299 verity_loc_device = fstab_rec->verity_loc; 300 } else if (verity_loc_device != fstab_rec->verity_loc) { 301 LOG(ERROR) << "More than one verity_loc found: " << verity_loc_device << ", " 302 << fstab_rec->verity_loc; 303 return false; 304 } 305 } 306 } 307 308 // Includes the partition names of fstab records and verity_loc_device (if any). 309 // Notes that fstab_rec->blk_device has A/B suffix updated by fs_mgr when A/B is used. 310 for (auto fstab_rec : mount_fstab_recs_) { 311 required_devices_partition_names_.emplace(basename(fstab_rec->blk_device)); 312 } 313 314 if (!verity_loc_device.empty()) { 315 required_devices_partition_names_.emplace(basename(verity_loc_device.c_str())); 316 } 317 318 return true; 319} 320 321bool FirstStageMountVBootV1::SetUpDmVerity(fstab_rec* fstab_rec) { 322 if (fs_mgr_is_verified(fstab_rec)) { 323 int ret = fs_mgr_setup_verity(fstab_rec, false /* wait_for_verity_dev */); 324 switch (ret) { 325 case FS_MGR_SETUP_VERITY_SKIPPED: 326 case FS_MGR_SETUP_VERITY_DISABLED: 327 LOG(INFO) << "Verity disabled/skipped for '" << fstab_rec->mount_point << "'"; 328 return true; 329 case FS_MGR_SETUP_VERITY_SUCCESS: 330 // The exact block device name (fstab_rec->blk_device) is changed to 331 // "/dev/block/dm-XX". Needs to create it because ueventd isn't started in init 332 // first stage. 333 return InitVerityDevice(fstab_rec->blk_device); 334 default: 335 return false; 336 } 337 } 338 return true; // Returns true to mount the partition. 339} 340 341// FirstStageMountVBootV2 constructor. 342// Gets the vbmeta partitions from device tree. 343// /{ 344// firmware { 345// android { 346// vbmeta { 347// compatible = "android,vbmeta"; 348// parts = "vbmeta,boot,system,vendor" 349// }; 350// }; 351// }; 352// } 353FirstStageMountVBootV2::FirstStageMountVBootV2() : avb_handle_(nullptr) { 354 if (!read_android_dt_file("vbmeta/parts", &device_tree_vbmeta_parts_)) { 355 PLOG(ERROR) << "Failed to read vbmeta/parts from device tree"; 356 return; 357 } 358} 359 360bool FirstStageMountVBootV2::GetRequiredDevices() { 361 need_dm_verity_ = false; 362 363 // fstab_rec->blk_device has A/B suffix. 364 for (auto fstab_rec : mount_fstab_recs_) { 365 if (fs_mgr_is_avb(fstab_rec)) { 366 need_dm_verity_ = true; 367 } 368 required_devices_partition_names_.emplace(basename(fstab_rec->blk_device)); 369 } 370 371 // libavb verifies AVB metadata on all verified partitions at once. 372 // e.g., The device_tree_vbmeta_parts_ will be "vbmeta,boot,system,vendor" 373 // for libavb to verify metadata, even if there is only /vendor in the 374 // above mount_fstab_recs_. 375 if (need_dm_verity_) { 376 if (device_tree_vbmeta_parts_.empty()) { 377 LOG(ERROR) << "Missing vbmeta parts in device tree"; 378 return false; 379 } 380 std::vector<std::string> partitions = android::base::Split(device_tree_vbmeta_parts_, ","); 381 std::string ab_suffix = fs_mgr_get_slot_suffix(); 382 for (const auto& partition : partitions) { 383 // required_devices_partition_names_ is of type std::set so it's not an issue 384 // to emplace a partition twice. e.g., /vendor might be in both places: 385 // - device_tree_vbmeta_parts_ = "vbmeta,boot,system,vendor" 386 // - mount_fstab_recs_: /vendor_a 387 required_devices_partition_names_.emplace(partition + ab_suffix); 388 } 389 } 390 return true; 391} 392 393ListenerAction FirstStageMountVBootV2::UeventCallback(const Uevent& uevent) { 394 // Check if this uevent corresponds to one of the required partitions and store its symlinks if 395 // so, in order to create FsManagerAvbHandle later. 396 // Note that the parent callback removes partitions from the list of required partitions 397 // as it finds them, so this must happen first. 398 if (!uevent.partition_name.empty() && 399 required_devices_partition_names_.find(uevent.partition_name) != 400 required_devices_partition_names_.end()) { 401 // GetBlockDeviceSymlinks() will return three symlinks at most, depending on 402 // the content of uevent. by-name symlink will be at [0] if uevent->partition_name 403 // is not empty. e.g., 404 // - /dev/block/platform/soc.0/f9824900.sdhci/by-name/modem 405 // - /dev/block/platform/soc.0/f9824900.sdhci/by-num/p1 406 // - /dev/block/platform/soc.0/f9824900.sdhci/mmcblk0p1 407 std::vector<std::string> links = device_handler_.GetBlockDeviceSymlinks(uevent); 408 if (!links.empty()) { 409 auto[it, inserted] = by_name_symlink_map_.emplace(uevent.partition_name, links[0]); 410 if (!inserted) { 411 LOG(ERROR) << "Partition '" << uevent.partition_name 412 << "' already existed in the by-name symlink map with a value of '" 413 << it->second << "', new value '" << links[0] << "' will be ignored."; 414 } 415 } 416 } 417 418 return FirstStageMount::UeventCallback(uevent); 419} 420 421bool FirstStageMountVBootV2::SetUpDmVerity(fstab_rec* fstab_rec) { 422 if (fs_mgr_is_avb(fstab_rec)) { 423 if (!InitAvbHandle()) return false; 424 SetUpAvbHashtreeResult hashtree_result = 425 avb_handle_->SetUpAvbHashtree(fstab_rec, false /* wait_for_verity_dev */); 426 switch (hashtree_result) { 427 case SetUpAvbHashtreeResult::kDisabled: 428 return true; // Returns true to mount the partition. 429 case SetUpAvbHashtreeResult::kSuccess: 430 // The exact block device name (fstab_rec->blk_device) is changed to 431 // "/dev/block/dm-XX". Needs to create it because ueventd isn't started in init 432 // first stage. 433 return InitVerityDevice(fstab_rec->blk_device); 434 default: 435 return false; 436 } 437 } 438 return true; // Returns true to mount the partition. 439} 440 441bool FirstStageMountVBootV2::InitAvbHandle() { 442 if (avb_handle_) return true; // Returns true if the handle is already initialized. 443 444 if (by_name_symlink_map_.empty()) { 445 LOG(ERROR) << "by_name_symlink_map_ is empty"; 446 return false; 447 } 448 449 avb_handle_ = FsManagerAvbHandle::Open(std::move(by_name_symlink_map_)); 450 by_name_symlink_map_.clear(); // Removes all elements after the above std::move(). 451 452 if (!avb_handle_) { 453 PLOG(ERROR) << "Failed to open FsManagerAvbHandle"; 454 return false; 455 } 456 // Sets INIT_AVB_VERSION here for init to set ro.boot.avb_version in the second stage. 457 setenv("INIT_AVB_VERSION", avb_handle_->avb_version().c_str(), 1); 458 return true; 459} 460 461// Public functions 462// ---------------- 463// Mounts partitions specified by fstab in device tree. 464bool DoFirstStageMount() { 465 // Skips first stage mount if we're in recovery mode. 466 if (IsRecoveryMode()) { 467 LOG(INFO) << "First stage mount skipped (recovery mode)"; 468 return true; 469 } 470 471 // Firstly checks if device tree fstab entries are compatible. 472 if (!is_android_dt_value_expected("fstab/compatible", "android,fstab")) { 473 LOG(INFO) << "First stage mount skipped (missing/incompatible fstab in device tree)"; 474 return true; 475 } 476 477 std::unique_ptr<FirstStageMount> handle = FirstStageMount::Create(); 478 if (!handle) { 479 LOG(ERROR) << "Failed to create FirstStageMount"; 480 return false; 481 } 482 return handle->DoFirstStageMount(); 483} 484 485void SetInitAvbVersionInRecovery() { 486 if (!IsRecoveryMode()) { 487 LOG(INFO) << "Skipped setting INIT_AVB_VERSION (not in recovery mode)"; 488 return; 489 } 490 491 if (!IsDtVbmetaCompatible()) { 492 LOG(INFO) << "Skipped setting INIT_AVB_VERSION (not vbmeta compatible)"; 493 return; 494 } 495 496 // Initializes required devices for the subsequent FsManagerAvbHandle::Open() 497 // to verify AVB metadata on all partitions in the verified chain. 498 // We only set INIT_AVB_VERSION when the AVB verification succeeds, i.e., the 499 // Open() function returns a valid handle. 500 // We don't need to mount partitions here in recovery mode. 501 FirstStageMountVBootV2 avb_first_mount; 502 if (!avb_first_mount.InitDevices()) { 503 LOG(ERROR) << "Failed to init devices for INIT_AVB_VERSION"; 504 return; 505 } 506 507 FsManagerAvbUniquePtr avb_handle = 508 FsManagerAvbHandle::Open(std::move(avb_first_mount.by_name_symlink_map_)); 509 if (!avb_handle) { 510 PLOG(ERROR) << "Failed to open FsManagerAvbHandle for INIT_AVB_VERSION"; 511 return; 512 } 513 setenv("INIT_AVB_VERSION", avb_handle->avb_version().c_str(), 1); 514} 515 516} // namespace init 517} // namespace android 518