Loading init/builtins.cpp +68 −25 Original line number Diff line number Diff line Loading @@ -360,57 +360,61 @@ static Result<void> do_interface_stop(const BuiltinArguments& args) { return {}; } // mkdir <path> [mode] [owner] [group] [<option> ...] static Result<void> do_mkdir(const BuiltinArguments& args) { auto options = ParseMkdir(args.args); if (!options) return options.error(); static Result<void> make_dir_with_options(const MkdirOptions& options) { std::string ref_basename; if (options->ref_option == "ref") { if (options.ref_option == "ref") { ref_basename = fscrypt_key_ref; } else if (options->ref_option == "per_boot_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 << "'"; return Error() << "Unknown key option: '" << options.ref_option << "'"; } struct stat mstat; if (lstat(options->target.c_str(), &mstat) != 0) { if (lstat(options.target.c_str(), &mstat) != 0) { if (errno != ENOENT) { return ErrnoError() << "lstat() failed on " << options->target; return ErrnoError() << "lstat() failed on " << options.target; } if (!make_dir(options->target, options->mode)) { return ErrnoErrorIgnoreEnoent() << "mkdir() 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 (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; 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; 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 (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)) { if (!FscryptSetDirectoryPolicy(ref_basename, options.fscrypt_action, options.target)) { return reboot_into_recovery( {"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + options->target}); {"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + options.target}); } } return {}; } // mkdir <path> [mode] [owner] [group] [<option> ...] static Result<void> do_mkdir(const BuiltinArguments& args) { auto options = ParseMkdir(args.args); if (!options) return options.error(); return make_dir_with_options(*options); } /* umount <path> */ static Result<void> do_umount(const BuiltinArguments& args) { if (umount(args[1].c_str()) < 0) { Loading Loading @@ -1172,7 +1176,7 @@ static Result<void> do_mark_post_data(const BuiltinArguments& args) { return {}; } static Result<void> do_parse_apex_configs(const BuiltinArguments& args) { static Result<void> parse_apex_configs() { glob_t glob_result; static constexpr char glob_pattern[] = "/apex/*/etc/*.rc"; const int ret = glob(glob_pattern, GLOB_MARK, nullptr, &glob_result); Loading Loading @@ -1211,6 +1215,45 @@ static Result<void> do_parse_apex_configs(const BuiltinArguments& args) { } } /* * Creates a directory under /data/misc/apexdata/ for each APEX. */ static Result<void> create_apex_data_dirs() { auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir("/apex"), closedir); if (!dirp) { return ErrnoError() << "Unable to open apex directory"; } struct dirent* entry; while ((entry = readdir(dirp.get())) != nullptr) { if (entry->d_type != DT_DIR) continue; const char* name = entry->d_name; // skip any starting with "." if (name[0] == '.') continue; if (strchr(name, '@') != nullptr) continue; auto path = "/data/misc/apexdata/" + std::string(name); auto system_uid = DecodeUid("system"); auto options = MkdirOptions{path, 0700, *system_uid, *system_uid, FscryptAction::kNone, "ref"}; make_dir_with_options(options); } return {}; } static Result<void> do_perform_apex_config(const BuiltinArguments& args) { auto create_dirs = create_apex_data_dirs(); if (!create_dirs) { return create_dirs.error(); } auto parse_configs = parse_apex_configs(); if (!parse_configs) { return parse_configs.error(); } return {}; } static Result<void> do_enter_default_mount_ns(const BuiltinArguments& args) { if (SwitchToDefaultMountNamespace()) { return {}; Loading Loading @@ -1271,7 +1314,7 @@ const BuiltinFunctionMap& GetBuiltinFunctionMap() { // mount and umount are run in the same context as mount_all for symmetry. {"mount_all", {1, kMax, {false, do_mount_all}}}, {"mount", {3, kMax, {false, do_mount}}}, {"parse_apex_configs", {0, 0, {false, do_parse_apex_configs}}}, {"perform_apex_config", {0, 0, {false, do_perform_apex_config}}}, {"umount", {1, 1, {false, do_umount}}}, {"umount_all", {1, 1, {false, do_umount_all}}}, {"readahead", {1, 2, {true, do_readahead}}}, Loading rootdir/init.rc +4 −1 Original line number Diff line number Diff line Loading @@ -579,6 +579,8 @@ on post-fs-data mkdir /data/misc/profman 0770 system shell mkdir /data/misc/gcov 0770 root root mkdir /data/misc/installd 0700 root root mkdir /data/misc/apexdata 0700 root root mkdir /data/misc/apexrollback 0700 root root mkdir /data/preloads 0775 system system encryption=None Loading Loading @@ -668,7 +670,8 @@ on post-fs-data # Wait for apexd to finish activating APEXes before starting more processes. wait_for_prop apexd.status ready parse_apex_configs perform_apex_config exec_start derive_sdk init_user0 Loading Loading
init/builtins.cpp +68 −25 Original line number Diff line number Diff line Loading @@ -360,57 +360,61 @@ static Result<void> do_interface_stop(const BuiltinArguments& args) { return {}; } // mkdir <path> [mode] [owner] [group] [<option> ...] static Result<void> do_mkdir(const BuiltinArguments& args) { auto options = ParseMkdir(args.args); if (!options) return options.error(); static Result<void> make_dir_with_options(const MkdirOptions& options) { std::string ref_basename; if (options->ref_option == "ref") { if (options.ref_option == "ref") { ref_basename = fscrypt_key_ref; } else if (options->ref_option == "per_boot_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 << "'"; return Error() << "Unknown key option: '" << options.ref_option << "'"; } struct stat mstat; if (lstat(options->target.c_str(), &mstat) != 0) { if (lstat(options.target.c_str(), &mstat) != 0) { if (errno != ENOENT) { return ErrnoError() << "lstat() failed on " << options->target; return ErrnoError() << "lstat() failed on " << options.target; } if (!make_dir(options->target, options->mode)) { return ErrnoErrorIgnoreEnoent() << "mkdir() 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 (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; 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; 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 (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)) { if (!FscryptSetDirectoryPolicy(ref_basename, options.fscrypt_action, options.target)) { return reboot_into_recovery( {"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + options->target}); {"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + options.target}); } } return {}; } // mkdir <path> [mode] [owner] [group] [<option> ...] static Result<void> do_mkdir(const BuiltinArguments& args) { auto options = ParseMkdir(args.args); if (!options) return options.error(); return make_dir_with_options(*options); } /* umount <path> */ static Result<void> do_umount(const BuiltinArguments& args) { if (umount(args[1].c_str()) < 0) { Loading Loading @@ -1172,7 +1176,7 @@ static Result<void> do_mark_post_data(const BuiltinArguments& args) { return {}; } static Result<void> do_parse_apex_configs(const BuiltinArguments& args) { static Result<void> parse_apex_configs() { glob_t glob_result; static constexpr char glob_pattern[] = "/apex/*/etc/*.rc"; const int ret = glob(glob_pattern, GLOB_MARK, nullptr, &glob_result); Loading Loading @@ -1211,6 +1215,45 @@ static Result<void> do_parse_apex_configs(const BuiltinArguments& args) { } } /* * Creates a directory under /data/misc/apexdata/ for each APEX. */ static Result<void> create_apex_data_dirs() { auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir("/apex"), closedir); if (!dirp) { return ErrnoError() << "Unable to open apex directory"; } struct dirent* entry; while ((entry = readdir(dirp.get())) != nullptr) { if (entry->d_type != DT_DIR) continue; const char* name = entry->d_name; // skip any starting with "." if (name[0] == '.') continue; if (strchr(name, '@') != nullptr) continue; auto path = "/data/misc/apexdata/" + std::string(name); auto system_uid = DecodeUid("system"); auto options = MkdirOptions{path, 0700, *system_uid, *system_uid, FscryptAction::kNone, "ref"}; make_dir_with_options(options); } return {}; } static Result<void> do_perform_apex_config(const BuiltinArguments& args) { auto create_dirs = create_apex_data_dirs(); if (!create_dirs) { return create_dirs.error(); } auto parse_configs = parse_apex_configs(); if (!parse_configs) { return parse_configs.error(); } return {}; } static Result<void> do_enter_default_mount_ns(const BuiltinArguments& args) { if (SwitchToDefaultMountNamespace()) { return {}; Loading Loading @@ -1271,7 +1314,7 @@ const BuiltinFunctionMap& GetBuiltinFunctionMap() { // mount and umount are run in the same context as mount_all for symmetry. {"mount_all", {1, kMax, {false, do_mount_all}}}, {"mount", {3, kMax, {false, do_mount}}}, {"parse_apex_configs", {0, 0, {false, do_parse_apex_configs}}}, {"perform_apex_config", {0, 0, {false, do_perform_apex_config}}}, {"umount", {1, 1, {false, do_umount}}}, {"umount_all", {1, 1, {false, do_umount_all}}}, {"readahead", {1, 2, {true, do_readahead}}}, Loading
rootdir/init.rc +4 −1 Original line number Diff line number Diff line Loading @@ -579,6 +579,8 @@ on post-fs-data mkdir /data/misc/profman 0770 system shell mkdir /data/misc/gcov 0770 root root mkdir /data/misc/installd 0700 root root mkdir /data/misc/apexdata 0700 root root mkdir /data/misc/apexrollback 0700 root root mkdir /data/preloads 0775 system system encryption=None Loading Loading @@ -668,7 +670,8 @@ on post-fs-data # Wait for apexd to finish activating APEXes before starting more processes. wait_for_prop apexd.status ready parse_apex_configs perform_apex_config exec_start derive_sdk init_user0 Loading