summaryrefslogtreecommitdiff
path: root/init/builtins.cpp
diff options
context:
space:
mode:
authorMartijn Coenen <maco@google.com>2019-04-23 16:26:01 +0200
committerMartijn Coenen <maco@google.com>2019-04-26 11:54:19 +0200
commitf0bc58a42dff06213b60676c034b0d345e2b5344 (patch)
tree74441d9e95e383c0d78c2d54b4d5c7116ebc7ec3 /init/builtins.cpp
parenta04e48dbec87730af840b3df2b459c03b87479e8 (diff)
Support for stopping/starting post-data-mount class subsets.
On devices that use FDE and APEX at the same time, we need to bring up a minimal framework to be able to mount the /data partition. During this period, a tmpfs /data filesystem is created, which doesn't contain any of the updated APEXEs. As a consequence, all those processes will be using the APEXes from the /system partition. This is obviously not desired, as APEXes in /system may be old and/or contain security issues. Additionally, it would create a difference between FBE and FDE devices at runtime. Ideally, we restart all processes that have started after we created the tmpfs /data. We can't (re)start based on class names alone, because some classes (eg 'hal') contain services that are required to start apexd itself and that shouldn't be killed (eg the graphics HAL). To address this, keep track of which processes are started after /data is mounted, with a new 'mark_post_data' keyword. Additionally, create 'class_reset_post_data', which resets all services in the class that were created after the initial /data mount, and 'class_start_post_data', which starts all services in the class that were started after /data was mounted. On a device with FBE, these keywords wouldn't be used; on a device with FDE, we'd use them to bring down the right processes after the user has entered the correct secret, and restart them. Bug: 118485723 Test: manually verified process list Change-Id: I16adb776dacf1dd1feeaff9e60639b99899905eb
Diffstat (limited to 'init/builtins.cpp')
-rw-r--r--init/builtins.cpp39
1 files changed, 35 insertions, 4 deletions
diff --git a/init/builtins.cpp b/init/builtins.cpp
index fc75072b6..34f229b7f 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -104,23 +104,37 @@ static void ForEachServiceInClass(const std::string& classname, F function) {
}
}
-static Result<Success> do_class_start(const BuiltinArguments& args) {
+static Result<Success> class_start(const std::string& class_name, bool post_data_only) {
// Do not start 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))
+ if (android::base::GetBoolProperty("persist.init.dont_start_class." + class_name, false))
return Success();
// Starting a class does not start services which are explicitly disabled.
// They must be started individually.
for (const auto& service : ServiceList::GetInstance()) {
- if (service->classnames().count(args[1])) {
+ if (service->classnames().count(class_name)) {
+ if (post_data_only && !service->is_post_data()) {
+ continue;
+ }
if (auto result = service->StartIfNotDisabled(); !result) {
LOG(ERROR) << "Could not start service '" << service->name()
- << "' as part of class '" << args[1] << "': " << result.error();
+ << "' as part of class '" << class_name << "': " << result.error();
}
}
}
return Success();
}
+static Result<Success> do_class_start(const BuiltinArguments& args) {
+ return class_start(args[1], false /* post_data_only */);
+}
+
+static Result<Success> do_class_start_post_data(const BuiltinArguments& args) {
+ if (args.context != kInitContext) {
+ return Error() << "command 'class_start_post_data' only available in init context";
+ }
+ return class_start(args[1], true /* post_data_only */);
+}
+
static Result<Success> do_class_stop(const BuiltinArguments& args) {
ForEachServiceInClass(args[1], &Service::Stop);
return Success();
@@ -131,6 +145,14 @@ static Result<Success> do_class_reset(const BuiltinArguments& args) {
return Success();
}
+static Result<Success> do_class_reset_post_data(const BuiltinArguments& args) {
+ if (args.context != kInitContext) {
+ return Error() << "command 'class_reset_post_data' only available in init context";
+ }
+ ForEachServiceInClass(args[1], &Service::ResetIfPostData);
+ return Success();
+}
+
static Result<Success> 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))
@@ -1119,6 +1141,12 @@ static Result<Success> do_init_user0(const BuiltinArguments& args) {
{{"exec", "/system/bin/vdc", "--wait", "cryptfs", "init_user0"}, args.context});
}
+static Result<Success> do_mark_post_data(const BuiltinArguments& args) {
+ ServiceList::GetInstance().MarkPostData();
+
+ return Success();
+}
+
static Result<Success> do_parse_apex_configs(const BuiltinArguments& args) {
glob_t glob_result;
// @ is added to filter out the later paths, which are bind mounts of the places
@@ -1170,8 +1198,10 @@ const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
{"chmod", {2, 2, {true, do_chmod}}},
{"chown", {2, 3, {true, do_chown}}},
{"class_reset", {1, 1, {false, do_class_reset}}},
+ {"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}}},
{"domainname", {1, 1, {true, do_domainname}}},
@@ -1191,6 +1221,7 @@ const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
{"load_persist_props", {0, 0, {false, do_load_persist_props}}},
{"load_system_props", {0, 0, {false, do_load_system_props}}},
{"loglevel", {1, 1, {false, do_loglevel}}},
+ {"mark_post_data", {0, 0, {false, do_mark_post_data}}},
{"mkdir", {1, 4, {true, do_mkdir}}},
// TODO: Do mount operations in vendor_init.
// mount_all is currently too complex to run in vendor_init as it queues action triggers,