summaryrefslogtreecommitdiff
path: root/init/builtins.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'init/builtins.cpp')
-rw-r--r--init/builtins.cpp166
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}}},