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