前情提要
遇到问题
当然是和之前一样啦,开机并不能正常启动,而是
自动进入了 recovery 界面,且界面显示
Can’t load Android system. You’r data may be corrupt.If you continue to get this message, you may
need to perform a factory data reset and erase all user data stored on this devices.
按照提示我进行了恢复出厂操作,恢复出厂后能正常开机。但是预装的app没了,很明显预装app会没了。
按照之前 Q 版本的经验去修改代码后,问题依旧,还是不能正常开机,这就离谱,难道谷歌把这个地方给
堵死了???这还能难倒我么,上才艺。
解决办法
跳过 data 分区下 app 目录加密策略读取和设置即可
system/core/init/util.cpp
@@ -88,7 +88,7 @@ static FscryptAction FscryptInferAction(const std::string& dir) // Special case various directories that must not be encrypted, // often because their subdirectories must be encrypted. // This isn't a nice way to do this, see b/26641735 std::vector<std::string> directories_to_exclude = { "lost+found", "system_ce", "system_de", "misc_ce", "misc_de", "vendor_ce", "vendor_de", "media", "data", "user", - "user_de", "apex", "preloads", "app-staging", "gsi", + "user_de", "apex", "preloads", "app-staging", "gsi", "app", }; for (const auto& d : directories_to_exclude) { if ((prefix + d) == dir) { return FscryptAction::kNone; } }
跳过 init.rc 中 /data/app 节点加密
system/core/rootdir/init.rc
+++ b/alps/system/core/rootdir/init.rc @@ -658,7 +658,7 @@ on post-fs-data mkdir /data/app-ephemeral 0771 system system encryption=Require mkdir /data/app-asec 0700 root root encryption=Require mkdir /data/app-lib 0771 system system encryption=Require - mkdir /data/app 0771 system system encryption=Require + mkdir /data/app 0771 system system encryption=None mkdir /data/property 0700 root root encryption=Require mkdir /data/tombstones 0771 system system encryption=Require mkdir /data/vendor/tombstones 0771 root root
分析过程
当然要打开串口 Log 记录呀,它又不是那么简单的。R 版本的串口打开修改地方如下
kernel-4.19\drivers\misc\mediatek\mtprintk\mtk_printk_ctrl.c
@@ -43,7 +43,7 @@ module_param_named(disable_uart, printk_ctrl, int, 0644); bool mt_get_uartlog_status(void) { if (printk_ctrl == 1) - return false; + return true; else if ((printk_ctrl == 0) || (printk_ctrl == 2)) return true; return true; @@ -53,7 +53,7 @@ void mt_disable_uart(void) { /* uart print not always enable */ if (printk_ctrl != 2) - printk_ctrl = 1; + printk_ctrl = 0; } EXPORT_SYMBOL_GPL(mt_disable_uart);
vendor/mediatek/proprietary/bootable/bootloader/lk/app/mt_boot/mt_boot.c
@@ -1345,7 +1345,7 @@ int boot_linux_fdt(void *kernel, unsigned *tags, #endif cmdline_append("mtk_printk_ctrl.disable_uart=0"); else - cmdline_append("mtk_printk_ctrl.disable_uart=1"); + cmdline_append("mtk_printk_ctrl.disable_uart=0"); break; case BUILD_TYPE_USERDEBUG: @@ -1355,13 +1355,13 @@ int boot_linux_fdt(void *kernel, unsigned *tags, #else (is_meta_log_disable() == 1)) #endif - cmdline_append("mtk_printk_ctrl.disable_uart=1 slub_debug=O"); + cmdline_append("mtk_printk_ctrl.disable_uart=0 slub_debug=O"); #ifdef LOG_STORE_SUPPORT else if (boot_ftrace && g_boot_arg->log_dynamic_switch == 0) #else else if (boot_ftrace) #endif - cmdline_append("mtk_printk_ctrl.disable_uart=1 slub_debug=-"); + cmdline_append("mtk_printk_ctrl.disable_uart=0 slub_debug=-"); else cmdline_append("mtk_printk_ctrl.disable_uart=0"); break; @@ -1369,7 +1369,7 @@ int boot_linux_fdt(void *kernel, unsigned *tags, case BUILD_TYPE_ENG: if ((g_boot_mode == META_BOOT) && is_meta_log_disable && (is_meta_log_disable() == 1)) - cmdline_append("mtk_printk_ctrl.disable_uart=1 slub_debug=O"); + cmdline_append("mtk_printk_ctrl.disable_uart=0 slub_debug=O"); else cmdline_append("mtk_printk_ctrl.disable_uart=0 ddebug_query=\"file *mediatek* +p ; file *gpu* =_\""); break;
重新编译烧写开机得到如下串口日志
[ 13.654157] <4>.(4)[1:init]init 21: [13623][0]Switched to default mount namespace [ 13.655223] <4>.(4)[1:init]init 21: [13624][0]Not setting encryption policy on: /data/apex [ 13.663218] <4>.(4)[1:init]init 21: [13632][0]Not setting encryption policy on: /data/app-staging [ 13.666087] <4>.(4)[1:init]init 21: [13635][0]starting service 'apexd'... ) failed: No such file or directory [ 13.677980] <4>.(4)[1:init]init 25: [13644][0]Encryption policy of /data/misc set to d27f72eaf61213e463b2a9ec48dae65d v2 modes 1/4 flags 0x2 d input file '/data/misc/recovery/ro.build.fingerprint': open() failed: No such file or directory ata/misc/recovery/proc/version': open() failed: No such file or directory [ 13.692959] <7>.(7)[456:apexd]apexd: Scanning /system/apex for preinstalled data [ 13.698614] <1>.(1)[456:apexd]apexd: Scanning /system_ext/apex for preinstalled data [ 13.699725] <1>.(1)[456:apexd]apexd: ... does not exist. Skipping path.utils.link]=[stopped]13507 [init.svc_debug_pid.mtk.plpath.utils.link]=[]13507 [dev.mnt.blk.data]=[dm-7]13509 [init.svc.apexd]=[running]13639 [ro.boottime.apexd]=[13638876462]13640 [init.svc_debug_pid.apexd]=[456]13641 Done [ 13.700519] <1>.(1)[456:apexd]apexd: Scanning /product/apex for preinstalled data [ 13.706583] <1>.(1)[456:apexd]apexd: ... does not exist. Skipping [ 13.707396] <1>.(1)[456:apexd]apexd: Scanning /vendor/apex for preinstalled data [ 13.708382] <1>.(1)[456:apexd]apexd: ... does not exist. Skipping [ 13.709166] <1>.(1)[456:apexd]apexd: Populating APEX database from mounts... [ 13.710720] <1>.(1)[456:apexd]apexd: 0 packages restored. [ 13.711617] <1>.(1)[456:apexd]apexd: Marking APEXd as starting [ 13.730259] <3>.(3)[1:init]init 25: [13698][0]Encryption policy of /data/local set to d27f72eaf61213e463b2a9ec48dae65d v2 modes 1/4 flags 0x2 [ 13.745616] <1>.(1)[456:apexd]EXT4-fs (loop6): mounted filesystem without journal. Opts: (null) [ 13.758344] <3>.(3)[1:init]init 25: [13727][0]Not setting encryption policy on: /data/preloads [ 13.762309] <3>.(3)[1:init]init 25: [13730][0]Encryption policy of /data/vendor set to d27f72eaf61213e463b2a9ec48dae65d v2 modes 1/4 flags 0x2 [ 13.764161] <3>.(3)[1:init]init 25: [13733][0]Not setting encryption policy on: /data/vendor_ce [ 13.766555] <3>.(3)[1:init]init 25: [13735][0]Not setting encryption policy on: /data/vendor_de [ 13.773079] <3>.(3)[1:init]init 25: [13742][0]Not setting encryption policy on: /data/data [ 13.776787] <1>.(1)[456:apexd]EXT4-fs (loop7): mounted filesystem without journal. Opts: (null) [ 13.777475] <3>.(3)[1:init]init 21: [13745][0]Encryption policy of /data/app-private set to d27f72eaf61213e463b2a9ec48dae65d v2 modes 1/4 flags 0x2 [ 13.781923] <0>.(0)[1:init]init 21: [13749][0]Encryption policy of /data/app-ephemeral set to d27f72eaf61213e463b2a9ec48dae65d v2 modes 1/4 flags 0x2 [ 13.785340] <0>.(0)[1:init]init 21: [13753][0]Encryption policy of /data/app-asec set to d27f72eaf61213e463b2a9ec48dae65d v2 modes 1/4 flags 0x2 [ 13.788729] <0>.(0)[1:init]init 21: [13756][0]Encryption policy of /data/app-lib set to d27f72eaf61213e463b2a9ec48dae65d v2 modes 1/4 flags 0x2 [ 13.790485] <0>.(0)[1:init]init 21: [13759][0]Inferred action different from explicit one, expected 0 but got 2 [ 13.792434] <0>.(0)[1:init]init 21: [13759][0]Failed to set encryption policy of /data/app to d27f72eaf61213e463b2a9ec48dae65d v2 modes 1/4 flags 0x2: Directory not empty :s0 tclass=file permissive=1 [ 13.800279] <2>.(2)[1:init]ls 21: [13759][0]executing ls failed: No such file or directory [ 13.800313] <2>.(1)[462:init]logwrapper 21: executing ls failed: No such file or directory [ 13.800321] <2>.(1)[462:init]logwrapper 21: [ 13.805673] <2>.(2)[1:init]ls 21: [13759][0]ls terminated by exit(255) [ 13.806716] <2>.(2)[1:init]init: 1 output lines suppressed due to ratelimiting [ 13.807641] <2>.(2)[1:init]init 25: [13759][0]ls -laZ /data/app returned failure: 255 [ 13.808723] <2>.(2)[1:init]init 25: [13759][0]Setting d27f72eaf61213e463b2a9ec48dae65d policy on /data/app failed! [ 13.809210] <0>.(0)[456:apexd]EXT4-fs (loop8): mounted filesystem without journal. Opts: (null) [ 13.810098] <2>.(2)[1:init]init 25: [13759][0]Rebooting into recovery
和原来还是一样的配方,错误提示
Failed to set encryption policy of /data/app to d27f72eaf61213e463b2a9ec48dae65d v2 modes 1/4 flags 0x2: Directory not empty
R 版本上谷歌对 libfscrypt 这块进行了重构,代码移到了 system/core/init/util.cpp 中
现在来看下整体的流程,切入点从 init.rc 开始
mkdir /data/app 0771 system system encryption=Require
相比较 Q 版本的 init.rc R 多出了 encryption=Require 属性,就是这个属性决定了 boot
阶段需要检查文件加密情况。mkdir 指令应该调用 builtins 中 do_mkdir(args) 方法
system\core\init\builtins.cpp
// mkdir <path> [mode] [owner] [group] [<option> ...] static Result<void> do_mkdir(const BuiltinArguments& args) { auto options = ParseMkdir(args.args); if (!options.ok()) return options.error(); return make_dir_with_options(*options); } static Result<void> make_dir_with_options(const MkdirOptions& options) { std::string ref_basename; if (options.ref_option == "ref") { ref_basename = fscrypt_key_ref; } else if (options.ref_option == "per_boot_ref") { ref_basename = fscrypt_key_per_boot_ref; } else { return Error() << "Unknown key option: '" << options.ref_option << "'"; } struct stat mstat; if (lstat(options.target.c_str(), &mstat) != 0) { if (errno != ENOENT) { return ErrnoError() << "lstat() failed on " << options.target; } if (!make_dir(options.target, options.mode)) { return ErrnoErrorIgnoreEnoent() << "mkdir() failed on " << options.target; } if (lstat(options.target.c_str(), &mstat) != 0) { return ErrnoError() << "lstat() failed on new " << options.target; } } if (!S_ISDIR(mstat.st_mode)) { return Error() << "Not a directory on " << options.target; } bool needs_chmod = (mstat.st_mode & ~S_IFMT) != options.mode; if ((options.uid != static_cast<uid_t>(-1) && options.uid != mstat.st_uid) || (options.gid != static_cast<gid_t>(-1) && options.gid != mstat.st_gid)) { if (lchown(options.target.c_str(), options.uid, options.gid) == -1) { return ErrnoError() << "lchown failed on " << options.target; } // chown may have cleared S_ISUID and S_ISGID, chmod again needs_chmod = true; } if (needs_chmod) { if (fchmodat(AT_FDCWD, options.target.c_str(), options.mode, AT_SYMLINK_NOFOLLOW) == -1) { return ErrnoError() << "fchmodat() failed on " << options.target; } } if (fscrypt_is_native()) { if (!FscryptSetDirectoryPolicy(ref_basename, options.fscrypt_action, options.target)) { return reboot_into_recovery( {"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + options.target}); } } return {}; }
可以看到其中调用 ParseMkdir(args.args) 获取 options,然后根据 options 创建文件夹,
如果过程中没遇到问题,则 return {} 可以看到出问题的时候进入 recovery 界面,应该是走的
reboot_into_recovery(
{"–prompt_and_wipe_data", "–reason=set_policy_failed:"s + options.target})
那么来看下 FscryptSetDirectoryPolicy() 方法是如何判断的
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; }
可以看到要想不进入 recovery 界面,action 为 FscryptAction::kNone 即可,也就是跳过
action 的取值 options.fscrypt_action,回到 builtins.cpp 中关注 auto options = ParseMkdir(args.args);
system\core\init\util.cpp
Result<MkdirOptions> ParseMkdir(const std::vector<std::string>& args) { mode_t mode = 0755; Result<uid_t> uid = -1; Result<gid_t> gid = -1; //第一次赋值 fscrypt_action,FscryptInferAction() 和之前一样有白名单可跳过 FscryptAction fscrypt_inferred_action = FscryptInferAction(args[1]); FscryptAction fscrypt_action = fscrypt_inferred_action; std::string ref_option = "ref"; bool set_option_encryption = false; bool set_option_key = false; for (size_t i = 2; i < args.size(); i++) { switch (i) { case 2: mode = std::strtoul(args[2].c_str(), 0, 8); break; case 3: uid = DecodeUid(args[3]); if (!uid.ok()) { return Error() << "Unable to decode UID for '" << args[3] << "': " << uid.error(); } break; case 4: gid = DecodeUid(args[4]); if (!gid.ok()) { return Error() << "Unable to decode GID for '" << args[4] << "': " << gid.error(); } break; default: auto parts = android::base::Split(args[i], "="); if (parts.size() != 2) { return Error() << "Can't parse option: '" << args[i] << "'"; } auto optname = parts[0]; auto optval = parts[1]; //第二次赋值 fscrypt_action,根据 optval 值再次判断 //这里增加 log 打印后发现 optname = encryption optval = Require/None 在init.rc中配置 if (optname == "encryption") { if (set_option_encryption) { return Error() << "Duplicated option: '" << optname << "'"; } if (optval == "Require") { fscrypt_action = FscryptAction::kRequire; } else if (optval == "None") { fscrypt_action = FscryptAction::kNone; } else if (optval == "Attempt") { fscrypt_action = FscryptAction::kAttempt; } else if (optval == "DeleteIfNecessary") { fscrypt_action = FscryptAction::kDeleteIfNecessary; } else { return Error() << "Unknown encryption option: '" << optval << "'"; } set_option_encryption = true; } else if (optname == "key") { if (set_option_key) { return Error() << "Duplicated option: '" << optname << "'"; } if (optval == "ref" || optval == "per_boot_ref") { ref_option = optval; } else { return Error() << "Unknown key option: '" << optval << "'"; } set_option_key = true; } else { return Error() << "Unknown option: '" << args[i] << "'"; } } } if (set_option_key && fscrypt_action == FscryptAction::kNone) { return Error() << "Key option set but encryption action is none"; } const std::string prefix = "/data/"; if (StartsWith(args[1], prefix) && args[1].find_first_of('/', prefix.size()) == std::string::npos) { if (!set_option_encryption) { LOG(WARNING) << "Top-level directory needs encryption action, eg mkdir " << args[1] << " <mode> <uid> <gid> encryption=Require"; } if (fscrypt_action == FscryptAction::kNone) { LOG(INFO) << "Not setting encryption policy on: " << args[1]; } } if (fscrypt_action != fscrypt_inferred_action) { LOG(WARNING) << "Inferred action different from explicit one, expected " << static_cast<int>(fscrypt_inferred_action) << " but got " << static_cast<int>(fscrypt_action); } //构建 options 返回 return MkdirOptions{args[1], mode, *uid, *gid, fscrypt_action, ref_option}; } static FscryptAction FscryptInferAction(const std::string& dir) { const std::string prefix = "/data/"; if (!android::base::StartsWith(dir, prefix)) { return FscryptAction::kNone; } // Special-case /data/media/obb per b/64566063 if (dir == "/data/media/obb") { // Try to set policy on this directory, but if it is non-empty this may fail. return FscryptAction::kAttempt; } // Only set policy on first level /data directories // To make this less restrictive, consider using a policy file. // However this is overkill for as long as the policy is simply // to apply a global policy to all /data folders created via makedir if (dir.find_first_of('/', prefix.size()) != std::string::npos) { return FscryptAction::kNone; } // Special case various directories that must not be encrypted, // often because their subdirectories must be encrypted. // This isn't a nice way to do this, see b/26641735 std::vector<std::string> directories_to_exclude = { "lost+found", "system_ce", "system_de", "misc_ce", "misc_de", "vendor_ce", "vendor_de", "media", "data", "user", "user_de", "apex", "preloads", "app-staging", "gsi", }; //在 directories_to_exclude 集合中则跳过 for (const auto& d : directories_to_exclude) { if ((prefix + d) == dir) { return FscryptAction::kNone; } } // Empty these directories if policy setting fails. std::vector<std::string> wipe_on_failure = { "rollback", "rollback-observer", // b/139193659 "connsyslog", "debuglogger", "ramdump", "mdlog", "log_temp", "aee_exp", "mdl", }; for (const auto& d : wipe_on_failure) { if ((prefix + d) == dir) { return FscryptAction::kDeleteIfNecessary; } } return FscryptAction::kRequire; }
可以看到这样正常的流程就走完了,接下来看下错误的流程
回到 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; } static bool SetPolicyOn(const std::string& ref_basename, const std::string& dir) { EncryptionPolicy policy; if (!LookupPolicy(ref_basename, &policy)) return false; if (!EnsurePolicyOrLog(policy, dir)) return false; return true; } static bool EnsurePolicyOrLog(const EncryptionPolicy& policy, const std::string& dir) { if (!EnsurePolicy(policy, dir)) { std::string ref_hex; BytesToHex(policy.key_raw_ref, &ref_hex); LOG(ERROR) << "Setting " << ref_hex << " policy on " << dir << " failed!"; return false; } return true; }
最终调用到 system\extras\libfscrypt\fscrypt.cpp
bool EnsurePolicy(const EncryptionPolicy& policy, const std::string& directory) { union { fscrypt_policy_v1 v1; fscrypt_policy_v2 v2; } kern_policy; memset(&kern_policy, 0, sizeof(kern_policy)); switch (policy.options.version) { case 1: if (policy.key_raw_ref.size() != FSCRYPT_KEY_DESCRIPTOR_SIZE) { LOG(ERROR) << "Invalid key descriptor length for v1 policy: " << policy.key_raw_ref.size(); return false; } // Careful: FSCRYPT_POLICY_V1 is actually 0 in the API, so make sure // to use it here instead of a literal 1. kern_policy.v1.version = FSCRYPT_POLICY_V1; kern_policy.v1.contents_encryption_mode = policy.options.contents_mode; kern_policy.v1.filenames_encryption_mode = policy.options.filenames_mode; kern_policy.v1.flags = policy.options.flags; policy.key_raw_ref.copy(reinterpret_cast<char*>(kern_policy.v1.master_key_descriptor), FSCRYPT_KEY_DESCRIPTOR_SIZE); break; case 2: if (policy.key_raw_ref.size() != FSCRYPT_KEY_IDENTIFIER_SIZE) { LOG(ERROR) << "Invalid key identifier length for v2 policy: " << policy.key_raw_ref.size(); return false; } kern_policy.v2.version = FSCRYPT_POLICY_V2; kern_policy.v2.contents_encryption_mode = policy.options.contents_mode; kern_policy.v2.filenames_encryption_mode = policy.options.filenames_mode; kern_policy.v2.flags = policy.options.flags; policy.key_raw_ref.copy(reinterpret_cast<char*>(kern_policy.v2.master_key_identifier), FSCRYPT_KEY_IDENTIFIER_SIZE); break; default: LOG(ERROR) << "Invalid encryption policy version: " << policy.options.version; return false; } android::base::unique_fd fd(open(directory.c_str(), O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC)); if (fd == -1) { PLOG(ERROR) << "Failed to open directory " << directory; return false; } bool already_encrypted = fscrypt_is_encrypted(fd); // FS_IOC_SET_ENCRYPTION_POLICY will set the policy if the directory is // unencrypted; otherwise it will verify that the existing policy matches. // Setting the policy will fail if the directory is already nonempty. if (ioctl(fd, FS_IOC_SET_ENCRYPTION_POLICY, &kern_policy) != 0) { std::string reason; switch (errno) { case EEXIST: reason = "The directory already has a different encryption policy."; break; default: reason = strerror(errno); break; } LOG(ERROR) << "Failed to set encryption policy of " << directory << " to " << PolicyDebugString(policy) << ": " << reason; if (errno == ENOTEMPTY) { log_ls(directory.c_str()); } return false; } if (already_encrypted) { LOG(INFO) << "Verified that " << directory << " has the encryption policy " << PolicyDebugString(policy); } else { LOG(INFO) << "Encryption policy of " << directory << " set to " << PolicyDebugString(policy); } return true; }
重新编译烧写后成功开机的log,可以看到打印了跳过 /data/app/ 相关
[ 14.186668] <0>.(0)[1:init]init 16: [14155][0]ccz ParseMkdir encryption policy on: /data/app-lib [ 14.187866] <0>.(0)[1:init]init 16: [14155][0]ccz ParseMkdir encryption optname: encryption [ 14.189007] <0>.(0)[1:init]init 19: [14155][0]ccz ParseMkdir encryption optval: Require [ 14.191729] <0>.(0)[1:init]init 19: [14155][0]Encryption policy of /data/app-lib set to ef2067add1858706a84cc01d25260ea5 v2 modes 1/4 flags 0x2 [ 14.193467] <0>.(0)[1:init]init 19: [14162][0]ccz ParseMkdir encryption policy on: /data/app [ 14.194557] <0>.(0)[1:init]init 19: [14162][0]ccz ParseMkdir encryption optname: encryption [ 14.195651] <0>.(0)[1:init]init 19: [14162][0]ccz ParseMkdir encryption optval: None [ 14.196637] <0>.(0)[1:init]init 19: [14162][0]ccz ParseMkdir encryption hook: [ 14.197555] <0>.(0)[1:init]init 19: [14162][0]Not setting encryption policy on: /data/app [ 14.198574] <5>.(5)[317:init]init 16: [14167][200]ReapLogT PropSet [apexd.status]=[starting]13967 Done [ 14.198737] <0>.(0)[1:init]init 19: [14167][0]ccz ParseMkdir encryption policy on: /data/property [ 14.200913] <0>.(0)[1:init]init 19: [14167][0]ccz ParseMkdir encryption optname: encryption [ 14.201996] <0>.(0)[1:init]init 25: [14167][0]ccz ParseMkdir encryption optval: Require [ 14.204488] <0>.(0)[1:init]init 25: [14167][0]Encryption policy of /data/property set to ef2067add1858706a84cc01d25260ea5 v2 modes 1/4 flags 0x2 [ 14.206220] <0>.(0)[1:init]init 25: [14175][0]ccz ParseMkdir encryption policy on: /data/tombstones [ 14.207437] <0>.(0)[1:init]init 25: [14175][0]ccz ParseMkdir encryption optname: encryption [ 14.208516] <0>.(0)[1:init]init 25: [14175][0]ccz ParseMkdir encryption optval: Require [ 14.211116] <0>.(0)[1:init]init 25: [14175][0]Encryption policy of /data/tombstones set to ef2067add1858706a84cc01d25260ea5 v2 modes 1/4 flags 0x2 [ 14.212936] <0>.(0)[1:init]init 25: [14181][0]ccz ParseMkdir encryption policy on: /data/vendor/tombstones [ 14.215671] <0>.(0)[1:init]init 25: [14184][0]ccz ParseMkdir encryption policy on: /data/vendor/tombstones/wifi
关于 init.rc 启动可以参考下面