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 <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 // ----------------
     98 static inline bool IsDtVbmetaCompatible() {
     99     return is_android_dt_value_expected("vbmeta/compatible", "android,vbmeta");
    100 }
    101 
    102 static bool inline IsRecoveryMode() {
    103     return access("/sbin/recovery", F_OK) == 0;
    104 }
    105 
    106 // Class Definitions
    107 // -----------------
    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 
    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 
    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 
    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.
    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 
    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.
    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 
    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 
    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 
    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 //  }
    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 
    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 
    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 
    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 
    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.
    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 
    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