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