diff options
author | Oli Lan <olilan@google.com> | 2019-11-19 18:08:45 +0000 |
---|---|---|
committer | Oli Lan <olilan@google.com> | 2019-12-09 11:10:42 +0000 |
commit | 13e51e7f0bc0419ad5463037bbe87f3789fdf9f9 (patch) | |
tree | 938c4dfa38b270d0bf453ec16fd0ea4b95ab9654 /init/builtins.cpp | |
parent | 1fd9c5568999d333630225071801f3e6bb905d7e (diff) |
Create DE_sys APEX data directories.
This creates the directory /data/misc/apexdata, at the same time as other
directories under /data/misc. Then, when apexd has finished activating
APEXes, a directory is created under /data/misc/apexdata for every
APEX, with the same name as the APEX module name.
See go/apex-data-directories.
APEXes are discovered by scanning the /apex directory. It may be better
to delegate this process to a library, but it is proposed to defer that
change to a future CL.
Bug: 141148175
Test: Built and flashed, checked directories were created.
Change-Id: I639d6f490ae0b97f116ce38ff3ac348bd73aa20e
Diffstat (limited to 'init/builtins.cpp')
-rw-r--r-- | init/builtins.cpp | 93 |
1 files changed, 68 insertions, 25 deletions
diff --git a/init/builtins.cpp b/init/builtins.cpp index 6bf399778..62a19abc5 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -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) { @@ -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); @@ -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 {}; @@ -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}}}, |