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// ------------------
38class 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
68class 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
78class 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// ----------------
98static inline bool IsDtVbmetaCompatible() {
99    return is_android_dt_value_expected("vbmeta/compatible", "android,vbmeta");
100}
101
102static bool inline IsRecoveryMode() {
103    return access("/sbin/recovery", F_OK) == 0;
104}
105
106// Class Definitions
107// -----------------
108FirstStageMount::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
123std::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
131bool 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
142bool 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.
161void 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
180coldboot_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.
211void 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
225bool 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
239bool 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
280bool 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//  }
308FirstStageMountVBootV2::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
315bool 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
348coldboot_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
377bool 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
393bool 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.
416bool 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
437void 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