Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6f451a9c authored by David Anderson's avatar David Anderson
Browse files

init: Issue a wipe on boot if trade-in mode was active.

This modifies first-stage init to check for /metadata/tradeinmode/wipe
as soon as /metadata is mounted. If the file exists, we issue a request
to the bootloader to reboot to recovery and wipe /data. Since this also
wipes /metadata, the wipe indicator will be removed too.

In case some kind of failure happens in recovery, this also implements a
quick-and-dirty counter mechanism to fallback to the recovery menu.

Bug: 307713521
Test: touch /metadata/tradeinmode/wipe && adb reboot
Change-Id: I2d05903cadcdadf9c05f6736454db790a9e6b5bb
parent 47ec15c9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -390,6 +390,7 @@ init_first_stage_cc_defaults {
        "libsnapshot_init",
        "update_metadata-protos",
        "libprocinfo",
        "libbootloader_message",
    ],

    static_executable: true,
+57 −0
Original line number Diff line number Diff line
@@ -32,9 +32,12 @@
#include <android-base/chrono_utils.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android/avf_cc_flags.h>
#include <bootloader_message/bootloader_message.h>
#include <cutils/android_reboot.h>
#include <fs_avb/fs_avb.h>
#include <fs_mgr.h>
#include <fs_mgr_dm_linear.h>
@@ -46,6 +49,7 @@

#include "block_dev_initializer.h"
#include "devices.h"
#include "reboot_utils.h"
#include "result.h"
#include "snapuserd_transition.h"
#include "switch_root.h"
@@ -111,6 +115,8 @@ class FirstStageMountVBootV2 : public FirstStageMount {
    bool GetDmVerityDevices(std::set<std::string>* devices);
    bool SetUpDmVerity(FstabEntry* fstab_entry);

    void RequestTradeInModeWipeIfNeeded();

    bool InitAvbHandle();

    bool need_dm_verity_;
@@ -263,6 +269,8 @@ bool FirstStageMountVBootV2::DoCreateDevices() {
}

bool FirstStageMountVBootV2::DoFirstStageMount() {
    RequestTradeInModeWipeIfNeeded();

    if (!IsDmLinearEnabled() && fstab_.empty()) {
        // Nothing to mount.
        LOG(INFO) << "First stage mount skipped (missing/incompatible/empty fstab in device tree)";
@@ -883,6 +891,55 @@ bool FirstStageMountVBootV2::InitAvbHandle() {
    return true;
}

void FirstStageMountVBootV2::RequestTradeInModeWipeIfNeeded() {
    static constexpr const char* kWipeIndicator = "/metadata/tradeinmode/wipe";
    static constexpr size_t kWipeAttempts = 3;

    if (access(kWipeIndicator, R_OK) == -1) {
        return;
    }

    // Write a counter to the wipe indicator, to try and prevent boot loops if
    // recovery fails to wipe data.
    uint32_t counter = 0;
    std::string contents;
    if (ReadFileToString(kWipeIndicator, &contents)) {
        android::base::ParseUint(contents, &counter);
        contents = std::to_string(++counter);
        if (android::base::WriteStringToFile(contents, kWipeIndicator)) {
            sync();
        } else {
            PLOG(ERROR) << "Failed to update " << kWipeIndicator;
        }
    } else {
        PLOG(ERROR) << "Failed to read " << kWipeIndicator;
    }

    std::string err;
    auto misc_device = get_misc_blk_device(&err);
    if (misc_device.empty()) {
        LOG(FATAL) << "Could not find misc device: " << err;
    }

    auto misc_name = android::base::Basename(misc_device);
    if (!block_dev_init_.InitDevices({misc_name})) {
        LOG(FATAL) << "Could not find misc device: " << misc_device;
    }

    // If we've failed to wipe three times, don't include the wipe command. This
    // will force us to boot into the recovery menu instead where a manual wipe
    // can be attempted.
    std::vector<std::string> options;
    if (counter <= kWipeAttempts) {
        options.emplace_back("--wipe_data");
        options.emplace_back("--reason=tradeinmode");
    }
    if (!write_bootloader_message(options, &err)) {
        LOG(FATAL) << "Could not issue wipe: " << err;
    }
    RebootSystem(ANDROID_RB_RESTART2, "recovery", "reboot,tradeinmode,wipe");
}

void SetInitAvbVersionInRecovery() {
    if (!IsRecoveryMode()) {
        LOG(INFO) << "Skipped setting INIT_AVB_VERSION (not in recovery mode)";
+1 −0
Original line number Diff line number Diff line
@@ -644,6 +644,7 @@ on post-fs
    mkdir /metadata/ota 0750 root system
    mkdir /metadata/ota/snapshots 0750 root system
    mkdir /metadata/watchdog 0770 root system
    mkdir /metadata/tradeinmode 0770 root system

    mkdir /metadata/apex 0700 root system
    mkdir /metadata/apex/sessions 0700 root system