Android折腾重启报set_policy_failed:/data/adb

Table of contents

TL;DR: 修改init脚本,把 init.usb.rcencryption=Require 改成encryption=DeleteIfNecessary,在system分区中应用修改,再重启。

起因

调试 KernelSU,把 /data/adb 删了,manager创建了个新的。结果就这样。

原理

File based encryption. init脚本会在开机时配置/创建所需要的文件目录结构,但若所设加密策略与实际不匹配,就会报错要求擦除数据。

以LineageOS 23.0为例,

system/core/init/builtins.cpp

    if (IsFbeEnabled()) {
        if (!FscryptSetDirectoryPolicy(ref_basename, options.fscrypt_action, options.target)) {
            return reboot_into_recovery(
                    {"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + options.target});
        }
    }

又见 system/core/init/fscrypt_init_extensions.cpp

bool FscryptSetDirectoryPolicy(const std::string& ref_basename, FscryptAction action,
                               const std::string& dir) {
    if (action == FscryptAction::kNone) {
        return true;
    }
    if (SetPolicyOn(ref_basename, dir) || action == FscryptAction::kAttempt) {
        return true;
    }
    if (action == FscryptAction::kDeleteIfNecessary) {
        LOG(ERROR) << "Setting policy failed, deleting: " << dir;
        delete_dir_contents(dir);
        return SetPolicyOn(ref_basename, dir);
    }
    return false;
}

init.usb.rc 中有:

on post-fs-data
    ...(skip)
    mkdir /data/adb 0700 root root encryption=Require

导致 /data/adb 出加密配置问题时系统会提示擦除数据。

幸好有办法在遇到错误时删掉整个目录……不然从备份恢复也够麻烦的……