Changes to init to support encrypted filesystems.
These are the changes to init and init.rc necessary to
support booting with and encrypted /data filesystem.
A corresponding change to init.<device>.rc goes along
with this change.
Change-Id: I0c7e2cc39568358014a82e317735c0eae14dd683
diff --git a/init/builtins.c b/init/builtins.c
index 4326ebc..8b2e4aa 100644
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -162,6 +162,12 @@
return 0;
}
+int do_class_reset(int nargs, char **args)
+{
+ service_for_each_class(args[1], service_reset);
+ return 0;
+}
+
int do_domainname(int nargs, char **args)
{
return write_file("/proc/sys/kernel/domainname", args[1]);
@@ -269,6 +275,8 @@
{ 0, 0 },
};
+#define DATA_MNT_POINT "/data"
+
/* mount <type> <device> <path> <flags ...> <options> */
int do_mount(int nargs, char **args)
{
@@ -359,9 +367,51 @@
if (wait)
wait_for_file(source, COMMAND_RETRY_TIMEOUT);
if (mount(source, target, system, flags, options) < 0) {
- return -1;
+ /* If this fails, it may be an encrypted filesystem.
+ * We only support encrypting /data. Check
+ * if we're trying to mount it, and if so,
+ * assume it's encrypted, mount a tmpfs instead.
+ * Then save the orig mount parms in properties
+ * for vold to query when it mounts the real
+ * encrypted /data.
+ */
+ if (!strcmp(target, DATA_MNT_POINT)) {
+ const char *tmpfs_options;
+
+ tmpfs_options = property_get("ro.crypto.tmpfs_options");
+
+ if (mount("tmpfs", target, "tmpfs", MS_NOATIME | MS_NOSUID | MS_NODEV,
+ tmpfs_options) < 0) {
+ return -1;
+ }
+
+ /* Set the property that triggers the framework to do a minimal
+ * startup and ask the user for a password
+ */
+ property_set("vold.decrypt", "1");
+ } else {
+ return -1;
+ }
+ } else {
+ if (!strcmp(target, DATA_MNT_POINT)) {
+ /* We succeeded in mounting /data, so it's not encrypted */
+ action_for_each_trigger("nonencrypted", action_add_queue_tail);
+ }
}
+ if (!strcmp(target, DATA_MNT_POINT)) {
+ char fs_flags[32];
+
+ /* Save the original mount options */
+ property_set("ro.crypto.fs_type", system);
+ property_set("ro.crypto.fs_real_blkdev", source);
+ property_set("ro.crypto.fs_mnt_point", target);
+ if (options) {
+ property_set("ro.crypto.fs_options", options);
+ }
+ snprintf(fs_flags, sizeof(fs_flags), "0x%8.8x", flags);
+ property_set("ro.crypto.fs_flags", fs_flags);
+ }
return 0;
}
}
diff --git a/init/init.c b/init/init.c
index 7aef387..e13d4b1 100755
--- a/init/init.c
+++ b/init/init.c
@@ -150,11 +150,11 @@
int needs_console;
int n;
- /* starting a service removes it from the disabled
+ /* starting a service removes it from the disabled or reset
* state and immediately takes it out of the restarting
* state if it was in there
*/
- svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING));
+ svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET));
svc->time_started = 0;
/* running processes require no additional work -- if
@@ -300,27 +300,42 @@
notify_service_state(svc->name, "running");
}
-void service_stop(struct service *svc)
+/* The how field should be either SVC_DISABLED or SVC_RESET */
+static void service_stop_or_reset(struct service *svc, int how)
{
/* we are no longer running, nor should we
* attempt to restart
*/
svc->flags &= (~(SVC_RUNNING|SVC_RESTARTING));
+ if ((how != SVC_DISABLED) && (how != SVC_RESET)) {
+ /* Hrm, an illegal flag. Default to SVC_DISABLED */
+ how = SVC_DISABLED;
+ }
/* if the service has not yet started, prevent
* it from auto-starting with its class
*/
- svc->flags |= SVC_DISABLED;
+ svc->flags |= how;
if (svc->pid) {
NOTICE("service '%s' is being killed\n", svc->name);
- kill(-svc->pid, SIGTERM);
+ kill(-svc->pid, SIGKILL);
notify_service_state(svc->name, "stopping");
} else {
notify_service_state(svc->name, "stopped");
}
}
+void service_reset(struct service *svc)
+{
+ service_stop_or_reset(svc, SVC_RESET);
+}
+
+void service_stop(struct service *svc)
+{
+ service_stop_or_reset(svc, SVC_DISABLED);
+}
+
void property_changed(const char *name, const char *value)
{
if (property_triggers_enabled)
@@ -725,6 +740,7 @@
action_for_each_trigger("early-fs", action_add_queue_tail);
action_for_each_trigger("fs", action_add_queue_tail);
action_for_each_trigger("post-fs", action_add_queue_tail);
+ action_for_each_trigger("post-fs-data", action_add_queue_tail);
queue_builtin_action(property_service_init_action, "property_service_init");
queue_builtin_action(signal_init_action, "signal_init");
diff --git a/init/init.h b/init/init.h
index 8691335..05cdfaa 100644
--- a/init/init.h
+++ b/init/init.h
@@ -69,6 +69,8 @@
#define SVC_RESTARTING 0x08 /* waiting to restart */
#define SVC_CONSOLE 0x10 /* requires console */
#define SVC_CRITICAL 0x20 /* will reboot into recovery if keeps crashing */
+#define SVC_RESET 0x40 /* Use when stopping a process, but not disabling
+ so it can be restarted with its class */
#define NR_SVC_SUPP_GIDS 12 /* twelve supplementary groups */
@@ -121,6 +123,7 @@
void service_for_each_flags(unsigned matchflags,
void (*func)(struct service *svc));
void service_stop(struct service *svc);
+void service_reset(struct service *svc);
void service_start(struct service *svc, const char *dynamic_args);
void property_changed(const char *name, const char *value);
diff --git a/init/init_parser.c b/init/init_parser.c
index d136c28..7ac1a1e 100644
--- a/init/init_parser.c
+++ b/init/init_parser.c
@@ -82,6 +82,7 @@
if (!strcmp(s, "lass")) return K_class;
if (!strcmp(s, "lass_start")) return K_class_start;
if (!strcmp(s, "lass_stop")) return K_class_stop;
+ if (!strcmp(s, "lass_reset")) return K_class_reset;
if (!strcmp(s, "onsole")) return K_console;
if (!strcmp(s, "hown")) return K_chown;
if (!strcmp(s, "hmod")) return K_chmod;
diff --git a/init/keywords.h b/init/keywords.h
index 25315d8..d15ad49 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -4,6 +4,7 @@
int do_chdir(int nargs, char **args);
int do_class_start(int nargs, char **args);
int do_class_stop(int nargs, char **args);
+int do_class_reset(int nargs, char **args);
int do_domainname(int nargs, char **args);
int do_exec(int nargs, char **args);
int do_export(int nargs, char **args);
@@ -39,6 +40,7 @@
KEYWORD(class, OPTION, 0, 0)
KEYWORD(class_start, COMMAND, 1, do_class_start)
KEYWORD(class_stop, COMMAND, 1, do_class_stop)
+ KEYWORD(class_reset, COMMAND, 1, do_class_reset)
KEYWORD(console, OPTION, 0, 0)
KEYWORD(critical, OPTION, 0, 0)
KEYWORD(disabled, OPTION, 0, 0)
diff --git a/init/signal_handler.c b/init/signal_handler.c
index 3e5d136..833e59d 100644
--- a/init/signal_handler.c
+++ b/init/signal_handler.c
@@ -83,8 +83,8 @@
svc->flags |= SVC_DISABLED;
}
- /* disabled processes do not get restarted automatically */
- if (svc->flags & SVC_DISABLED) {
+ /* disabled and reset processes do not get restarted automatically */
+ if (svc->flags & (SVC_DISABLED | SVC_RESET) ) {
notify_service_state(svc->name, "stopped");
return 0;
}