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

Commit ab4dd013 authored by Yi-Yo Chiang's avatar Yi-Yo Chiang
Browse files

set-verity-state: Use ro.boot.veritymode to determine current verity state

On a device that don't use overlayfs remount (e.g. no EXT4 dup blocks;
this can be simulated by patching fs_mgr_wants_overlayfs()), if we run
disable-verity or enable-verity twice in a row then the second
invocation would not suggest a reboot:

  adb disable-verity
  > Successfully disabled verity
  > Reboot to take effect...
  adb disable-verity
  > Verity is already disabled
              ^^^ this is WRONG! verity is disabled only after a reboot

It behaves like this because it suggest a reboot only if the vbmeta
verity (HASHTREE) flag is changed.
Read the ro.boot.veritymode property instead to determine the current
dm-verity state and suggest a reboot by comparing current and future
verity state:
* If AVB verification is disabled, then ro.boot.veritymode is undefined
  (probably empty), don't suggest reboot in this case as it's pointless.
* Otherwise suggest a reboot if the new state (which would take effect
  after reboot) differs from the current verity state.
* Reference:
  https://android.googlesource.com/platform/external/avb/+/master/README.md#handling-dm_verity-errors

Bug: 241688845
Test: adb-remount-test
Test: Run "adb enable-verity" & "adb disable-verity" multiple times
Change-Id: If1df5bee6e5dcbda580b3dff6c32da93d08bbb46
parent 2a501a11
Loading
Loading
Loading
Loading
+16 −13
Original line number Original line Diff line number Diff line
@@ -445,30 +445,33 @@ struct SetVerityStateResult {


SetVerityStateResult SetVerityState(bool enable_verity) {
SetVerityStateResult SetVerityState(bool enable_verity) {
    const auto ab_suffix = android::base::GetProperty("ro.boot.slot_suffix", "");
    const auto ab_suffix = android::base::GetProperty("ro.boot.slot_suffix", "");
    bool verity_enabled = false;

    std::unique_ptr<AvbOps, decltype(&avb_ops_user_free)> ops(avb_ops_user_new(),
    std::unique_ptr<AvbOps, decltype(&avb_ops_user_free)> ops(avb_ops_user_new(),
                                                              &avb_ops_user_free);
                                                              &avb_ops_user_free);
    if (!ops) {
    if (!ops) {
        LOG(ERROR) << "Error getting AVB ops";
        LOG(ERROR) << "Error getting AVB ops";
        return {};
        return {};
    }
    }

    if (!avb_user_verity_set(ops.get(), ab_suffix.c_str(), enable_verity)) {
    if (!avb_user_verity_get(ops.get(), ab_suffix.c_str(), &verity_enabled)) {
        LOG(ERROR) << "Error setting verity state";
        LOG(ERROR) << "Error getting verity state";
        return {};
        return {};
    }
    }

    bool verification_enabled = false;
    if ((verity_enabled && enable_verity) || (!verity_enabled && !enable_verity)) {
    if (!avb_user_verification_get(ops.get(), ab_suffix.c_str(), &verification_enabled)) {
        LOG(INFO) << "Verity is already " << (verity_enabled ? "enabled" : "disabled");
        LOG(ERROR) << "Error getting verification state";
        return {};
    }
    if (!verification_enabled) {
        LOG(WARNING) << "AVB verification is disabled, "
                     << (enable_verity ? "enabling" : "disabling")
                     << " verity state may have no effect";
        return {.success = true, .want_reboot = false};
        return {.success = true, .want_reboot = false};
    }
    }

    const auto verity_mode = android::base::GetProperty("ro.boot.veritymode", "");
    if (!avb_user_verity_set(ops.get(), ab_suffix.c_str(), enable_verity)) {
    const bool was_enabled = (verity_mode != "disabled");
        LOG(ERROR) << "Error setting verity state";
    if ((was_enabled && enable_verity) || (!was_enabled && !enable_verity)) {
        return {};
        LOG(INFO) << "Verity is already " << (enable_verity ? "enabled" : "disabled");
        return {.success = true, .want_reboot = false};
    }
    }

    LOG(INFO) << "Successfully " << (enable_verity ? "enabled" : "disabled") << " verity";
    LOG(INFO) << "Successfully " << (enable_verity ? "enabled" : "disabled") << " verity";
    return {.success = true, .want_reboot = true};
    return {.success = true, .want_reboot = true};
}
}