diff options
Diffstat (limited to 'init/builtins.cpp')
-rw-r--r-- | init/builtins.cpp | 166 |
1 files changed, 104 insertions, 62 deletions
diff --git a/init/builtins.cpp b/init/builtins.cpp index 01db4f5da..035038f32 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -28,7 +28,6 @@ #include <net/if.h> #include <sched.h> #include <signal.h> -#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -43,9 +42,9 @@ #include <sys/wait.h> #include <unistd.h> -#include <map> #include <memory> +#include <ApexProperties.sysprop.h> #include <InitProperties.sysprop.h> #include <android-base/chrono_utils.h> #include <android-base/file.h> @@ -88,7 +87,6 @@ using namespace std::literals::string_literals; using android::base::Basename; -using android::base::ResultError; using android::base::SetProperty; using android::base::Split; using android::base::StartsWith; @@ -117,7 +115,7 @@ class ErrorIgnoreEnoent { android::base::GetMinimumLogSeverity() > android::base::DEBUG) {} template <typename T> - operator android::base::expected<T, ResultError<android::base::Errno>>() { + operator android::base::expected<T, ResultError>() { if (ignore_error_) { return {}; } @@ -131,7 +129,7 @@ class ErrorIgnoreEnoent { } private: - Error<> error_; + Error error_; bool ignore_error_; }; @@ -177,6 +175,28 @@ static Result<void> do_class_start(const BuiltinArguments& args) { return {}; } +static Result<void> do_class_start_post_data(const BuiltinArguments& args) { + if (args.context != kInitContext) { + return Error() << "command 'class_start_post_data' only available in init context"; + } + static bool is_apex_updatable = android::sysprop::ApexProperties::updatable().value_or(false); + + if (!is_apex_updatable) { + // No need to start these on devices that don't support APEX, since they're not + // stopped either. + return {}; + } + for (const auto& service : ServiceList::GetInstance()) { + if (service->classnames().count(args[1])) { + if (auto result = service->StartIfPostData(); !result.ok()) { + LOG(ERROR) << "Could not start service '" << service->name() + << "' as part of class '" << args[1] << "': " << result.error(); + } + } + } + return {}; +} + static Result<void> do_class_stop(const BuiltinArguments& args) { ForEachServiceInClass(args[1], &Service::Stop); return {}; @@ -187,35 +207,24 @@ static Result<void> do_class_reset(const BuiltinArguments& args) { return {}; } +static Result<void> do_class_reset_post_data(const BuiltinArguments& args) { + if (args.context != kInitContext) { + return Error() << "command 'class_reset_post_data' only available in init context"; + } + static bool is_apex_updatable = android::sysprop::ApexProperties::updatable().value_or(false); + if (!is_apex_updatable) { + // No need to stop these on devices that don't support APEX. + return {}; + } + ForEachServiceInClass(args[1], &Service::ResetIfPostData); + return {}; +} + static Result<void> do_class_restart(const BuiltinArguments& args) { // Do not restart a class if it has a property persist.dont_start_class.CLASS set to 1. if (android::base::GetBoolProperty("persist.init.dont_start_class." + args[1], false)) return {}; - - std::string classname; - - CHECK(args.size() == 2 || args.size() == 3); - - bool only_enabled = false; - if (args.size() == 3) { - if (args[1] != "--only-enabled") { - return Error() << "Unexpected argument: " << args[1]; - } - only_enabled = true; - classname = args[2]; - } else if (args.size() == 2) { - classname = args[1]; - } - - for (const auto& service : ServiceList::GetInstance()) { - if (!service->classnames().count(classname)) { - continue; - } - if (only_enabled && !service->IsEnabled()) { - continue; - } - service->Restart(); - } + ForEachServiceInClass(args[1], &Service::Restart); return {}; } @@ -575,7 +584,32 @@ static void import_late(const std::vector<std::string>& rc_paths) { * return code is processed based on input code */ static Result<void> queue_fs_event(int code, bool userdata_remount) { - if (code == FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) { + if (code == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) { + if (userdata_remount) { + // FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION should only happen on FDE devices. Since we don't + // support userdata remount on FDE devices, this should never been triggered. Time to + // panic! + LOG(ERROR) << "Userdata remount is not supported on FDE devices. How did you get here?"; + trigger_shutdown("reboot,requested-userdata-remount-on-fde-device"); + } + ActionManager::GetInstance().QueueEventTrigger("encrypt"); + return {}; + } else if (code == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) { + if (userdata_remount) { + // FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED should only happen on FDE devices. Since we + // don't support userdata remount on FDE devices, this should never been triggered. + // Time to panic! + LOG(ERROR) << "Userdata remount is not supported on FDE devices. How did you get here?"; + trigger_shutdown("reboot,requested-userdata-remount-on-fde-device"); + } + SetProperty("ro.crypto.state", "encrypted"); + ActionManager::GetInstance().QueueEventTrigger("defaultcrypto"); + return {}; + } else if (code == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { + SetProperty("ro.crypto.state", "unencrypted"); + ActionManager::GetInstance().QueueEventTrigger("nonencrypted"); + return {}; + } else if (code == FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) { SetProperty("ro.crypto.state", "unsupported"); ActionManager::GetInstance().QueueEventTrigger("nonencrypted"); return {}; @@ -775,21 +809,8 @@ static Result<void> do_stop(const BuiltinArguments& args) { } static Result<void> do_restart(const BuiltinArguments& args) { - bool only_if_running = false; - if (args.size() == 3) { - if (args[1] == "--only-if-running") { - only_if_running = true; - } else { - return Error() << "Unknown argument to restart: " << args[1]; - } - } - - const auto& classname = args[args.size() - 1]; - Service* svc = ServiceList::GetInstance().FindService(classname); - if (!svc) return Error() << "service " << classname << " not found"; - if (only_if_running && !svc->IsRunning()) { - return {}; - } + Service* svc = ServiceList::GetInstance().FindService(args[1]); + if (!svc) return Error() << "service " << args[1] << " not found"; svc->Restart(); return {}; } @@ -873,11 +894,9 @@ static Result<void> do_verity_update_state(const BuiltinArguments& args) { std::string partition = entry.mount_point == "/" ? "system" : Basename(entry.mount_point); SetProperty("partition." + partition + ".verified", std::to_string(mode)); - auto hashtree_info = fs_mgr_get_hashtree_info(entry); - if (hashtree_info) { - SetProperty("partition." + partition + ".verified.hash_alg", hashtree_info->algorithm); - SetProperty("partition." + partition + ".verified.root_digest", - hashtree_info->root_digest); + std::string hash_alg = fs_mgr_get_hashtree_algorithm(entry); + if (!hash_alg.empty()) { + SetProperty("partition." + partition + ".verified.hash_alg", hash_alg); } } @@ -1096,6 +1115,17 @@ static Result<void> do_loglevel(const BuiltinArguments& args) { } static Result<void> do_load_persist_props(const BuiltinArguments& args) { + // Devices with FDE have load_persist_props called twice; the first time when the temporary + // /data partition is mounted and then again once /data is truly mounted. We do not want to + // read persistent properties from the temporary /data partition or mark persistent properties + // as having been loaded during the first call, so we return in that case. + std::string crypto_state = android::base::GetProperty("ro.crypto.state", ""); + std::string crypto_type = android::base::GetProperty("ro.crypto.type", ""); + if (crypto_state == "encrypted" && crypto_type == "block") { + static size_t num_calls = 0; + if (++num_calls == 1) return {}; + } + SendLoadPersistentPropertiesMessage(); start_waiting_for_property("ro.persistent_properties.ready", "true"); @@ -1275,13 +1305,25 @@ static Result<void> MountLinkerConfigForDefaultNamespace() { return {}; } + +static bool IsApexUpdatable() { + static bool updatable = android::sysprop::ApexProperties::updatable().value_or(false); + return updatable; +} + static Result<void> do_update_linker_config(const BuiltinArguments&) { - return GenerateLinkerConfiguration(); + // If APEX is not updatable, then all APEX information are already included in the first + // linker config generation, so there is no need to update linker configuration again. + if (IsApexUpdatable()) { + return GenerateLinkerConfiguration(); + } + + return {}; } static Result<void> parse_apex_configs() { glob_t glob_result; - static constexpr char glob_pattern[] = "/apex/*/etc/*rc"; + static constexpr char glob_pattern[] = "/apex/*/etc/*.rc"; const int ret = glob(glob_pattern, GLOB_MARK, nullptr, &glob_result); if (ret != 0 && ret != GLOB_NOMATCH) { globfree(&glob_result); @@ -1298,18 +1340,16 @@ static Result<void> parse_apex_configs() { if (paths.size() >= 3 && paths[2].find('@') != std::string::npos) { continue; } - // Filter directories - if (path.back() == '/') { - continue; - } configs.push_back(path); } globfree(&glob_result); - int active_sdk = android::base::GetIntProperty("ro.build.version.sdk", INT_MAX); - bool success = true; - for (const auto& c : parser.FilterVersionedConfigs(configs, active_sdk)) { + for (const auto& c : configs) { + if (c.back() == '/') { + // skip if directory + continue; + } success &= parser.ParseConfigFile(c); } ServiceList::GetInstance().MarkServicesUpdate(); @@ -1383,8 +1423,10 @@ const BuiltinFunctionMap& GetBuiltinFunctionMap() { {"chmod", {2, 2, {true, do_chmod}}}, {"chown", {2, 3, {true, do_chown}}}, {"class_reset", {1, 1, {false, do_class_reset}}}, - {"class_restart", {1, 2, {false, do_class_restart}}}, + {"class_reset_post_data", {1, 1, {false, do_class_reset_post_data}}}, + {"class_restart", {1, 1, {false, do_class_restart}}}, {"class_start", {1, 1, {false, do_class_start}}}, + {"class_start_post_data", {1, 1, {false, do_class_start_post_data}}}, {"class_stop", {1, 1, {false, do_class_stop}}}, {"copy", {2, 2, {true, do_copy}}}, {"copy_per_line", {2, 2, {true, do_copy_per_line}}}, @@ -1420,7 +1462,7 @@ const BuiltinFunctionMap& GetBuiltinFunctionMap() { {"update_linker_config", {0, 0, {false, do_update_linker_config}}}, {"readahead", {1, 2, {true, do_readahead}}}, {"remount_userdata", {0, 0, {false, do_remount_userdata}}}, - {"restart", {1, 2, {false, do_restart}}}, + {"restart", {1, 1, {false, do_restart}}}, {"restorecon", {1, kMax, {true, do_restorecon}}}, {"restorecon_recursive", {1, kMax, {true, do_restorecon_recursive}}}, {"rm", {1, 1, {true, do_rm}}}, |