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