Home | History | Annotate | Download | only in init
      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 
     40 using android::base::Timer;
     41 
     42 namespace android {
     43 namespace init {
     44 
     45 // Class Declarations
     46 // ------------------
     47 class 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 
     79 class 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 
     89 class 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 // ----------------
    109 static inline bool IsDtVbmetaCompatible() {
    110     return is_android_dt_value_expected("vbmeta/compatible", "android,vbmeta");
    111 }
    112 
    113 static bool inline IsRecoveryMode() {
    114     return access("/sbin/recovery", F_OK) == 0;
    115 }
    116 
    117 // Class Definitions
    118 // -----------------
    119 FirstStageMount::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 
    137 std::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 
    145 bool 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 
    156 bool 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.
    163 bool 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 
    215 ListenerAction 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 
    233 ListenerAction 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.
    252 bool 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 
    282 bool 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 
    296 bool 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 
    337 bool 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 //  }
    369 FirstStageMountVBootV2::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 
    376 bool 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 
    409 ListenerAction 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 
    436 bool 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 
    456 bool 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.
    479 bool 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 
    500 void 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